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

📄 rtpproxy_relay.c

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


#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>

#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <signal.h>

#ifdef HAVE_PTHREAD_SETSCHEDPARAM
   #include <sched.h>
#endif

#include <osipparser2/osip_parser.h>

#include "nsrsbc.h"
#include "cmdline.h"
#include "rtpproxy.h"

/* configuration storage */
extern struct gengetopt_args_info args_info;

/*
 * table to remember all active rtp proxy streams
 */
rtp_proxytable_t rtp_proxytable[RTPPROXY_SIZE];

/*
 * Mutex for thread synchronization (locking when accessing common 
 * data structures -> rtp_proxytable[]).
 *
 * use a 'fast' mutex for synchronizing - as these are portable... 
 */
static pthread_mutex_t rtp_proxytable_mutex = PTHREAD_MUTEX_INITIALIZER;

/* thread id of RTP proxy */
static pthread_t rtpproxy_tid=0;

/* master fd_set */
static fd_set master_fdset;
static int    master_fd_max;

/* forward declarations */
static void *rtpproxy_main(void *i);
static int rtp_recreate_fdset(void);
void rtpproxy_kill( void );
static void sighdl_alm(int sig) {/* just wake up from select() */};


/*
 * initialize and create rtp_relay proxy thread
 *
 * RETURNS
 *	STS_SUCCESS on success
 */
int rtp_relay_init( void ) {
   int sts;
   int arg=0;
   struct sigaction sigact;
   
   /* cancel RTP thread at exit */
   atexit(rtpproxy_kill);  

   /* clean proxy table */
   memset (rtp_proxytable, 0, sizeof(rtp_proxytable));

   /* initialize fd set for RTP proxy thread */
   FD_ZERO(&master_fdset); /* start with an empty fdset */
   master_fd_max=-1;

   /* install signal handler for SIGALRM - used to wake up
      the rtpproxy thread from select() hibernation */
   sigact.sa_handler = sighdl_alm;
   sigemptyset(&sigact.sa_mask);
   sigact.sa_flags=0;
   sigaction(SIGALRM, &sigact, NULL);

   sts=pthread_create(&rtpproxy_tid, NULL, rtpproxy_main, (void *)&arg);

   return STS_SUCCESS;
}


/*
 * main() of rtpproxy
 */
