Esempio n. 1
0
File: adm.c Progetto: brnrc/ion-dtn
void adm_destroy()
{
   LystElt elt = 0;

   for (elt = lyst_first(gAdmData); elt; elt = lyst_next(elt))
   {
	   adm_datadef_t *cur = (adm_datadef_t *) lyst_data(elt);
	   mid_release(cur->mid);
	   MRELEASE(cur);
   }
   lyst_destroy(gAdmData);
   gAdmData = NULL;

   for (elt = lyst_first(gAdmCtrls); elt; elt = lyst_next(elt))
   {
	   adm_ctrl_t *cur = (adm_ctrl_t *) lyst_data(elt);
	   mid_release(cur->mid);
	   MRELEASE(cur);
   }
   lyst_destroy(gAdmCtrls);
   gAdmCtrls = NULL;

   lyst_destroy(gAdmLiterals);
   gAdmLiterals = NULL;

   lyst_destroy(gAdmOps);
   gAdmOps = NULL;

}
Esempio n. 2
0
void rpt_release_data_entry(rpt_data_entry_t *entry)
{
	if(entry != NULL)
	{
		MRELEASE(entry->contents);
		mid_release(entry->id);
		MRELEASE(entry);
	}

}
Esempio n. 3
0
int	ltpei_parse_extension(char **cursor, int *bytesRemaining, Lyst exts,
		unsigned int *extensionOffset)
{
	char			*initialCursor;
	LtpExtensionInbound	*extField;
	unsigned int		valueLength;

	CHKERR(cursor);
	CHKERR(*cursor);
	CHKERR(bytesRemaining);
	CHKERR(exts);
	if ((*bytesRemaining) < 1)
	{
		return 0;	/*	Corrupt.			*/
	}

	extField = MTAKE(sizeof(LtpExtensionInbound));
	if (extField == NULL)
	{
		return -1;	/*	Give up.			*/
	}

	initialCursor = *cursor;
	extField->offset = *extensionOffset;
	extField->tag = **cursor;
	(*cursor)++;
	(*bytesRemaining)--;
	extractSmallSdnv(&valueLength, cursor, bytesRemaining);
	if (valueLength == 0 || *bytesRemaining < valueLength)
	{
		return 0;	/*	Corrupt.			*/
	}

	extField->length = valueLength;
	extField->value = MTAKE(valueLength);
	if (extField->value == 0)
	{
		MRELEASE(extField);
		return -1;	/*	Give up.			*/
	}

	memcpy(extField->value, *cursor, valueLength);
	(*cursor) += valueLength;
	(*bytesRemaining) -= valueLength;
	if (lyst_insert_last(exts, extField) == NULL)
	{
		MRELEASE(extField->value);
		MRELEASE(extField);
		return -1;	/*	Give up.			*/
	}

	*extensionOffset += ((*cursor) - initialCursor);
	return 1;
}
Esempio n. 4
0
File: adm.c Progetto: brnrc/ion-dtn
void adm_build_mid_str(uint8_t flag, char *nn, int nn_len, int offset, uint8_t *mid_str)
{
	uint8_t *cursor = NULL;
	Sdnv len;
	Sdnv off;
	uint32_t nn_size;
	uint8_t *tmp = NULL;
	int size = 0;

	DTNMP_DEBUG_ENTRY("adm_build_mid_str", "(%d, %s, %d, %d)",
			          flag, nn, nn_len, offset);


	encodeSdnv(&len, nn_len + 1);
	encodeSdnv(&off, offset);
	tmp = utils_string_to_hex((unsigned char*)nn, &nn_size);

	size = 1 + nn_size + len.length + off.length + 1;

	if(size > ADM_MID_ALLOC)
	{
		DTNMP_DEBUG_ERR("adm_build_mid_str",
						"Size %d bigger than max MID size of %d.",
						size,
						ADM_MID_ALLOC);
		DTNMP_DEBUG_EXIT("adm_build_mid_str","->.", NULL);
		MRELEASE(tmp);
		return;
	}

	cursor = mid_str;

	memcpy(cursor, &flag, 1);
	cursor += 1;

	memcpy(cursor, len.text, len.length);
	cursor += len.length;

	memcpy(cursor, tmp, nn_size);
	cursor += nn_size;

	memcpy(cursor, off.text, off.length);
	cursor += off.length;

	memset(cursor, 0, 1); // NULL terminator.

	DTNMP_DEBUG_EXIT("adm_build_mid_str","->%s", mid_str);
	MRELEASE(tmp);
	return;
}
Esempio n. 5
0
File: udpts.c Progetto: b/ION
static void	udpClearAmsEndpoint(AmsEndpoint *dp)
{
	if (dp->tsep)
	{
		MRELEASE(dp->tsep);
	}
}
Esempio n. 6
0
File: mid.c Progetto: brnrc/ion-dtn
/******************************************************************************
 *
 * \par Function Name: mid_clear
 *
 * \par Resets the values associated with a MID. Basically, a structure-aware
 *      bzero.
 *
 * \retval void
 *
 * \param[in,out] mid  The MID being cleared.
 *
 * \par Notes:
 *		1. Clearing a MID is different than destroying a MID. This just clears
 *		   allocated members. The MID itself may be re-used.
 *
 * Modification History:
 *  MM/DD/YY  AUTHOR         DESCRIPTION
 *  --------  ------------   ---------------------------------------------
 *  10/22/12  E. Birrane     Initial implementation,
 *****************************************************************************/
