⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtpproxy_relay.c

📁 简单的基于SIP的会话边界控制器
💻 C
📖 第 1 页 / 共 2 页
字号:
  	osip_call_id_t cid;

  	if (callid == NULL) {
      		printf("rtp_relay_start_fwd: callid is NULL!");
     		return STS_FAILURE;
   	}

   	if (client_id == NULL) {
      		printf("rtp_relay_start_fwd: did not get a client ID!");
      		return STS_FAILURE;
   	}

   	pthread_mutex_lock(&rtp_proxytable_mutex);

   	/*
   	 * figure out, if this is an request to start an RTP proxy stream
    	 * that is already existing (identified by SIP Call-ID, direction,
        * media_stream_no and some other client unique thing).
        * This can be due to UDP repetitions of the INVITE request...
        */
       for (i=0; i<RTPPROXY_SIZE; i++) {
      		cid.number = rtp_proxytable[i].callid_number;
      		cid.host   = rtp_proxytable[i].callid_host;
      		if (rtp_proxytable[i].rtp_rx_sock &&
         	   (compare_callid(callid, &cid) == STS_SUCCESS) &&
                 (rtp_proxytable[i].direction == rtp_direction) &&
                 (rtp_proxytable[i].media_stream_no == media_stream_no) &&
                 (strcmp(rtp_proxytable[i].client_id, client_id) == 0)) {
                     /*  The RTP port number reported by the UA MAY change
          	    	  * for a given media stream
          	    	  * Also the destination IP may change during a re-Invite 
          	    	  */
          	    	    
          	       /* Port number */
         		if (rtp_proxytable[i].remote_port != remote_port) 
            			rtp_proxytable[i].remote_port = remote_port;
         		/* IP address */
        		if (memcmp(&rtp_proxytable[i].remote_ipaddr, &remote_ipaddr,
                    		sizeof(remote_ipaddr))) {
            				memcpy (&rtp_proxytable[i].remote_ipaddr, &remote_ipaddr,
                     			sizeof(remote_ipaddr));
         		}
        		*local_port=rtp_proxytable[i].local_port;
	 		sts = STS_SUCCESS;
	 		goto unlock_and_exit;
      		}
       }

       /*
    	* find first free slot in rtp_proxytable
    	*/
   	freeidx=-1;
   	for (j=0; j<RTPPROXY_SIZE; j++) {
      		if (rtp_proxytable[j].rtp_rx_sock==0) {
         		freeidx=j;
	 		break;
      		}
   	}
   	/* rtp_proxytable port pool full? */
   	if (freeidx == -1) {
      		printf("rtp_relay_start_fwd: rtp_proxytable is full!");
      		sts = STS_FAILURE;
      		goto unlock_and_exit;
   	}

   	/*randomize the port allocation - start at a random offset to
          search in the allowed port range
	   random start offset 
	 - for i=x to (p1-p0)+x; p=p0+mod(x,p1-p0) */

   	/* find a local port number to use and bind to it */
   	sock=0;
   	port=0;

   	if ((prev_used_port < args_info.rtp_port_low_arg) || 
   	    (prev_used_port > args_info.rtp_port_high_arg)) {
       	prev_used_port = args_info.rtp_port_high_arg;
   	}
   	num_ports = args_info.rtp_port_high_arg - args_info.rtp_port_low_arg + 1;
   	for (i2 = (prev_used_port - args_info.rtp_port_low_arg + 1);
            	   i2 < (num_ports + prev_used_port - args_info.rtp_port_low_arg + 1);
                 i2++) {
     		i = (i2%num_ports) + args_info.rtp_port_low_arg;

     		/* only allow even port numbers */
      		if ((i % 2) != 0) continue;

      		for (j=0; j<RTPPROXY_SIZE; j++) {
         	/* check if port already in use */
         		if ((memcmp(&rtp_proxytable[j].local_ipaddr,
	             	     &local_ipaddr, sizeof(struct in_addr))== 0) &&
	                   (rtp_proxytable[j].local_port == i) ) break;
      		}
         	/* port is available, try to allocate */
      		if (j == RTPPROXY_SIZE) {
         		port=i;
         		sock=sockbind(local_ipaddr, port);
                     /* if success break, else try further on */
         		if (sock) break;
      		}
        }
        prev_used_port = port;

         /* found an unused port? No -> RTP port pool fully allocated */
   	 if ((port == 0) || (sock == 0)) {
        	printf("rtp_relay_start_fwd: no RTP port available or bind() failed");
      		sts = STS_FAILURE;
      		goto unlock_and_exit;
   	 }

   	 /* write entry into rtp_proxytable slot (freeidx) */
   	 rtp_proxytable[freeidx].rtp_rx_sock=sock;

   	 if (callid->number) {
      		strcpy(rtp_proxytable[freeidx].callid_number, callid->number);
   	 } else {
              rtp_proxytable[freeidx].callid_number[0]='\0';
   	 }

   	 if (callid->host) {
              strcpy(rtp_proxytable[freeidx].callid_host, callid->host);
   	 } else {
              rtp_proxytable[freeidx].callid_host[0]='\0';
   	 }

   	 if (client_id) {
      		strcpy(rtp_proxytable[freeidx].client_id, client_id);
   	 } else {
      		rtp_proxytable[freeidx].client_id[0]='\0';
   	 }

   	 rtp_proxytable[freeidx].direction = rtp_direction;
   	 rtp_proxytable[freeidx].media_stream_no = media_stream_no;
        memcpy(&rtp_proxytable[freeidx].local_ipaddr,&local_ipaddr, sizeof(struct in_addr));
   	 rtp_proxytable[freeidx].local_port=port;
	 memcpy(&rtp_proxytable[freeidx].remote_ipaddr,&remote_ipaddr, sizeof(struct in_addr));
        rtp_proxytable[freeidx].remote_port=remote_port;
   	 time(&rtp_proxytable[freeidx].timestamp);

        *local_port=port;

        /* prepare FD set for next select operation */
   	 rtp_recreate_fdset();
        
	int k;
        for (k=0; k<RTPPROXY_SIZE; k++) {
		if (rtp_proxytable[k].rtp_rx_sock != 0) {
			printf("rtp_proxytable[%d]:%d,%s@%s,%s,%d,%d\n",k,rtp_proxytable[k].rtp_rx_sock,
					rtp_proxytable[k].callid_number,rtp_proxytable[k].callid_host,
					rtp_proxytable[k].client_id,rtp_proxytable[k].direction,rtp_proxytable[k].media_stream_no);
       	 }
        }

  	 /* wakeup/signal rtp_proxythread from select() hibernation */
   	if (!pthread_equal(rtpproxy_tid, pthread_self()))
       	pthread_kill(rtpproxy_tid, SIGALRM);

 unlock_and_exit:
   	/* unlock mutex */
   	pthread_mutex_unlock(&rtp_proxytable_mutex);

   	return sts;
}


