www.pudn.com > streamrtp.rar > rtcpsdes.c


/*-------------------------------------------------------------------------
 * rtcpsdes.c - rtcpsdes, rtcpprocesschunk, rtcpconsumechunk
 *-------------------------------------------------------------------------
 */

#include 
#include 
#include 
#include 
#include 

/*------------------------------------------------------------------------
 * rtcpsdes - process an incoming source description message
 *------------------------------------------------------------------------
 */
int
rtcpsdes(struct session *psn, struct rtcp *prtcp)
{

	struct sdchunk	*pchunk;
	int			i;

	if (prtcp->rtcp_type != RTCP_SDES) 
		return ERROR;

	/*
	 * Iterate over the source description's chunks.
	 */
	pchunk = (struct sdchunk *) prtcp->rtcp_data;
	for (i = 0; i < prtcp->rtcp_count && pchunk != NULL; i++) {
		pchunk = rtcpprocesschunk(psn, pchunk);
	}
	return OK;
}

/*------------------------------------------------------------------------
 * rtcpprocesschunk - process a single chunk of a source description
 * message.Rtcpprocesschunk returns a pointer to the next chunk.
 *------------------------------------------------------------------------
 */
struct sdchunk *
rtcpprocesschunk(struct session *psn, struct sdchunk *pchunk) 
{
  
	struct stream		*pstm;
	struct sditem		*psditem;
	struct sdchunk	        *nextchunk;

	pchunk->sdc_ssrc = ntohl(pchunk->sdc_ssrc);
	pstm = rtpgetstream(psn, pchunk->sdc_ssrc);
	if (pstm == NULL)
		if ((pstm = rtpnewstream(psn, pchunk->sdc_ssrc)) == NULL)
			return rtcpconsumechunk(pchunk);
  
	if (!RTP_INACTIVE(pstm->stm_inactive))
		pstm->stm_inactive = 0;
	else {
		rtpreleasestream(psn, pstm);
		return rtcpconsumechunk(pchunk);
	}

	/*
	 * Iterate over all items in the chunk.
	 */
	psditem = (struct sditem *) pchunk->sdc_data;
	nextchunk = NULL;
  
	while (nextchunk == NULL) {
		switch(psditem->sdi_type) {
		case RTCP_ITEM_NULL:
      
			/*
			 * End of chunk; eat nulls until we reach
			 * 32-bit alignmnet.
			 */
			do {
				psditem = (struct sditem *) ((char *) psditem + 1);
			} while (((unsigned int) psditem - (unsigned int) pchunk) % 4 != 0);

			nextchunk =  (struct sdchunk *) psditem; 
			break;

			/* 
			 * For all other items, record item in stream's state
			 * and post an event with no data.
			 */
		case RTCP_ITEM_CNAME:
			if (bcmp(pstm->stm_cname, psditem->sdi_data, psditem->sdi_len)) {
				strncpy(pstm->stm_cname, psditem->sdi_data, psditem->sdi_len);
				pstm->stm_cname[psditem->sdi_len] = '\0';
	
				rtcpcnameadd(psn, pstm);
				rtppostevent(psn, EVENT_RTCP_SDES_CNAME,
					     pstm->stm_ssrc, NULL, 0);
			}
			break;
      
		case RTCP_ITEM_NAME:
			if (bcmp(pstm->stm_name, psditem->sdi_data, psditem->sdi_len)) {
				strncpy(pstm->stm_name, psditem->sdi_data, psditem->sdi_len);
				pstm->stm_name[psditem->sdi_len] = '\0';
				rtppostevent(psn, EVENT_RTCP_SDES_NAME,
					     pstm->stm_ssrc, NULL, 0);
			}
			break;
	
		case RTCP_ITEM_EMAIL:
			if (bcmp(pstm->stm_email, psditem->sdi_data, psditem->sdi_len)) {
				strncpy(pstm->stm_email, psditem->sdi_data, psditem->sdi_len);
				pstm->stm_email[psditem->sdi_len] = '\0';
				rtppostevent(psn, EVENT_RTCP_SDES_EMAIL,
					     pstm->stm_ssrc, NULL, 0);
			}
			break;
      
		case RTCP_ITEM_PHONE:
			if (bcmp(pstm->stm_phone, psditem->sdi_data, psditem->sdi_len)) {
				strncpy(pstm->stm_phone, psditem->sdi_data, psditem->sdi_len);
				pstm->stm_phone[psditem->sdi_len] = '\0';
				rtppostevent(psn, EVENT_RTCP_SDES_PHONE,
					     pstm->stm_ssrc, NULL, 0);
			}
			break;
      
		case RTCP_ITEM_LOC:
			if (bcmp(pstm->stm_loc, psditem->sdi_data, psditem->sdi_len)) {
				strncpy(pstm->stm_loc, psditem->sdi_data, psditem->sdi_len);
				pstm->stm_loc[psditem->sdi_len] = '\0';
				rtppostevent(psn, EVENT_RTCP_SDES_LOC,
					     pstm->stm_ssrc, NULL, 0);
			}
			break;
      
		case RTCP_ITEM_TOOL:
			if (bcmp(pstm->stm_tool, psditem->sdi_data, psditem->sdi_len)) {
				strncpy(pstm->stm_tool, psditem->sdi_data, psditem->sdi_len);
				pstm->stm_tool[psditem->sdi_len] = '\0';
				rtppostevent(psn, EVENT_RTCP_SDES_TOOL,
					     pstm->stm_ssrc, NULL, 0);
			}  
			break;
      
		case RTCP_ITEM_NOTE:
			if (bcmp(pstm->stm_note, psditem->sdi_data, psditem->sdi_len)) {
				strncpy(pstm->stm_note, psditem->sdi_data, psditem->sdi_len);
				pstm->stm_note[psditem->sdi_len] = '\0';
				rtppostevent(psn, EVENT_RTCP_SDES_NOTE,
					     pstm->stm_ssrc, NULL, 0);
			}
			break;
      
		case RTCP_ITEM_PRIV:
			if (bcmp(pstm->stm_priv, psditem->sdi_data, psditem->sdi_len)) {
				strncpy(pstm->stm_priv, psditem->sdi_data, psditem->sdi_len);
				pstm->stm_note[psditem->sdi_len] = '\0';
				rtppostevent(psn, EVENT_RTCP_SDES_PRIV,
					     pstm->stm_ssrc, NULL, 0);
			} 
			break;
		}
    
		/*
		 * Advance to next item.
		 */
		psditem = (struct sditem *) ((char *) psditem + 2 + psditem->sdi_len);
	}

	rtppostevent(psn, EVENT_RTCP_SDES_CHUNK, pstm->stm_ssrc,
		     (char *) pchunk, (unsigned int) nextchunk 
		     - (unsigned int) pchunk);

	rtpreleasestream(psn, pstm);

	return nextchunk;
}

/*------------------------------------------------------------------------
 * rtcpconsumechunk - quietly consume a source description chunk.
 * Rtcpconsumechunk is used to skip over chunks that relate to inactive
 * participants.
 *------------------------------------------------------------------------
 */
struct sdchunk *
rtcpconsumechunk(struct sdchunk *pchunk)
{

	struct sdchunk	*nextchunk;
	struct sditem		*psditem;

	/*
	 * Iterate over items in the chunk.
	 */
	psditem = (struct sditem *) pchunk->sdc_data;
	nextchunk = NULL;
  
	while (nextchunk == NULL) {
		if (psditem->sdi_type == RTCP_ITEM_NULL) {
			/*
			 * End of chunk; eat nulls until we 
			 * reach 32-bit alignmnet.
			 */
			do {
				psditem = (struct sditem *) ((char *) psditem + 1);
			} while (((unsigned int) psditem - (unsigned int) pchunk) % 4 != 0);
      
			nextchunk =  (struct sdchunk *) psditem; 
		}
    
		/* 
		 * Advance to next item.
		 */
		psditem = (struct sditem *) ((char *) psditem + 2 + psditem->sdi_len);
	}

	return nextchunk;
}