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

📄 rtpproxy_relay.c

📁 siproxd is a proxy/masquerading for the SIP protocal.
💻 C
📖 第 1 页 / 共 2 页
字号:
      return STS_FAILURE;   }   if (client_id == NULL) {      ERROR("rtp_relay_start_fwd: contact header 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 "            "has too many characters (%i, max=%i)",            strlen(callid->number),CALLIDNUM_SIZE);      return STS_FAILURE;   }   if (callid->host && strlen(callid->host) > CALLIDHOST_SIZE) {      ERROR("rtp_relay_start_fwd: received callid host "            "has too many characters (%i, max=%i)",            strlen(callid->host),CALLIDHOST_SIZE);      return STS_FAILURE;   }   if (client_id && strlen(client_id) > CLIENT_ID_SIZE) {      ERROR("rtp_relay_start_fwd: client ID has too many characters "            "(%i, max=%i) (maybe you need to increase CLIENT_ID_SIZE",            strlen(client_id),CLIENT_ID_SIZE);      return STS_FAILURE;   }   DEBUGC(DBCLASS_RTP,"rtp_relay_start_fwd: starting RTP proxy "          "stream for: %s@%s[%s] (%s) #=%i",          callid->number, callid->host, client_id,          ((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) &&         (strcmp(rtp_proxytable[i].client_id, client_id) == 0)) {         /*          * The RTP port number reported by the UA MAY change          * for a given media stream          * (seen with KPhone during HOLD/unHOLD)          */         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;         }         /* return the already known local port number */         DEBUGC(DBCLASS_RTP,"RTP stream already active (raddr=%s, "                "port=%i, id=%s, #=%i)",                utils_inet_ntoa(remote_ipaddr),                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;      }   }   /*    * 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 outbound port number to use and bind to it */   sock=0;   port=0;   for (i=configuration.rtp_port_low; i<=configuration.rtp_port_high; i+=2) {      for (j=0; j<RTPPROXY_SIZE; j++) {         /* outbound 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, 0);         /* if success break, else try further on */         if (sock) break;      }   } /* for i */   DEBUGC(DBCLASS_RTP,"rtp_relay_start_fwd: addr=%s, port=%i, sock=%i "          "freeidx=%i", utils_inet_ntoa(local_ipaddr), port, sock, freeidx);   /* found an unused port? No -> RTP port pool fully allocated */   if ((port == 0) || (sock == 0)) {      ERROR("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();   /* 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);   #undef return   return sts;}/* * stop a rtp stream on the proxy * * RETURNS *	STS_SUCCESS on success *	STS_FAILURE on error */int rtp_relay_stop_fwd (osip_call_id_t *callid,                        int rtp_direction, 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)",          callid->number, callid->host,          ((rtp_direction == DIR_INCOMING) ? "incoming" : "outgoing"));   /*    * 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 strema active for the same callid (audio + video stream)    */   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)) {         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);         }         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) {         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;	 }      }   } /* for i */   return STS_SUCCESS;}/* * kills the rtp_proxy thread * * RETURNS *	- */void rtpproxy_kill( void ) {   void *thread_status;   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;}

⌨️ 快捷键说明

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