/*
 * stop a rtp stream on the proxy
 *
 * if media_stream_no == -1, all media streams will be stopped,
 * otherwise only the specified one.
 *
 * RETURNS
 *	STS_SUCCESS on success
 *	STS_FAILURE on error
 */
int rtp_relay_stop_fwd (osip_call_id_t *callid, int rtp_direction,
                        int media_stream_no, int nolock) {
	int i, sts;
   	int retsts=STS_SUCCESS;
   	int got_match=0;
   	osip_call_id_t cid;
 
   	if (callid == NULL) {
      		printf("rtp_relay_stop_fwd: callid is NULL!\n");
      		return STS_FAILURE;
   	} 

   	if (nolock == 0) {
       	pthread_mutex_lock(&rtp_proxytable_mutex);
   	}

   	/* 
   	 * wakeup/signal rtp_proxythread from select() hibernation.
   	 * This must be done here before we close the socket, otherwise
   	 * we may get an select() error later from the proxy thread that
   	 * is still hibernating in select() now.
   	 */
   	if (!pthread_equal(rtpproxy_tid, pthread_self()))
      		pthread_kill(rtpproxy_tid, SIGALRM);

   	/*
        * find the proper entry in rtp_proxytable
    	 * we need to loop the whole table, as there might be multiple
    	 * media streams active for the same callid (audio + video stream)
    	 * if media_stream_no == -1, all streams are stoppen, otherwise
    	 * if media_stream_no > 0 only the specified stream is stopped.
     	 */
        for (i=0; i<RTPPROXY_SIZE; i++) {
      		cid.number = rtp_proxytable[i].callid_number;
      		cid.host   = rtp_proxytable[i].callid_host;
      		if (rtp_proxytable[i].rtp_rx_sock &&
         	       (compare_callid(callid, &cid) == STS_SUCCESS) &&
         		(rtp_proxytable[i].direction == rtp_direction) &&
        		((media_stream_no < 0) ||
          		(media_stream_no == rtp_proxytable[i].media_stream_no))) {

         		sts = close(rtp_proxytable[i].rtp_rx_sock);
         		memset(&rtp_proxytable[i], 0, sizeof(rtp_proxytable[0]));
         		got_match=1;
      		}
        }

        /* did not find an active stream... */
   	 if (!got_match) {
      		printf("rtp_relay_stop_fwd: can't find active stream for %s@%s (%s)",
             		 callid->number, callid->host,
             		 ((rtp_direction == DIR_INCOMING) ? "incoming RTP\n" : "outgoing RTP\n"));
      	 	retsts = STS_FAILURE;
        	goto unlock_and_exit;
   	 }

   	 /* prepare FD set for next select operation */
   	 rtp_recreate_fdset();
   

unlock_and_exit:
   	/*
    	 * unlock mutex - only if not requested to skip the lock.
        * this is needed as we are also called from within
    	 * the RTP thread itself - and there we already own the lock.
    	 */
   	if (nolock == 0) {
      		pthread_mutex_unlock(&rtp_proxytable_mutex);
  	}

   	return retsts;
}