void mid_clear(mid_t *mid)
{

    DTNMP_DEBUG_ENTRY("mid_clear","(%#llx)", (unsigned long) mid);

    if(mid == NULL)
    {
        DTNMP_DEBUG_ERR("mid_clear","Clearing NULL MID.", NULL);
        DTNMP_DEBUG_EXIT("mid_clear","->NULL.",NULL);
        return;
    }

    if(mid->raw != NULL)
    {
        MRELEASE(mid->raw);
        mid->raw = NULL;
    }

    if(mid->oid != NULL)
    {
    	oid_release(mid->oid);
    	mid->oid = NULL;
    }

    memset(mid, 0, sizeof(mid_t));
    DTNMP_DEBUG_EXIT("mid_clear","", NULL);
}
Esempio n. 7
0
/**
 * \brief serializes a register agent message into a buffer.
 *
 * \author Ed Birrane
 *
 * \note The returned message must be de-allocated from the memory pool.
 *
 * \return NULL - Failure
 *         !NULL - The serialized message.
 *
 * \param[in]  msg  The message to serialize.
 * \param[out] len  The length of the serialized message.
 */
uint8_t *msg_serialize_reg_agent(adm_reg_agent_t *msg, uint32_t *len)
{
	Sdnv id;

	uint8_t *result = NULL;
	uint8_t *cursor = NULL;

	DTNMP_DEBUG_ENTRY("msg_serialize_reg_agent","(0x%x, 0x%x)",
			          (unsigned long)msg, (unsigned long) len);

	/* Step 0: Sanity Checks. */
	if((msg == NULL) || (len == NULL))
	{
		DTNMP_DEBUG_ERR("msg_serialize_reg_agent","Bad Args",NULL);
		DTNMP_DEBUG_EXIT("msg_serialize_reg_agent","->NULL",NULL);
		return NULL;
	}

	/*
	 * STEP 1: Figure out the size of the entire message. That includes the
	 *         length of the header, acl list, SDNV holding length, and data.
	 */
	int id_len = strlen(msg->agent_id.name);
	encodeSdnv(&id,id_len);
	*len = id.length + id_len;

	/* STEP 4: Allocate the serialized message. */
	if((result = (uint8_t*)MTAKE(*len)) == NULL)
	{
		DTNMP_DEBUG_ERR("msg_serialize_reg_agent","Can't alloc %d bytes", *len);
		*len = 0;

		DTNMP_DEBUG_EXIT("msg_serialize_reg_agent","->NULL",NULL);
		return NULL;
	}

	/* Step 5: Populate the serialized message. */
	cursor = result;

	memcpy(cursor, id.text, id.length);
	cursor += id.length;

	memcpy(cursor, msg->agent_id.name, id_len);
	cursor += id_len;

	/* Step 6: Last sanity check. */
	if((cursor - result) != *len)
	{
		DTNMP_DEBUG_ERR("msg_serialize_reg_agent","Wrote %d bytes but allcated %d",
				(unsigned long) (cursor - result), *len);
		*len = 0;
		MRELEASE(result);

		DTNMP_DEBUG_EXIT("msg_serialize_reg_agent","->NULL",NULL);
		return NULL;
	}

	DTNMP_DEBUG_EXIT("msg_serialize_reg_agent","->0x%x",(unsigned long)result);
	return result;
}
Esempio n. 8
0
File: libbp.c Progetto: b/ION
void	bp_release_delivery(BpDelivery *dlvBuffer, int releasePayload)
{
	Sdr	sdr = getIonsdr();

	CHKVOID(dlvBuffer);
	if (dlvBuffer->result == BpPayloadPresent)
	{
		if (dlvBuffer->bundleSourceEid)
		{
			MRELEASE(dlvBuffer->bundleSourceEid);
			dlvBuffer->bundleSourceEid = NULL;
		}

		if (releasePayload)
		{
			if (dlvBuffer->adu)
			{
				sdr_begin_xn(sdr);
				zco_destroy_reference(sdr, dlvBuffer->adu);
				if (sdr_end_xn(sdr) < 0)
				{
					putErrmsg("Failed releasing delivery.",
							NULL);
				}

				dlvBuffer->adu = 0;
			}
		}
	}
}
Esempio n. 9
0
File: udpts.c Progetto: b/ION
static void	udpClearMamsEndpoint(MamsEndpoint *ep)
{
	if (ep->tsep)
	{
		MRELEASE(ep->tsep);
	}
}
Esempio n. 10
0
void rpt_release_prod(rpt_prod_t *msg)
{

	DTNMP_DEBUG_ENTRY("rpt_release_prod","(0x%x)",
			          (unsigned long) msg);

	if(msg != NULL)
	{
		LystElt elt;
		rule_time_prod_t *item;

		for(elt = lyst_first(msg->defs); elt; elt = lyst_next(elt))
		{
			item = (rule_time_prod_t *) lyst_data(elt);

			rule_release_time_prod_entry(item);
			/* \todo Double check we don't need to kill the ELT here versus as
			 * part of lyst_destroy.
			 */
		}

		lyst_destroy(msg->defs);

		MRELEASE(msg);
	}

	DTNMP_DEBUG_EXIT("rpt_release_prod","->.",NULL);
}
Esempio n. 11
0
static void	terminateReceiverThread(ReceiverThreadParms *parms)
{
	int	senderSocket;

	writeErrmsgMemos();
	writeMemo("[i] brsscla receiver thread stopping.");
	pthread_mutex_lock(parms->mutex);
	if (parms->bundleSocket != -1)
	{
		closesocket(parms->bundleSocket);
		if (parms->ductNbr != (unsigned int) -1)
		{
			senderSocket = parms->ductNbr - parms->baseDuctNbr;
			if (parms->brsSockets[senderSocket] ==
					parms->bundleSocket)
			{
				/*	Stop sender thread transmission
				 *	over this socket.  Note: does
				 *	not halt the sender thread.	*/

				parms->brsSockets[senderSocket] = -1;
			}
		}

		parms->bundleSocket = -1;
	}

	lyst_delete(parms->elt);
	pthread_mutex_unlock(parms->mutex);
	MRELEASE(parms);
}
Esempio n. 12
0
File: mid.c Progetto: brnrc/ion-dtn
mid_t *mid_copy(mid_t *src_mid)
{
    mid_t *result = 0;
    
    DTNMP_DEBUG_ENTRY("mid_copy","(%#llx)",
    		          (unsigned long) src_mid);
    
    /* Step 0: Sanity Check */
    if(src_mid == NULL)
    {
        DTNMP_DEBUG_ERR("mid_copy","Cannot copy from NULL source MID.", NULL);
        DTNMP_DEBUG_EXIT("mid_copy","->NULL",NULL);
        return NULL;
    }

    /* Step 1: Allocate the new MID. */
    if((result = (mid_t *)MTAKE(sizeof(mid_t))) == NULL)
    {
        DTNMP_DEBUG_ERR("mid_copy","Can't allocate %d bytes", sizeof(mid_t));
        DTNMP_DEBUG_EXIT("mid_copy","->NULL",NULL);
        return NULL;
    }

    /* Step 2: Start with a shallow copy. */
    memcpy(result, src_mid, sizeof(mid_t));

    /* Step 3: Now, deep copy the pointers. */
    result->oid = oid_copy(src_mid->oid);

    if((result->raw = (uint8_t *)MTAKE(src_mid->raw_size)) == NULL)
    {
        DTNMP_DEBUG_ERR("mid_copy","Can't allocate %d bytes",
        		        src_mid->raw_size);

        MRELEASE(result->oid);
        MRELEASE(result);

        DTNMP_DEBUG_EXIT("mid_copy","->NULL",NULL);
        return NULL;
    }

    memcpy(result->raw, src_mid->raw, src_mid->raw_size);

    DTNMP_DEBUG_EXIT("mid_copy","->%d", result);
    return result;
}
Esempio n. 13
0
File: libbp.c Progetto: b/ION
void	bp_close(BpSAP sap)
{
	VEndpoint	*vpoint;

	if (sap == NULL)
	{
		return;
	}

	vpoint = sap->vpoint;
	if (vpoint->appPid == sm_TaskIdSelf())
	{
		vpoint->appPid = -1;
	}

	MRELEASE(sap->endpointMetaEid.nss);
	MRELEASE(sap->endpointMetaEid.schemeName);
	MRELEASE(sap);
}
Esempio n. 14
0
uint8_t *msg_serialize_rpt_policy(adm_rpt_policy_t *msg, uint32_t *len)
{
	uint8_t *result = NULL;
	uint8_t *cursor = NULL;

	DTNMP_DEBUG_ENTRY("msg_serialize_rpt_policy","(0x%x, 0x%x)",
			          (unsigned long)msg, (unsigned long) len);

	/* Step 0: Sanity Checks. */
	if((msg == NULL) || (len == NULL))
	{
		DTNMP_DEBUG_ERR("msg_serialize_rpt_policy","Bad Args",NULL);
		DTNMP_DEBUG_EXIT("msg_serialize_rpt_policy","->NULL",NULL);
		return NULL;
	}


	/*
	 * STEP 1: Figure out the size of the entire message. That includes the
	 *         length of the header, acl list, and 1 byte for the mask.
	 */
	*len = 1;

	/* STEP 4: Allocate the serialized message. */
	if((result = (uint8_t*)MTAKE(*len)) == NULL)
	{
		DTNMP_DEBUG_ERR("msg_serialize_rpt_policy","Can't alloc %d bytes", *len);
		*len = 0;

		DTNMP_DEBUG_EXIT("msg_serialize_rpt_policy","->NULL",NULL);
		return NULL;
	}

	/* Step 5: Populate the serialized message. */
	cursor = result;

	memcpy(cursor, &(msg->mask),1);
	cursor += 1;

	/* Step 6: Last sanity check. */
	if((cursor - result) != *len)
	{
		DTNMP_DEBUG_ERR("msg_serialize_rpt_policy","Wrote %d bytes but allcated %d",
				(unsigned long) (cursor - result), *len);
		*len = 0;
		MRELEASE(result);

		DTNMP_DEBUG_EXIT("msg_serialize_rpt_policy","->NULL",NULL);
		return NULL;
	}

	DTNMP_DEBUG_EXIT("msg_serialize_rpt_policy","->0x%x",(unsigned long)result);
	return result;
}
Esempio n. 15
0
void	ltpei_discard_extensions(Lyst extensions)
{
	LystElt			elt;
	LtpExtensionInbound	*ext;

	CHKVOID(extensions);
	while ((elt = lyst_first(extensions)) != NULL)
	{
		ext = (LtpExtensionInbound *) lyst_data(elt);
		if (ext->value)
		{
			MRELEASE(ext->value);
		}

		MRELEASE(ext);
		lyst_delete(elt);
	}

	lyst_destroy(extensions);
}
Esempio n. 16
0
File: udpts.c Progetto: b/ION
static void	*udpAmsReceiver(void *parm)
{
	AmsInterface		*tsif = (AmsInterface *) parm;
	int			fd;
	AmsSAP			*amsSap;
	char			*buffer;
	sigset_t		signals;
	int			length;
	struct sockaddr_in	fromAddr;
	unsigned int		fromSize;

	fd = (long) (tsif->sap);
	amsSap = tsif->amsSap;
	buffer = MTAKE(UDPTS_MAX_MSG_LEN);
	if (buffer == NULL)
	{
		putSysErrmsg(NoMemoryMemo, NULL);
		return NULL;
	}

	sigfillset(&signals);
	pthread_sigmask(SIG_BLOCK, &signals, NULL);
	while (1)
	{
		fromSize = sizeof fromAddr;
		length = recvfrom(fd, buffer, UDPTS_MAX_MSG_LEN, 0,
				(struct sockaddr *) &fromAddr, &fromSize);
		if (length < 2)	/*	length == 1 is "shutdown"	*/
		{
			if (length < 0)
			{
				if (errno == EINTR)
				{
					continue;
				}

				putSysErrmsg("udpts failed receiving AMS \
message", NULL);
			}

			close(fd);
			MRELEASE(buffer);
			tsif->sap = NULL;
			return NULL;
		}

		/*	Got an AMS message.				*/

		if (enqueueAmsMsg(amsSap, (unsigned char *) buffer, length) < 0)
		{
			putErrmsg("udpts discarded AMS message.", NULL);
		}
	}
}
Esempio n. 17
0
File: adm.c Progetto: brnrc/ion-dtn
/******************************************************************************
 *
 * \par Function Name: adm_add_datadef_collect
 *
 * \par Registers a collection function to a data definition.
 *
 * \param[in] mid_str   serialized MID value
 * \param[in] collect   The data collection function.
 *
 * \par Notes:
 *		1. When working with parameterized OIDs, the given MID should
 *		   be all information excluding the parameterized portion of the OID.
 *		2. ADM names will be truncated after ADM_MAX_NAME bytes.
 *
 * Modification History:
 *  MM/DD/YY  AUTHOR         DESCRIPTION
 *  --------  ------------   ---------------------------------------------
 *  11/25/12  E. Birrane     Initial implementation.
 *  07/27/13  E. BIrrane     Updated ADM to use Lysts.
 *****************************************************************************/
void adm_add_datadef_collect(uint8_t *mid_str, adm_data_collect_fn collect)
{
	uint32_t used = 0;
	mid_t *mid = NULL;
	adm_datadef_t *entry = NULL;

	DTNMP_DEBUG_ENTRY("adm_add_datadef_collect","(%lld, %lld)", mid_str, collect);

	if((mid_str == NULL) || (collect == NULL))
	{
		DTNMP_DEBUG_ERR("adm_add_datadef_collect","Bad Args.", NULL);
		DTNMP_DEBUG_EXIT("adm_add_datadef_collect","->.", NULL);
		return;
	}

	if((mid = mid_deserialize(mid_str, ADM_MID_ALLOC, &used)) == NULL)
	{
		char *tmp = utils_hex_to_string(mid_str, ADM_MID_ALLOC);
		DTNMP_DEBUG_ERR("adm_add_datadef_collect","Can't deserialize MID str %s.",tmp);
		MRELEASE(tmp);

		DTNMP_DEBUG_EXIT("adm_add_datadef_collect","->.", NULL);
		return;
	}

	if((entry = adm_find_datadef(mid)) == NULL)
	{
		char *tmp = mid_to_string(mid);
		DTNMP_DEBUG_ERR("adm_add_datadef_collect","Can't find data for MID %s.", tmp);
		MRELEASE(tmp);
	}
	else
	{
		entry->collect = collect;
	}

	mid_release(mid);

	DTNMP_DEBUG_EXIT("adm_add_datadef_collect","->.", NULL);
}
Esempio n. 18
0
File: mid.c Progetto: brnrc/ion-dtn
void mid_release(mid_t *mid)
{
    DTNMP_DEBUG_ENTRY("mid_release", "(%#llx)", (unsigned long) mid);

    if(mid != NULL)
    {
        mid_clear(mid);
        MRELEASE(mid);
        mid = NULL;
    }

    DTNMP_DEBUG_EXIT("mid_release", "-> NULL", NULL);
}
Esempio n. 19
0
File: adm.c Progetto: brnrc/ion-dtn
void adm_add_ctrl_run(uint8_t *mid_str, adm_ctrl_fn run)
{
	uint32_t used = 0;
	mid_t *mid = NULL;
	adm_ctrl_t *entry = NULL;

	DTNMP_DEBUG_ENTRY("adm_add_ctrl_run","(%lld, %lld)", mid_str, run);

	if((mid_str == NULL) || (run == NULL))
	{
		DTNMP_DEBUG_ERR("adm_add_ctrl_run","Bad Args.", NULL);
		DTNMP_DEBUG_EXIT("adm_add_ctrl_run","->.",NULL);
		return;
	}

	if((mid = mid_deserialize(mid_str, ADM_MID_ALLOC, &used)) == NULL)
	{
		char *tmp = utils_hex_to_string(mid_str, ADM_MID_ALLOC);
		DTNMP_DEBUG_ERR("adm_add_ctrl_run","Can't deserialized MID %s", tmp);
		MRELEASE(tmp);
		DTNMP_DEBUG_EXIT("adm_add_ctrl_run","->.",NULL);
		return;
	}

	if((entry = adm_find_ctrl(mid)) == NULL)
	{
		char *tmp = mid_to_string(mid);
		DTNMP_DEBUG_ERR("adm_add_ctrl_run","Can't find control for MID %s", tmp);
		MRELEASE(tmp);
	}
	else
	{
		entry->run = run;
	}

	mid_release(mid);

	DTNMP_DEBUG_EXIT("adm_add_ctrl_run","->.",NULL);
}
Esempio n. 20
0
int mgr_agent_remove(eid_t* in_eid)
{
	agent_t 	*agent 		= NULL;
	Object 		*entry		= NULL;
	LystElt		elt;

	DTNMP_DEBUG_ENTRY("mgr_agent_remove","(0x%#llx)", (unsigned long) in_eid);

	/* Step 0: Sanity Checks. */
	if(in_eid == NULL)
	{
		DTNMP_DEBUG_ERR("remove_agent","Specified EID was null.", NULL);
		DTNMP_DEBUG_EXIT("remove_agent","", NULL);
		return -1;
	}

	lockResource(&agents_mutex);

	elt = lyst_first(known_agents);
	while(elt != NULL)
	{
		if(strcmp(in_eid->name, ((agent_t *) lyst_data(elt))->agent_eid.name) == 0)
		{
			agent = (agent_t *) lyst_data(elt);
			lyst_delete(elt);
			break;
		}
		else
		{
			elt = lyst_next(elt);
		}
	}

	unlockResource(&agents_mutex);

	if(agent == NULL)
	{
		DTNMP_DEBUG_ERR("remove_agent", "No agent %s found in hashtable", in_eid->name);
		DTNMP_DEBUG_EXIT("remove_agent", "->0", NULL);
		return 0;
	}

	rpt_clear_lyst(&(agent->reports), &(agent->mutex), 1);
	def_lyst_clear(&(agent->custom_defs), &(agent->mutex), 1);

	killResourceLock(&(agent->mutex));
	MRELEASE(agent);

	DTNMP_DEBUG_EXIT("remove_agent", "->1", NULL);
	return 1;
}
Esempio n. 21
0
void rpt_print_data_entry(rpt_data_entry_t *entry)
{
	char *id_str = NULL;

	if(entry == NULL)
	{
		fprintf(stderr,"NULL ENTRY.\n");
	}

	id_str = mid_pretty_print(entry->id);
	fprintf(stderr,"DATA ENTRY:\n%s\n", id_str);
	MRELEASE(id_str);

	fprintf(stderr,"SIZE: %d\n", (uint32_t)entry->size);
	utils_print_hex(entry->contents, entry->size);
}
Esempio n. 22
0
/* Release functions.*/
void rpt_release_lst(rpt_items_t *msg)
{

	DTNMP_DEBUG_ENTRY("rpt_release_lst","(0x%x)",
			          (unsigned long) msg);

	if(msg != NULL)
	{
		if(msg->contents != NULL)
		{
			midcol_destroy(&(msg->contents));
		}
		MRELEASE(msg);
	}

	DTNMP_DEBUG_EXIT("rpt_release_lst","->.",NULL);
}
Esempio n. 23
0
void rpt_release_defs(rpt_defs_t *msg)
{
	DTNMP_DEBUG_ENTRY("rpt_release_defs","(0x%x)",
			          (unsigned long) msg);

	if(msg != NULL)
	{
		if(msg->defs != NULL)
		{
			midcol_destroy(&(msg->defs));
		}

		MRELEASE(msg);
	}

	DTNMP_DEBUG_EXIT("rpt_release_defs","->.",NULL);
}
Esempio n. 24
0
void mgr_agent_remove_cb(LystElt elt, void *nil)
{
	eid_t   *agent_eid	= NULL;
	agent_t	*agent		= NULL;
	Object	*entry		= NULL;

	if(elt == NULL)
	{
		DTNMP_DEBUG_ERR("mgr_agent_remove_cb",
				        "Specified Lyst element was null.", NULL);
		DTNMP_DEBUG_EXIT("mgr_agent_remove_cb","", NULL);
		return;
	}

	lockResource(&agents_mutex);

	if((agent = (agent_t *) lyst_data(elt)) == NULL)
	{
		DTNMP_DEBUG_ERR("mgr_agent_remove_cb",
				        "Specified Lyst data was null.", NULL);
	}
	else
	{
		rpt_clear_lyst(&(agent->reports), &(agent->mutex), 1);
		def_lyst_clear(&(agent->custom_defs), &(agent->mutex), 1);

		killResourceLock(&(agent->mutex));
		MRELEASE(agent);
	}

	unlockResource(&agents_mutex);

	DTNMP_DEBUG_EXIT("mgr_agent_remove_cb","", NULL);

	return;
}
Esempio n. 25
0
File: libbp.c Progetto: b/ION
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;
}
Esempio n. 26
0
static void	*sendKeepalives(void *parm)
{
	KeepaliveThreadParms	*parms = (KeepaliveThreadParms *) parm;
	int			keepaliveTimer = 0;
	int			bytesSent;
	int			backoffTimer = BACKOFF_TIMER_START;
	int 			backoffTimerCount = 0;
	unsigned char 		*buffer;

	buffer = MTAKE(TCPCLA_BUFSZ);	//To send keepalive bundle
	if (buffer == NULL)
	{
		putErrmsg("No memory for TCP buffer in tcpclo.", NULL);
		return NULL;
	}

	iblock(SIGTERM);
	while (*(parms->cloRunning))
	{
		snooze(1);
		keepaliveTimer++;
		if (keepaliveTimer < *(parms->keepalivePeriod))
		{
			continue;
		}

		// If the negotiated keep alive interval is 0, then
		// keep alives will not be sent.
		if(*(parms->keepalivePeriod) == 0)
		{
			continue;
		}

		/*	Time to send a keepalive.  Note that the
		 *	interval between keepalive attempts will be
		 *	KEEPALIVE_PERIOD plus (if the remote induct
		 *	is not reachable) the length of time taken
		 *	by TCP to determine that the connection
		 *	attempt will not succeed (e.g., 3 seconds).	*/

		keepaliveTimer = 0;
		pthread_mutex_lock(parms->mutex);
		bytesSent = sendBundleByTCPCL(parms->socketName,
				parms->ductSocket, 0, 0, buffer, parms->keepalivePeriod);
		pthread_mutex_unlock(parms->mutex);
		/*	if the node is unable to establish a TCP connection,
 		 * 	the connection should be tried only after some delay.
 		 *								*/
		if(bytesSent == 0)
		{	
			while((backoffTimerCount < backoffTimer) && (*(parms->ductSocket) < 0))
			{
				snooze(1);
				backoffTimerCount++;
				if(!(*(parms->cloRunning)))
				{
					break;
				}
			}
			backoffTimerCount = 0;
			/*	keepaliveTimer keeps track of when the keepalive needs 
			 *	to be sent. This value is set to keepalive period.
			 *	That way at the end of backoff period a 
			 *	keepalive is sent
			 *							*/
			keepaliveTimer = *(parms->keepalivePeriod);

			if(backoffTimer < BACKOFF_TIMER_LIMIT)
			{
				backoffTimer *= 2;
			}
			continue;
		}
		backoffTimer = BACKOFF_TIMER_START;
		if (bytesSent < 0)
		{
			shutDownClo();
			break;
		}
	}
	MRELEASE(buffer);
	return NULL;
}
Esempio n. 27
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;
}
Esempio n. 28
0
static void	*receiveBundles(void *parm)
{
	/*	Main loop for bundle reception thread	*/

	ReceiveThreadParms	*parms = (ReceiveThreadParms *) parm;
	int			threadRunning = 1;
	AcqWorkArea		*work;
	char			*buffer;

	buffer = MTAKE(TCPCLA_BUFSZ);
	if (buffer == NULL)
	{
		putErrmsg("tcpclo receiver can't get TCP buffer", NULL);
		return NULL;
	}

	work = bpGetAcqArea(parms->vduct);
	if (work == NULL)
	{
		putErrmsg("tcpclo receiver can't get acquisition work area",
				NULL);
		MRELEASE(buffer);
		return NULL;
	}

	iblock(SIGTERM);
	while (threadRunning && *(parms->cloRunning))
	{
		if(*(parms->bundleSocket) < 0)
		{
			snooze(1);
			/*Retry later*/
			continue;
		}

		if (bpBeginAcq(work, 0, NULL) < 0)
		{
			putErrmsg("Can't begin acquisition of bundle.", NULL);
			threadRunning = 0;
			continue;
		}
	
		switch (receiveBundleByTcpCL(*(parms->bundleSocket), work,
					buffer))
		{
		case -1:
			putErrmsg("Can't acquire bundle.", NULL);
			pthread_mutex_lock(parms->mutex);
			closesocket(*(parms->bundleSocket));
			*(parms->bundleSocket) = -1;
			pthread_mutex_unlock(parms->mutex);
			continue;

		case 0:			/*	Shutdown message	*/	
			/*	Go back to the start of the while loop	*/
			pthread_mutex_lock(parms->mutex);
			closesocket(*(parms->bundleSocket));
			*(parms->bundleSocket) = -1;
			pthread_mutex_unlock(parms->mutex);			
			continue;

		default:
			break;			/*	Out of switch.	*/
		}

		if (bpEndAcq(work) < 0)
		{
			putErrmsg("Can't end acquisition of bundle.", NULL);
			threadRunning = 0;
		}

		/*	Make sure other tasks have a chance to run.	*/

		sm_TaskYield();
	}

	/*	End of receiver thread; release resources.		*/

	bpReleaseAcqArea(work);
	MRELEASE(buffer);
	return NULL;
}
Esempio n. 29
0
File: libbp.c Progetto: b/ION
int	bp_open(char *eidString, BpSAP *bpsapPtr)
{
	Sdr		sdr;
	MetaEid		metaEid;
	VScheme		*vscheme;
	PsmAddress	vschemeElt;
	Sap		sap;
	VEndpoint	*vpoint;
	PsmAddress	vpointElt;

	CHKERR(eidString && *eidString && bpsapPtr);
	*bpsapPtr = NULL;	/*	Default, in case of failure.	*/
	sdr = getIonsdr();
	sdr_begin_xn(sdr);	/*	Just to lock memory.		*/

	/*	First validate the endpoint ID.				*/

	if (parseEidString(eidString, &metaEid, &vscheme, &vschemeElt) == 0)
	{
		sdr_exit_xn(sdr);
		putErrmsg("Malformed EID.", eidString);
		return -1;
	}

	if (vschemeElt == 0)
	{
		sdr_exit_xn(sdr);
		putErrmsg("Scheme not known.", metaEid.schemeName);
		restoreEidString(&metaEid);
		return -1;
	}

	findEndpoint(NULL, metaEid.nss, vscheme, &vpoint, &vpointElt);
	if (vpointElt == 0)
	{
		sdr_exit_xn(sdr);
		putErrmsg("Endpoint not known.", metaEid.nss);
		restoreEidString(&metaEid);
		return -1;
	}

	/*	Endpoint exists; make sure it's not already opened
	 *	by some application.					*/

	if (vpoint->appPid > 0)	/*	Endpoint not closed.		*/
	{
		if (sm_TaskExists(vpoint->appPid))
		{
			sdr_exit_xn(sdr);
			if (vpoint->appPid == sm_TaskIdSelf())
			{
				return 0;
			}

			restoreEidString(&metaEid);
			putErrmsg("Endpoint is already open.",
					itoa(vpoint->appPid));
			return -1;
		}

		/*	Application terminated without closing the
		 *	endpoint, so simply close it now.		*/

		vpoint->appPid = -1;
	}

	/*	Construct the service access point.			*/

	sap.vpoint = vpoint;
	memcpy(&sap.endpointMetaEid, &metaEid, sizeof(MetaEid));
	sap.endpointMetaEid.colon = NULL;
	sap.endpointMetaEid.schemeName = MTAKE(metaEid.schemeNameLength + 1);
	if (sap.endpointMetaEid.schemeName == NULL)
	{
		sdr_exit_xn(sdr);
		putErrmsg("Can't create BpSAP.", NULL);
		restoreEidString(&metaEid);
		return -1;
	}

	sap.endpointMetaEid.nss = MTAKE(metaEid.nssLength + 1);
	if (sap.endpointMetaEid.nss == NULL)
	{
		sdr_exit_xn(sdr);
		MRELEASE(sap.endpointMetaEid.schemeName);
		putErrmsg("Can't create BpSAP.", NULL);
		restoreEidString(&metaEid);
		return -1;
	}

	*bpsapPtr = MTAKE(sizeof(Sap));
	if (*bpsapPtr == NULL)
	{
		sdr_exit_xn(sdr);
		MRELEASE(sap.endpointMetaEid.nss);
		MRELEASE(sap.endpointMetaEid.schemeName);
		putErrmsg("Can't create BpSAP.", NULL);
		restoreEidString(&metaEid);
		return -1;
	}

	istrcpy(sap.endpointMetaEid.schemeName, metaEid.schemeName,
			sizeof sap.endpointMetaEid.schemeName);
	istrcpy(sap.endpointMetaEid.nss, metaEid.nss,
			sizeof sap.endpointMetaEid.nss);
	restoreEidString(&metaEid);
	sap.recvSemaphore = vpoint->semaphore;
	memcpy((char *) *bpsapPtr, (char *) &sap, sizeof(Sap));

	/*	Having created the SAP, give its owner exclusive
	 *	access to the endpoint.					*/

	vpoint->appPid = sm_TaskIdSelf();
	sdr_exit_xn(sdr);	/*	Unlock memory.			*/
	return 0;
}
Esempio n. 30
0
static void	*handleDatagrams(void *parm)
{
	/*	Main loop for UDP datagram reception and handling.	*/

	ReceiverThreadParms	*rtp = (ReceiverThreadParms *) parm;
	char			*procName = "udplsi";
	char			*buffer;
	int			segmentLength;
	struct sockaddr_in	fromAddr;
	socklen_t		fromSize;

	snooze(1);	/*	Let main thread become interruptable.	*/
	buffer = MTAKE(UDPLSA_BUFSZ);
	if (buffer == NULL)
	{
		putErrmsg("udplsi can't get UDP buffer.", NULL);
		ionKillMainThread(procName);
		return NULL;
	}

	/*	Can now start receiving bundles.  On failure, take
	 *	down the LSI.						*/

	while (rtp->running)
	{	
		fromSize = sizeof fromAddr;
		segmentLength = irecvfrom(rtp->linkSocket, buffer, UDPLSA_BUFSZ,
				0, (struct sockaddr *) &fromAddr, &fromSize);
		switch (segmentLength)
		{
		case -1:
			putSysErrmsg("Can't acquire segment", NULL);
			ionKillMainThread(procName);

			/*	Intentional fall-through to next case.	*/

		case 1:				/*	Normal stop.	*/
			rtp->running = 0;
			continue;
		}

		if (ltpHandleInboundSegment(buffer, segmentLength) < 0)
		{
			putErrmsg("Can't handle inbound segment.", NULL);
			ionKillMainThread(procName);
			rtp->running = 0;
			continue;
		}

		/*	Make sure other tasks have a chance to run.	*/

		sm_TaskYield();
	}

	writeErrmsgMemos();
	writeMemo("[i] udplsi receiver thread has ended.");

	/*	Free resources.						*/

	MRELEASE(buffer);
	return NULL;
}