static void *rtpproxy_main(void *arg) {
   struct timeval tv;
   fd_set fdset;
   int fd_max;
   time_t t, last_t=0;
   int i, sts;
   int num_fd;
   osip_call_id_t callid;
   static char rtp_buff[RTP_BUFFER_SIZE];
   int count;
   struct sockaddr_in from;
   socklen_t fromlen;

   memcpy(&fdset, &master_fdset, sizeof(fdset));
   fd_max=master_fd_max;

   /* loop forever... */
   for (;;) {

      tv.tv_sec = 5;
      tv.tv_usec = 0;

      num_fd=select(fd_max+1, &fdset, NULL, NULL, &tv);
      pthread_testcancel();
      if ((num_fd<0) && (errno==EINTR)) {
         /*
          * wakeup due to a change in the proxy table:
          * lock mutex, copy master FD set and unlock
          */
         pthread_mutex_lock(&rtp_proxytable_mutex);
         memcpy(&fdset, &master_fdset, sizeof(fdset));
         fd_max=master_fd_max;
         pthread_mutex_unlock(&rtp_proxytable_mutex);
         continue;
      }

      time(&t);

      /*
       * LOCK the MUTEX
       */
      pthread_mutex_lock(&rtp_proxytable_mutex);

      /* check for data available and send to destination */
      for (i=0;(i<RTPPROXY_SIZE) && (num_fd>0);i++) {
         if ( (rtp_proxytable[i].rtp_rx_sock != 0) && 
            FD_ISSET(rtp_proxytable[i].rtp_rx_sock, &fdset) ) {
            /* have some data to send */
            num_fd--;

	    /* read from sock rtp_proxytable[i].sock*/
	     fromlen = sizeof(struct sockaddr_in);
            count=recvfrom(rtp_proxytable[i].rtp_rx_sock, &rtp_buff, sizeof(rtp_buff)-1 , 0, (struct sockaddr*)&from, &fromlen);
            rtp_buff[RTP_BUFFER_SIZE] = '\0';
	     printf("RTP Packet from %s:%d\n", inet_ntoa(from.sin_addr), ntohs(from.sin_port));
            if (count < 0) {
               printf("rtp sock read error!\n");
               if (errno == EAGAIN)
                  continue;
            }

            /*
             * forwarding an RTP packet only makes sense if we really
             * have got some data in it (count > 0)
             */
            if (count > 0) {
               /* write nat_ipaddr and nat_port */
               if( rtp_proxytable[i].direction == DIR_OUTGOING) {
                     memcpy(&rtp_proxytable[i].nat_ipaddr, &from.sin_addr, sizeof(struct in_addr));
              	rtp_proxytable[i].nat_port = ntohs(from.sin_port);
                 	//printf("RTPTable: %s:%d\n", inet_ntoa(rtp_proxytable[i].nat_ipaddr), rtp_proxytable[i].nat_port);
               }
               /* find the corresponding TX socket */
               if (rtp_proxytable[i].rtp_tx_sock == 0) {
                  int j;
                  int rtp_direction = rtp_proxytable[i].direction;
                  int media_stream_no = rtp_proxytable[i].media_stream_no;

                  callid.number = rtp_proxytable[i].callid_number;
                  callid.host = rtp_proxytable[i].callid_host;

                  for (j=0;(j<RTPPROXY_SIZE);j++) {
                     char *client_id = rtp_proxytable[i].client_id;
                     osip_call_id_t cid;
                     cid.number = rtp_proxytable[j].callid_number;
                     cid.host = rtp_proxytable[j].callid_host;

                     /* match on:
                      * - same call ID
                      * - same media stream
                      * - opposite direction
                      * - different client ID
                      */
                     if ( (rtp_proxytable[j].rtp_rx_sock != 0) &&
                          (compare_callid(&callid, &cid) == STS_SUCCESS) &&
                          (media_stream_no == rtp_proxytable[j].media_stream_no) &&
                          (rtp_direction != rtp_proxytable[j].direction) &&
                          (strcmp(rtp_proxytable[j].client_id, client_id) != 0) ) {
                        rtp_proxytable[i].rtp_tx_sock = rtp_proxytable[j].rtp_rx_sock;
                        rtp_proxytable[i].opposite_entry=j+1;    
                        printf("media_stream_no:%d----%d\n",media_stream_no,rtp_proxytable[j].media_stream_no);
                        printf("rtp_direction:%d----%d\n",rtp_direction,rtp_proxytable[j].direction);
                        printf("client_id:%s----%s\n",client_id,rtp_proxytable[j].client_id);
                        break;
                     }
                  }
               } /* rtp_tx_sock == 0 */
		 printf("rtp_tx_sock %d\n", rtp_proxytable[i].rtp_tx_sock);       
               if (rtp_proxytable[i].rtp_tx_sock != 0) {
                  /* write to dest via socket rtp_tx_sock */
                  struct sockaddr_in dst_addr;
                  dst_addr.sin_family = AF_INET;
                  if(rtp_proxytable[i].direction == DIR_INCOMING) {      
                  	int j = rtp_proxytable[i].opposite_entry-1;
                  	memcpy(&dst_addr.sin_addr.s_addr,
                         &rtp_proxytable[j].nat_ipaddr, 
                         sizeof(struct in_addr));
                  	dst_addr.sin_port= htons(rtp_proxytable[j].nat_port);
                  	//printf("RTP Packet %s:%d\n", inet_ntoa(rtp_proxytable[j].nat_ipaddr), rtp_proxytable[j].nat_port);
                  }
                  if(rtp_proxytable[i].direction == DIR_OUTGOING) {
			 memcpy(&dst_addr.sin_addr.s_addr,
                         &rtp_proxytable[i].remote_ipaddr, 
                         sizeof(struct in_addr));
                  	 dst_addr.sin_port= htons(rtp_proxytable[i].remote_port);
               	// printf("RTP Packet %s:%d\n", inet_ntoa(rtp_proxytable[i].remote_ipaddr), rtp_proxytable[i].remote_port);
                  } 
                  printf("RTP Packet send to %s:%d\n", inet_ntoa(dst_addr.sin_addr.s_addr), ntohs(dst_addr.sin_port));	
                  sts = sendto(rtp_proxytable[i].rtp_tx_sock, rtp_buff,
                               count, 0, (const struct sockaddr *)&dst_addr,
                               (socklen_t)sizeof(dst_addr));
                  if (sts == -1) {
                     if (errno != ECONNREFUSED) {
                        printf("sendto() [%s:%i size=%i] call failed: %s\n",
                        inet_ntoa(rtp_proxytable[i].remote_ipaddr),
                        rtp_proxytable[i].remote_port, count, strerror(errno));

                    /* if sendto() fails with bad filedescriptor,
                     * this means that the opposite stream has been
                     * canceled or timed out.
                     * we should then cancel this stream as well.*/

                    //printf("stopping opposite stream\n");
                    /* don't lock the mutex, as we own the lock */
                    //callid.number=rtp_proxytable[i].callid_number;
                    //callid.host=rtp_proxytable[i].callid_host;
                    //rtp_relay_stop_fwd(&callid, rtp_proxytable[i].direction, -1, 1);
                    }
                 }
              }
            } /* count > 0 */

            /* update timestamp of last usage for both (RX and TX) entries.
             * This allows silence (no data) on one stream without breaking
             * the connection after the RTP timeout */
            rtp_proxytable[i].timestamp=t;
            if (rtp_proxytable[i].opposite_entry > 0) {
               rtp_proxytable[rtp_proxytable[i].opposite_entry-1].timestamp=t;
            }
         }
      } /* for i */

      /*
       * age and clean rtp_proxytable (check every 10 seconds)
       */
      if (t > (last_t+10) ) {
         last_t = t;
	  for (i=0;i<RTPPROXY_SIZE; i++) {
            if ( (rtp_proxytable[i].rtp_rx_sock != 0) &&
		 ((rtp_proxytable[i].timestamp+args_info.rtp_timeout_arg)<t)) {
               /* this one has expired, clean it up */
               callid.number=rtp_proxytable[i].callid_number;
               callid.host=rtp_proxytable[i].callid_host;
               /* Don't lock the mutex, as we own the lock already here */
               /* Only stop the stream we caught is timeout and not everything. */
               rtp_relay_stop_fwd(&callid, rtp_proxytable[i].direction,
                                  rtp_proxytable[i].media_stream_no, 1);
	    }
	 }
      }

      /* copy master FD set */
      memcpy(&fdset, &master_fdset, sizeof(fdset));
      fd_max=master_fd_max;

      /*
       * UNLOCK the MUTEX
       */
      pthread_mutex_unlock(&rtp_proxytable_mutex);
   } /* for(;;) */

   return NULL;
}


/*
 * start an rtp stream on the proxy
 *
 * RETURNS
 *	STS_SUCCESS on success
 *	STS_FAILURE on error
 */
int rtp_relay_start_fwd (osip_call_id_t *callid, char *client_id,
                         int rtp_direction, int media_stream_no, 
                         struct in_addr local_ipaddr,int *local_port, 
                         struct in_addr remote_ipaddr,int remote_port) {
	static int prev_used_port = 0;
  	int num_ports;
   	int i2, i, j;
   	int sock, port;
  	int freeidx;
   	int sts=STS_SUCCESS;
   	int tos;

⌨️ 快捷键说明

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