/*
 * some sockets have been newly created or removed -
 * recreate the FD set for next select operation
 *
 * RETURNS
 *	STS_SUCCESS on success (always)
 */
static int rtp_recreate_fdset(void) {
   	int i;

   	FD_ZERO(&master_fdset);
   	master_fd_max=-1;
   	for (i=0;i<RTPPROXY_SIZE;i++) {
      		if (rtp_proxytable[i].rtp_rx_sock != 0) {
         		FD_SET(rtp_proxytable[i].rtp_rx_sock, &master_fdset);
	 			if (rtp_proxytable[i].rtp_rx_sock > master_fd_max) {
	    				master_fd_max=rtp_proxytable[i].rtp_rx_sock;
	 			}
      		}
   	}
   	return STS_SUCCESS;
}


/*
 * kills the rtp_proxy thread
 *
 * RETURNS
 *	-
 */
void rtpproxy_kill( void ) {
   	void *thread_status;
   	osip_call_id_t cid;
  	 int i, sts;

   	/* stop any active RTP stream */
   	for (i=0;i<RTPPROXY_SIZE;i++) {
      		if (rtp_proxytable[i].rtp_rx_sock != 0) {
         		cid.number = rtp_proxytable[i].callid_number;
         		cid.host   = rtp_proxytable[i].callid_host;
         		sts = rtp_relay_stop_fwd(&cid, rtp_proxytable[i].direction,
                                  rtp_proxytable[i].media_stream_no, 0);
      		}
   	}
   
   	/* kill the thread */
   	if (rtpproxy_tid) {
      		pthread_cancel(rtpproxy_tid);
      		pthread_kill(rtpproxy_tid, SIGALRM);
      		pthread_join(rtpproxy_tid, &thread_status);
   	}
   
   	return;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -