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


/*-------------------------------------------------------------------------
 * rtpctl.c - rtpctl
 *-------------------------------------------------------------------------
 */

#include 
#include 
#include 
#include 
#include 
#include 

/*-------------------------------------------------------------------------
 * rtpctl - miscelaneous functions relating to an RTP layer sesion
 * Values are passed in and out by reference. It is the caller's 
 * responsibility to insure that a pointer of the correct type.
 * The field sizeofarg is only used when copying a string out.
 *-------------------------------------------------------------------------
 */

int
rtpctl(struct session *psn, int command, char *arg, int sizeofarg, ssrc_t ssrc)
{

	int             i;
	struct stream   *pstm;

	/*
	 * Commands that do not not refer to a specific stream.
	 */
	switch(command) {
	case RTP_CTL_ADDEVENTQUEUE:
		pthread_mutex_lock(&psn->sn_mutex);
		for (i = 0; i < RTP_MAXEVENTQUEUES && psn->sn_eventqs[i] != NULL; i++);
		if (i == RTP_MAXEVENTQUEUES) {
			pthread_mutex_unlock(&psn->sn_mutex);
			return ERROR;
		}
		psn->sn_eventqs[i] = (struct eventqueue *)arg;
		pthread_mutex_unlock(&psn->sn_mutex);
		return OK;

	case RTP_CTL_REMEVENTQUEUE:
		pthread_mutex_lock(&psn->sn_mutex);
		for (i = 0; i < RTP_MAXEVENTQUEUES; i++)
			if (psn->sn_eventqs[i] == (struct eventqueue *)arg)
				psn->sn_eventqs[i] = NULL;
		pthread_mutex_unlock(&psn->sn_mutex);
		return OK;

	case RTP_CTL_SETTTL:
		/*
		 * Not done for RTP socket for receive-only implementation.
		 */
		if (setsockopt(psn->sn_rtcpfd, IPPROTO_IP, IP_MULTICAST_TTL, 
			       (char *) arg, sizeof(char)) < 0) {
			return ERROR;
		}
		return OK;
    
	case RTP_CTL_SETBW:
		psn->sn_bw = *((unsigned int *) arg);
		return OK;
    
	case RTP_CTL_SETCLEANUP:
		psn->sn_autocleanup = *((bool *) arg);
		return OK;
    
	case RTP_CTL_RTCPCYCLETHREAD:
		switch(*((bool *) arg)) {
		case TRUE:
			return startthread(&psn->sn_rtcpcyclethr, (void *(*)(void *))rtcpcyclethreadfcn, (void *)psn, &psn->sn_rtcpcyclethrmutex, &psn->sn_cond, &psn->sn_rtcpcyclethrstat);
		case FALSE:
			return stopthread(&psn->sn_rtcpcyclethr, &psn->sn_rtcpcyclethrmutex, &psn->sn_cond, &psn->sn_rtpthrstat);
		}

	case RTP_CTL_RTPRECVTHREAD:
		switch(*((bool *) arg)) {
		case TRUE:
			return startthread(&psn->sn_rtpthr, (void *(*)(void *))rtprecvthreadfcn, (void *)psn, &psn->sn_rtpthrmutex, &psn->sn_cond, &psn->sn_rtpthrstat);
		case FALSE:
			return stopthread(&psn->sn_rtpthr, &psn->sn_rtpthrmutex, &psn->sn_cond, &psn->sn_rtpthrstat);
		}
      
	case RTP_CTL_RTCPRECVTHREAD:
		switch(*((bool *) arg)) {
		case TRUE:
			return startthread(&psn->sn_rtcpthr, (void *(*)(void *))rtcprecvthreadfcn, (void *)psn, &psn->sn_rtcpthrmutex, &psn->sn_cond, &psn->sn_rtcpthrstat);
		case FALSE:
			return stopthread(&psn->sn_rtcpthr, &psn->sn_rtcpthrmutex, &psn->sn_cond, &psn->sn_rtcpthrstat);
		}
	}

	/*
	 * Commands that refer to a specific stream.
	 */
	pstm = rtpgetstream(psn, ssrc);
	if (pstm == NULL)
		return ERROR;
  
	switch(command) {
	case RTP_CTL_STREAM_GETENQUEUE:
		*((bool *) arg) = pstm->stm_enqueue;
		break;
    
	case RTP_CTL_STREAM_GETCLKRT:
		*((unsigned int *) arg) = pstm->stm_clkrt;
		break;

	case RTP_CTL_STREAM_SETCLKRT:
		pstm->stm_clkrt = *((unsigned int *) arg);
		break;

	case RTP_CTL_STREAM_GETPT:
		*((int *) arg) = pstm->stm_payload;
		break;

	case RTP_CTL_STREAM_GETQLEN:
		*((int *) arg) = pstm->stm_queue.rq_len;
		break;

	case RTP_CTL_STREAM_GETINACTIVE:
		*((int *) arg) = pstm->stm_inactive;
		break;

	case RTP_CTL_STREAM_GETJITTER:
		*((double *) arg) = pstm->stm_jitter;
		break;

	case RTP_CTL_STREAM_GETPACKETCNT:
		*((unsigned int *) arg) = pstm->stm_packets;
		break;
 
	case RTP_CTL_STREAM_GETROLLOVERS:
		*((unsigned int *) arg) = pstm->stm_roll;
		break;

	case RTP_CTL_STREAM_GETPROBATION:
		*((unsigned int *) arg) = pstm->stm_probation;
		break;

	case RTP_CTL_STREAM_GETCNAME:
		strncpy((char *) arg, pstm->stm_cname, min(sizeofarg, strlen(pstm->stm_cname) + 1));
		break;

	case RTP_CTL_STREAM_GETNAME:
		strncpy((char *) arg, pstm->stm_name, min(sizeofarg, strlen(pstm->stm_name) + 1));
		break;

	case RTP_CTL_STREAM_GETEMAIL:
		strncpy((char *) arg, pstm->stm_email, min(sizeofarg, strlen(pstm->stm_email) + 1));
		break;

	case RTP_CTL_STREAM_GETPHONE:
		strncpy((char *) arg, pstm->stm_phone, min(sizeofarg, strlen(pstm->stm_phone) + 1));
		break;

	case RTP_CTL_STREAM_GETTOOL:
		strncpy((char *) arg, pstm->stm_tool, min(sizeofarg, strlen(pstm->stm_tool) + 1));
		break;

	case RTP_CTL_STREAM_GETNOTE:
		strncpy((char *) arg, pstm->stm_note, min(sizeofarg, strlen(pstm->stm_note) + 1));
		break;

	case RTP_CTL_STREAM_GETPRIV:
		strncpy((char *) arg, pstm->stm_cname, min(sizeofarg, strlen(pstm->stm_cname) + 1));
		break;
    
	case RTP_CTL_STREAM_GETINACTTHR:
		*((int *) arg) = pstm->stm_inactthresh;
		break;

	case RTP_CTL_STREAM_SETINACTTHR:
		/* 
		 * Will have no effect on streams already marked RTP_TIMEDOUT
		 */
		pstm->stm_inactthresh = *((int *) arg);
		break;

	case RTP_CTL_STREAM_GETSRTS:
		*((mediatime_t *) arg) = pstm->stm_lastsrts;
		break;

	case RTP_CTL_STREAM_GETSRNTP:
		memcpy(arg, pstm->stm_lastntp, sizeof(unsigned int) * 2);
		break;

	case RTP_CTL_STREAM_LOCK:
		if (pthread_mutex_lock(&pstm->stm_mutex)) {
			rtpreleasestream(psn, pstm);
			return ERROR;
		}

	case RTP_CTL_STREAM_UNLOCK:
		pthread_mutex_unlock(&pstm->stm_mutex);
		break;

	case RTP_CTL_STREAM_NULL:
		/* do nothing */
		break;

	default:
		rtpreleasestream(psn, pstm);
		return ERROR;
	} /* switch */

	rtpreleasestream(psn, pstm);
	return OK;
}