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

📄 rtpproxy_relay.c

📁 这是一个C程序
💻 C
📖 第 1 页 / 共 3 页
字号:
                   rtp_proxytable[freeidx].remote_ipaddr,                   rtp_proxytable[freeidx].remote_port);   /* call to firewall API: RTCP port */   fwapi_start_rtp(rtp_proxytable[freeidx].direction,                   rtp_proxytable[freeidx].local_ipaddr,                   rtp_proxytable[freeidx].local_port + 1,                   rtp_proxytable[freeidx].remote_ipaddr,                   rtp_proxytable[freeidx].remote_port + 1);   /* prepare FD set for next select operation */   rtp_recreate_fdset();   /* wakeup/signal rtp_proxythread from select() hibernation */   if (!pthread_equal(rtpproxy_tid, pthread_self()))      pthread_kill(rtpproxy_tid, SIGALRM);//&&&   DEBUGC(DBCLASS_RTP,"rtp_relay_start_fwd: started RTP proxy "          "stream for: CallID=%s@%s [Client-ID=%s] %s #=%i idx=%i",          rtp_proxytable[freeidx].callid_number,          rtp_proxytable[freeidx].callid_host,          rtp_proxytable[freeidx].client_id.contact,          ((rtp_proxytable[freeidx].direction == DIR_INCOMING) ? "incoming RTP" : "outgoing RTP"),          rtp_proxytable[freeidx].media_stream_no, freeidx);unlock_and_exit:   /* unlock mutex */   pthread_mutex_unlock(&rtp_proxytable_mutex);   #undef return   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) {      ERROR("rtp_relay_stop_fwd: callid is NULL!");      return STS_FAILURE;   }   DEBUGC(DBCLASS_RTP,"rtp_relay_stop_fwd: stopping RTP proxy "          "stream for: %s@%s (%s) (nolock=%i)",          callid->number, callid->host,          ((rtp_direction == DIR_INCOMING) ? "incoming" : "outgoing"),          nolock);   /*    * lock 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.    */   #define return is_forbidden_in_this_code_section   if (nolock == 0) {      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.       */   }   /*    * 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))) {         /* close RTP sockets */         sts = close(rtp_proxytable[i].rtp_rx_sock);         DEBUGC(DBCLASS_RTP,"closed socket %i for RTP stream "                "%s:%s == %s:%s  (idx=%i) sts=%i",                rtp_proxytable[i].rtp_rx_sock,                rtp_proxytable[i].callid_number,                rtp_proxytable[i].callid_host,                callid->number, callid->host, i, sts);         if (sts < 0) {            ERROR("Error in close(%i): %s nolock=%i %s:%s\n",                  rtp_proxytable[i].rtp_rx_sock,                  strerror(errno), nolock,                  callid->number, callid->host);         }         /* call to firewall API (RTP port) */         fwapi_stop_rtp(rtp_proxytable[i].direction,                   rtp_proxytable[i].local_ipaddr,                   rtp_proxytable[i].local_port,                   rtp_proxytable[i].remote_ipaddr,                   rtp_proxytable[i].remote_port);         /* close RTCP socket */         sts = close(rtp_proxytable[i].rtp_con_rx_sock);         DEBUGC(DBCLASS_RTP,"closed socket %i for RTCP stream sts=%i",                rtp_proxytable[i].rtp_con_rx_sock, sts);         if (sts < 0) {            ERROR("Error in close(%i): %s nolock=%i %s:%s\n",                  rtp_proxytable[i].rtp_con_rx_sock,                  strerror(errno), nolock,                  callid->number, callid->host);         }         /* call to firewall API (RTCP port) */         fwapi_stop_rtp(rtp_proxytable[i].direction,                   rtp_proxytable[i].local_ipaddr,                   rtp_proxytable[i].local_port + 1,                   rtp_proxytable[i].remote_ipaddr,                   rtp_proxytable[i].remote_port + 1);         /* clean up */         memset(&rtp_proxytable[i], 0, sizeof(rtp_proxytable[0]));         got_match=1;      }   }   /* did not find an active stream... */   if (!got_match) {      DEBUGC(DBCLASS_RTP,             "rtp_relay_stop_fwd: can't find active stream for %s@%s (%s)",             callid->number, callid->host,             ((rtp_direction == DIR_INCOMING) ? "incoming RTP" : "outgoing RTP"));      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);   }   #undef return   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) {         /* RTP */         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;         }         /* RTPCP */         FD_SET(rtp_proxytable[i].rtp_con_rx_sock, &master_fdset);         if (rtp_proxytable[i].rtp_con_rx_sock > master_fd_max) {            master_fd_max=rtp_proxytable[i].rtp_con_rx_sock;         }      }   } /* for i */   return STS_SUCCESS;}/* * kills the rtp_proxy thread * * RETURNS *	- */static 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,                                  LOCK_FDSET);      }   }      /* kill the thread */   if (rtpproxy_tid) {      pthread_cancel(rtpproxy_tid);      pthread_kill(rtpproxy_tid, SIGALRM);      pthread_join(rtpproxy_tid, &thread_status);   }   DEBUGC(DBCLASS_RTP,"killed RTP proxy thread");   return;}/* * match_socket * matches and cross connects two rtp_proxytable entries * (corresponds to the two data directions of one RTP stream) */static void match_socket (int rtp_proxytable_idx) {   int j;   int rtp_direction = rtp_proxytable[rtp_proxytable_idx].direction;   int media_stream_no = rtp_proxytable[rtp_proxytable_idx].media_stream_no;/*chnnel   int channel = rtp_proxytable[rtp_proxytable_idx].channel;*/   osip_call_id_t callid;   callid.number = rtp_proxytable[rtp_proxytable_idx].callid_number;   callid.host = rtp_proxytable[rtp_proxytable_idx].callid_host;   for (j=0;(j<RTPPROXY_SIZE);j++) {      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) /* channel: &&           (channel == rtp_proxytable[j].channel)*/ ) {         rtp_proxytable[rtp_proxytable_idx].rtp_tx_sock = rtp_proxytable[j].rtp_rx_sock;         rtp_proxytable[rtp_proxytable_idx].rtp_con_tx_sock = rtp_proxytable[j].rtp_con_rx_sock;         DEBUGC(DBCLASS_RTP, "connected entry %i (fd=%i) <-> entry %i (fd=%i)",                             j, rtp_proxytable[j].rtp_rx_sock,                             rtp_proxytable_idx,                             rtp_proxytable[rtp_proxytable_idx].rtp_rx_sock);         break;      }   }}/* * error_handler * * rtp_proxytable_idx:	index into the rtp_proxytable array * socket_type: 	1 - RTCP, 0 - RTP */static void error_handler (int rtp_proxytable_idx, int socket_type) {   /*    * It has been seen on linux 2.2.x systems that for some    * reason (ICMP issue? -> below) inside the RTP relay, select()    * claims that a certain file descriptor has data available to    * read, a subsequent call to read() or recv() then does block!!    * So lets make the FD's we are going to use non-blocking, so    * we will at least survive and not run into a deadlock.    *    * We catch this here with this workaround (pronounce "HACK")    * and hope that next time we pass by it will be ok again.    */   if (errno == EAGAIN) {      /* I may want to remove this WARNing */      WARN("read() [fd=%i, %s:%i] would block, but select() "           "claimed to be readable!",           socket_type ? rtp_proxytable[rtp_proxytable_idx].rtp_rx_sock :                          rtp_proxytable[rtp_proxytable_idx].rtp_con_rx_sock,           utils_inet_ntoa(rtp_proxytable[rtp_proxytable_idx].local_ipaddr),           rtp_proxytable[rtp_proxytable_idx].local_port + socket_type);   }   /*    * I *MAY* receive ICMP destination unreachable messages when I    * try to send RTP traffic to a destination that is in HOLD    * (better: is not listening on the UDP port where I send    * my RTP data to).    * So I should *not* do this - or ignore errors originating    * by this -> ECONNREFUSED    *    * Note: This error is originating from a previous send() on the    *       same socket and has nothing to do with the read() we have    *       done above!    */   if (errno != ECONNREFUSED) {      /* some other error that I probably want to know about */      int j;      WARN("read() [fd=%i, %s:%i] returned error [%i:%s]",          socket_type ? rtp_proxytable[rtp_proxytable_idx].rtp_rx_sock :                         rtp_proxytable[rtp_proxytable_idx].rtp_con_rx_sock,          utils_inet_ntoa(rtp_proxytable[rtp_proxytable_idx].local_ipaddr),          rtp_proxytable[rtp_proxytable_idx].local_port + socket_type,          errno, strerror(errno));      for (j=0; j<RTPPROXY_SIZE;j++) {         DEBUGC(DBCLASS_RTP, "%i - rx:%i tx:%i %s@%s dir:%i "                "lp:%i, rp:%i rip:%s",                j,                socket_type ? rtp_proxytable[rtp_proxytable_idx].rtp_rx_sock :                               rtp_proxytable[rtp_proxytable_idx].rtp_con_rx_sock,                socket_type ? rtp_proxytable[rtp_proxytable_idx].rtp_tx_sock :                               rtp_proxytable[rtp_proxytable_idx].rtp_con_tx_sock,                rtp_proxytable[j].callid_number,                rtp_proxytable[j].callid_host,                rtp_proxytable[j].direction,                rtp_proxytable[j].local_port,                rtp_proxytable[j].remote_port,                utils_inet_ntoa(rtp_proxytable[j].remote_ipaddr));      } /* for j */   } /* if errno != ECONNREFUSED */}

⌨️ 快捷键说明

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