Revert "and added files"
[bcm963xx.git] / userapps / opensource / siproxd / src / rtpproxy_relay.c
diff --git a/userapps/opensource/siproxd/src/rtpproxy_relay.c b/userapps/opensource/siproxd/src/rtpproxy_relay.c
deleted file mode 100755 (executable)
index 7344cc2..0000000
+++ /dev/null
@@ -1,903 +0,0 @@
-/*
-    Copyright (C) 2003-2005  Thomas Ries <tries@gmx.net>
-
-    This file is part of Siproxd.
-    
-    Siproxd is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-    
-    Siproxd is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warrantry of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-    
-    You should have received a copy of the GNU General Public License
-    along with Siproxd; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
-*/
-
-#include "config.h"
-
-#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 <netinet/in.h>
-#include <signal.h>
-
-#ifdef HAVE_PTHREAD_SETSCHEDPARAM
-   #include <sched.h>
-#endif
-
-#include <osipparser2/osip_parser.h>
-
-#include "siproxd.h"
-#include "rtpproxy.h"
-#include "log.h"
-
-static char const ident[]="$Id: rtpproxy_relay.c,v 1.30 2005/01/24 19:12:49 hb9xar Exp $";
-
-/* configuration storage */
-extern struct siproxd_config configuration;
-
-/*
- * 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;
-
-   atexit(rtpproxy_kill);  /* cancel RTP thread at exit */
-
-   /* 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);
-
-   DEBUGC(DBCLASS_RTP,"create thread");
-   sts=pthread_create(&rtpproxy_tid, NULL, rtpproxy_main, (void *)&arg);
-   DEBUGC(DBCLASS_RTP,"created, sts=%i", sts);
-
-   /* set realtime scheduling - if started by root */
-#ifdef HAVE_PTHREAD_SETSCHEDPARAM
-   {
-      int uid,euid;
-      struct sched_param schedparam;
-
-#ifndef _CYGWIN
-      uid=getuid();
-      euid=geteuid();
-      DEBUGC(DBCLASS_RTP,"uid=%i, euid=%i", uid, euid);
-      if (uid != euid) seteuid(0);
-
-      if (geteuid()==0) {
-#endif
-
-#if defined(HAVE_SCHED_GET_PRIORITY_MAX) && defined(HAVE_SCHED_GET_PRIORITY_MIN)
-         int pmin, pmax;
-         /* place ourself at 1/3 of the available priority space */
-         pmin=sched_get_priority_min(SCHED_RR);
-         pmax=sched_get_priority_max(SCHED_RR);
-         schedparam.sched_priority=pmin+(pmax-pmin)/3;
-         DEBUGC(DBCLASS_RTP,"pmin=%i, pmax=%i, using p=%i", pmin, pmax,
-                schedparam.sched_priority);
-#else
-         /* just taken a number out of thin air */
-         schedparam.sched_priority=10;
-         DEBUGC(DBCLASS_RTP,"using p=%i", schedparam.sched_priority);
-#endif
-         sts=pthread_setschedparam(rtpproxy_tid, SCHED_RR, &schedparam);
-         if (sts != 0) {
-            ERROR("pthread_setschedparam failed: %s", strerror(errno));
-         }
-#ifndef _CYGWIN
-      } else {
-         INFO("Unable to use realtime scheduling for RTP proxy");
-         INFO("You may want to start siproxd as root and switch UID afterwards");
-      }
-      if (uid != euid)  seteuid(euid);
-#endif
-   }
-#endif
-
-   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;
-   int j;
-
-   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) ) {
-            /* yup, have some data to send */
-            num_fd--;
-
-           /* read from sock rtp_proxytable[i].sock*/
-            count=read(rtp_proxytable[i].rtp_rx_sock, rtp_buff, RTP_BUFFER_SIZE);
-
-            /* check if something went banana */
-            if (count < 0) {
-               /*
-                * 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!",
-                       rtp_proxytable[i].rtp_rx_sock,
-                       utils_inet_ntoa(rtp_proxytable[i].local_ipaddr),
-                       rtp_proxytable[i].local_port);
-                  continue;
-               }
-
-               /*
-                * 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]",
-                  rtp_proxytable[i].rtp_rx_sock,
-                  utils_inet_ntoa(rtp_proxytable[i].local_ipaddr),
-                  rtp_proxytable[i].local_port, 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,
-                            rtp_proxytable[j].rtp_rx_sock,
-                            rtp_proxytable[j].rtp_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 */
-            } /* count < 0 */
-
-            /*
-             * forwarding an RTP packet only makes sense if we really
-             * have got some data in it (count > 0)
-             */
-            if (count > 0) {
-               /* find the corresponding TX socket */
-               if (rtp_proxytable[i].rtp_tx_sock == 0) {
-                  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;
-                        DEBUGC(DBCLASS_RTP, "connected entry %i (fd=%i) <-> entry %i (fd=%i)",
-                               j, rtp_proxytable[j].rtp_rx_sock,
-                               i, rtp_proxytable[i].rtp_rx_sock);
-                        break;
-                     }
-                  }
-               } /* rtp_tx_sock == 0 */
-
-               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;
-                  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);
-
-                  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) {
-                        ERROR("sendto() [%s:%i size=%i] call failed: %s",
-                        utils_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.*/
-
-                    WARN("stopping opposite stream");
-                    /* 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(rtp_proxytable[i].rtp_rx_sock, &callid, rtp_proxytable[i].direction, 1);
-                     }
-                  }
-               }
-               /* in case of rtp_tx_sock is not same as rtp_rx_sock, need update rtp_tx_sock too */
-               for (j=0;(j<RTPPROXY_SIZE);j++) {
-                  if (rtp_proxytable[i].rtp_tx_sock == rtp_proxytable[j].rtp_rx_sock) {
-                     rtp_proxytable[j].timestamp=t;
-                     break;
-                  }
-               }
-            } /* count > 0 */
-
-            /* update timestamp of last usage */
-            rtp_proxytable[i].timestamp=t;
-         }
-
-         /* handle rtcp packet */
-         if ( (rtp_proxytable[i].rtcp_rx_sock != 0) && 
-            FD_ISSET(rtp_proxytable[i].rtcp_rx_sock, &fdset) ) {
-            /* yup, have some data to send */
-            num_fd--;
-
-            /* read from sock rtp_proxytable[i].sock*/
-            count=read(rtp_proxytable[i].rtcp_rx_sock, rtp_buff, RTP_BUFFER_SIZE);
-
-            /*
-             * forwarding an RTP packet only makes sense if we really
-             * have got some data in it (count > 0)
-             */
-            if (count > 0) {
-               /* find the corresponding TX socket */
-               if (rtp_proxytable[i].rtcp_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;
-
-                     if ( (rtp_proxytable[j].rtcp_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].rtcp_tx_sock = rtp_proxytable[j].rtcp_rx_sock;
-                        break;
-                     }
-                  }
-               } /* rtcp_tx_sock == 0 */
-
-               if (rtp_proxytable[i].rtcp_tx_sock != 0) {
-                  /* write to dest via socket rtcp_tx_sock */
-                  struct sockaddr_in dst_addr;
-                  dst_addr.sin_family = AF_INET;
-                  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+1);
-
-                  sts = sendto(rtp_proxytable[i].rtcp_tx_sock, rtp_buff,
-                               count, 0, (const struct sockaddr *)&dst_addr,
-                               (socklen_t)sizeof(dst_addr));
-                  if (sts == -1) {
-                     if (errno != ECONNREFUSED) {
-                        ERROR("sendto() [%s:%i size=%i] call failed: %s",
-                        utils_inet_ntoa(rtp_proxytable[i].remote_ipaddr),
-                        rtp_proxytable[i].remote_port+1, 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.*/
-
-                    WARN("stopping opposite stream");
-                    /* 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(rtp_proxytable[i].rtcp_rx_sock, &callid, rtp_proxytable[i].direction, 1);
-                     }
-                  }
-               }
-            } /* count > 0 */
-
-            /* update timestamp of last usage */
-            rtp_proxytable[i].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+configuration.rtp_timeout)<t)) {
-               /* this one has expired, clean it up */
-               callid.number=rtp_proxytable[i].callid_number;
-               callid.host=rtp_proxytable[i].callid_host;
-               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 */
-               rtp_relay_stop_fwd(rtp_proxytable[i].rtp_rx_sock, &callid, rtp_proxytable[i].direction, 1);
-           }
-        }
-      } /* 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, 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) {
-   int i, j;
-   int sock, port;
-   int freeidx;
-   int sts=STS_SUCCESS;
-   osip_call_id_t cid;
-   int rtcp_sock;
-   
-
-   if (callid == NULL) {
-      ERROR("rtp_relay_start_fwd: callid is NULL!");
-      return STS_FAILURE;
-   }
-
-   if (client_id == NULL) {
-      ERROR("rtp_relay_start_fwd: did not get a client ID!");
-      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)
-          * 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));
-         }
-         /* return the already known local port number */
-         DEBUGC(DBCLASS_RTP,"RTP stream already active (remaddr=%s, "
-                "remport=%i, lclport=%i, id=%s, #=%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;
-      }
-   }
-
-
-   /*
-    * 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;
-   port=0;
-   rtcp_sock=0;
-   for (i=configuration.rtp_port_low; i<=configuration.rtp_port_high; i+=2) {
-      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, 0);
-         /* if success break, else try further on */
-         if (sock) {
-            rtcp_sock=sockbind(local_ipaddr, port+1, 0);
-            if (rtcp_sock)
-                break;
-            else
-                close(sock);
-         }
-      }
-   } /* for i */
-
-   DEBUGC(DBCLASS_RTP,"rtp_relay_start_fwd: addr=%s, port=%i, sock=%i rtcp_sock=%i "
-          "freeidx=%i", utils_inet_ntoa(local_ipaddr), port, sock, rtcp_sock, freeidx);
-
-   /* found an unused port? No -> RTP port pool fully allocated */
-   if ((port == 0) || (sock == 0) || (rtcp_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;
-   rtp_proxytable[freeidx].rtcp_rx_sock=rtcp_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;
-
-   /* call to firewall API */
-   fwapi_start_rtp(rtp_proxytable[freeidx].direction,
-                   rtp_proxytable[freeidx].local_ipaddr,
-                   rtp_proxytable[freeidx].local_port,
-                   rtp_proxytable[freeidx].remote_ipaddr,
-                   rtp_proxytable[freeidx].remote_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 (int rtp_rx_sock, 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)) {
-         if (rtp_rx_sock != 0) {
-            if (rtp_proxytable[i].rtp_rx_sock != rtp_rx_sock) {
-               continue;
-            }
-         }
-         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);
-         }
-         if (rtp_proxytable[i].rtcp_rx_sock) {
-            sts = close(rtp_proxytable[i].rtcp_rx_sock);
-            DEBUGC(DBCLASS_RTP,"closed socket %i for RTP stream "
-                    "%s:%s == %s:%s  (idx=%i) sts=%i",
-                   rtp_proxytable[i].rtcp_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].rtcp_rx_sock,
-                    strerror(errno), nolock,
-                    callid->number, callid->host);
-            }
-         }
-         /* call to firewall API */
-         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);
-         /* 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) {
-         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;
-         }
-      }
-      if (rtp_proxytable[i].rtcp_rx_sock != 0) {
-         FD_SET(rtp_proxytable[i].rtcp_rx_sock, &master_fdset);
-         if (rtp_proxytable[i].rtcp_rx_sock > master_fd_max) {
-              master_fd_max=rtp_proxytable[i].rtcp_rx_sock;
-         }
-      }
-   } /* for i */
-   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(rtp_proxytable[i].rtp_rx_sock, &cid, rtp_proxytable[i].direction, 0);
-      }
-   }
-   
-
-   /* 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;
-}
-