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

📄 rtpproxy_relay.c

📁 这是一个C程序
💻 C
📖 第 1 页 / 共 3 页
字号:
                        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 */                        sts = rtp_relay_stop_fwd(&callid,                                                 rtp_proxytable[i].direction,                                                 -1, NOLOCK_FDSET);                        if (sts != STS_SUCCESS) {                           /* force the streams to timeout on next occasion */                           rtp_proxytable[i].timestamp=0;                        }                     }                  }#endif               }            } /* 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=current_tv.tv_sec;            if (rtp_proxytable[i].opposite_entry > 0) {               rtp_proxytable[rtp_proxytable[i].opposite_entry-1].timestamp=                  current_tv.tv_sec;            }         } /* if */      } /* for i */      /*       * age and clean rtp_proxytable (check every 10 seconds)       */      if (current_tv.tv_sec > last_tv.tv_sec) {         last_tv.tv_sec = current_tv.tv_sec + 10 ;         for (i=0;i<RTPPROXY_SIZE; i++) {            if ( (rtp_proxytable[i].rtp_rx_sock != 0) &&                 ((rtp_proxytable[i].timestamp+configuration.rtp_timeout) <                    current_tv.tv_sec)) {               osip_call_id_t callid;               /* this one has expired, clean it up */               callid.number=rtp_proxytable[i].callid_number;               callid.host=rtp_proxytable[i].callid_host;#ifdef USE_DEJITTER               dejitter_cancel(&rtp_proxytable[i]);#endif               INFO("RTP stream %s@%s (media=%i) has expired",                    callid.number, callid.host,                    rtp_proxytable[i].media_stream_no);               DEBUGC(DBCLASS_RTP,"RTP stream rx_sock=%i tx_sock=%i "                      "%s@%s (idx=%i) has expired",                      rtp_proxytable[i].rtp_rx_sock,                      rtp_proxytable[i].rtp_tx_sock,                      callid.number, callid.host, i);               /* Don't lock the mutex, as we own the lock already here */               /* Only stop the stream we caught is timeout and not everything.                * This may be a multiple stream conversation (audio/video) and                * just one (unused?) has timed out. Seen with VoIPEX PBX! */               rtp_relay_stop_fwd(&callid, rtp_proxytable[i].direction,                                  rtp_proxytable[i].media_stream_no,                                  NOLOCK_FDSET);            } /* if */         } /* for i */      } /* if (t>...) */      /* 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, client_id_t 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, int dejitter) {   static int prev_used_port = 0;   int num_ports;   int i2, i, j;   int sock, port;   int sock_con;   int freeidx;   int sts=STS_SUCCESS;   int tos;   osip_call_id_t cid;   if (callid == NULL) {      ERROR("rtp_relay_start_fwd: callid is NULL!");      return STS_FAILURE;   }   /*    * life insurance: check size of received call_id strings    * I don't know what the maximum allowed size within SIP is,    * so if this test fails maybe it's just necessary to increase    * the constants CALLIDNUM_SIZE and/or CALLIDHOST_SIZE.    */   if (callid->number && (strlen(callid->number) >= CALLIDNUM_SIZE)) {      ERROR("rtp_relay_start_fwd: received callid number [%s] "            "has too many characters (%ld, max=%i)",            callid->number, (long)strlen(callid->number),CALLIDNUM_SIZE);      return STS_FAILURE;   }   if (callid->host && (strlen(callid->host) >= CALLIDHOST_SIZE)) {      ERROR("rtp_relay_start_fwd: received callid host [%s] "            "has too many characters (%ld, max=%i)",            callid->host, (long)strlen(callid->host),CALLIDHOST_SIZE);      return STS_FAILURE;   }   DEBUGC(DBCLASS_RTP,"rtp_relay_start_fwd: starting RTP proxy "          "stream for: CallID=%s@%s [Client-ID=%s] (%s) #=%i",          callid->number, callid->host, client_id.contact,          ((rtp_direction == DIR_INCOMING) ? "incoming RTP" : "outgoing RTP"),          media_stream_no);   /* lock mutex */   #define return is_forbidden_in_this_code_section   pthread_mutex_lock(&rtp_proxytable_mutex);   /*    * !! We now have a locked MUTEX! It is forbidden to return() from    * !! here up to the end of this funtion where the MUTEX is    * !! unlocked again.    * !! Per design, a mutex is locked (for one purpose) at *exactly one*    * !! place in the code and unlocked also at *exactly one* place.    * !! this minimizes the risk of deadlocks.    */   /*    * 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) &&         (compare_client_id(rtp_proxytable[i].client_id, client_id) ==            STS_SUCCESS)) {         /*          * The RTP port number reported by the UA MAY change          * for a given media stream          * (seen with KPhone during HOLD/unHOLD)          * Also the destination IP may change during a re-Invite          * (seen with Sipphone.com, re-Invites when using          * the SIP - POTS gateway [SIP Minutes]          */         /* Port number */         if (rtp_proxytable[i].remote_port != remote_port) {            DEBUGC(DBCLASS_RTP,"RTP port number changed %i -> %i",                   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))) {            DEBUGC(DBCLASS_RTP,"RTP IP address changed to %s",                   utils_inet_ntoa(remote_ipaddr));            memcpy (&rtp_proxytable[i].remote_ipaddr, &remote_ipaddr,                     sizeof(remote_ipaddr));         }#ifdef USE_DEJITTER         /* Initialize up timecrontrol for dejitter function */         dejitter_init_time(&rtp_proxytable[i].tc, dejitter);#endif         /* return the already known local port number */         DEBUGC(DBCLASS_RTP,"RTP stream already active idx=%i (remaddr=%s, "                "remport=%i, lclport=%i, id=%s, #=%i)",                i, utils_inet_ntoa(remote_ipaddr),                rtp_proxytable[i].remote_port,                rtp_proxytable[i].local_port,                rtp_proxytable[i].callid_number,                rtp_proxytable[i].media_stream_no);         *local_port=rtp_proxytable[i].local_port;         sts = STS_SUCCESS;	 goto unlock_and_exit;      } /* if already active */   } /* for */   /*    * 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) {      ERROR("rtp_relay_start_fwd: rtp_proxytable is full!");      sts = STS_FAILURE;      goto unlock_and_exit;   }   /* TODO: randomize the port allocation - start at a random offset to         search in the allowed port range (so some modulo stuff w/         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;	/* RTP socket */   sock_con=0;	/* RTCP socket */   port=0;   if ((prev_used_port < configuration.rtp_port_low) ||       (prev_used_port > configuration.rtp_port_high)) {      prev_used_port = configuration.rtp_port_high;   }   num_ports = configuration.rtp_port_high - configuration.rtp_port_low + 1;   for (i2 = (prev_used_port - configuration.rtp_port_low + 1);        i2 < (num_ports + prev_used_port - configuration.rtp_port_low + 1);        i2++) {      i = (i2%num_ports) + configuration.rtp_port_low;      /* 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) {            if (rtp_proxytable[j].local_port == i) break;            if (rtp_proxytable[j].local_port == i + 1) break;            if (rtp_proxytable[j].local_port + 1 == i) break;            if (rtp_proxytable[j].local_port + 1 == i + 1) break;          }      }      /* port is available, try to allocate */      if (j == RTPPROXY_SIZE) {         port=i;         sock=sockbind(local_ipaddr, port, 0);	/* RTP */         if (sock) {            sock_con=sockbind(local_ipaddr, port+1, 0);	/* RTCP */            /* if success break, else try further on */            if (sock_con) break;            sts = close(sock);            DEBUGC(DBCLASS_RTP,"closed socket %i [%i] for RTP stream because "                               "cant get pair sts=%i",                               sock, i, sts);         } /* if sock */      } /* if j */   } /* for i */   prev_used_port = port+1;   DEBUGC(DBCLASS_RTP,"rtp_relay_start_fwd: addr=%s, port=%i, sock=%i, "          "freeidx=%i, input data dejitter buffer=%i usec",           utils_inet_ntoa(local_ipaddr), port, sock, freeidx, dejitter);   /* found an unused port? No -> RTP port pool fully allocated */   if ((port == 0) || (sock == 0) || (sock_con == 0)) {      ERROR("rtp_relay_start_fwd: no RTP port available or bind() failed");      sts = STS_FAILURE;      goto unlock_and_exit;   }   /*&&&: do RTP and RTCP both set DSCP value? */   /* set DSCP value, need to be ROOT */   if (configuration.rtp_dscp) {      int uid,euid;      uid=getuid();      euid=geteuid();      DEBUGC(DBCLASS_RTP,"uid=%i, euid=%i", uid, euid);      if (uid != euid) seteuid(0);      if (geteuid()==0) {         /* now I'm root */         if (!(configuration.rtp_dscp & ~0x3f)) {            tos = (configuration.rtp_dscp << 2) & 0xff;            if(setsockopt(sock, SOL_IP, IP_TOS, &tos, sizeof(tos))) {               ERROR("rtp_relay_start_fwd: setsockopt() failed while "                     "setting DSCP value: %s", strerror(errno));            }         } else {            ERROR("rtp_relay_start_fwd: Invalid DSCP value %d",                  configuration.rtp_dscp);            configuration.rtp_dscp = 0; /* inhibit further attempts */         }      } else {         /* could not get root */         WARN("siproxd not started as root - cannot set DSCP value");         configuration.rtp_dscp = 0; /* inhibit further attempts */      }      /* drop privileges */      if (uid != euid) seteuid(euid);   }   /* write entry into rtp_proxytable slot (freeidx) */   rtp_proxytable[freeidx].rtp_rx_sock=sock;   rtp_proxytable[freeidx].rtp_con_rx_sock = sock_con;   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';   }   /* store the passed Client-ID data */   memcpy(&rtp_proxytable[freeidx].client_id, &client_id, sizeof(client_id_t));   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);#ifdef USE_DEJITTER   /* Initialize up timecrontrol for dejitter function */   dejitter_init_time(&rtp_proxytable[freeidx].tc, dejitter);#endif   *local_port=port;   /* call to firewall API: RTP port */   fwapi_start_rtp(rtp_proxytable[freeidx].direction,                   rtp_proxytable[freeidx].local_ipaddr,                   rtp_proxytable[freeidx].local_port,

⌨️ 快捷键说明

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