- released 0.3.6

- code cleanup for UDP masquerading tunnels
This commit is contained in:
Thomas Ries
2003-09-22 20:33:16 +00:00
parent a19661887f
commit 196e6efe6d
12 changed files with 681 additions and 588 deletions
+8 -2
View File
@@ -1,7 +1,13 @@
0.3.6
=====
07-Sep-2003: - IPCHAINS based UPD tunneling (kernel masquerading)
for RTP traffic (still experimental - but seems to work)
22-Sep-2003: - released 0.3.6
- Code cleanup for RTP proxy
07-Sep-2003: - IPCHAINS based UDP tunneling (kernel masquerading)
for RTP traffic (still experimental - but seems to work).
To activate it, just set 'rtp_proxy_enable' equal 2
in the config. NOTE: siproxd must then be started by
root (but dropping privileges works).
05-Sep-2003: - configure.in: test for pthreads before libosip (RH9.0)
0.3.5
=====
+5 -16
View File
@@ -22,16 +22,7 @@ IP addresses and port numbers.
REQUIREMENTS
============
- libosip2-2.0.2 (http://www.fsf.org/software/osip/)
- pthreads (should be part of any Linux distribution)
Up to now, siporxd only has been tested under:
- Redhat Linux 6.0
- Redhat Linux 7.2
- SUSE 5.3 (libc5)
However, it should build and run under newer versions (feedback is welcome).
see RELNOTES
HOW TO GET STARTED
@@ -210,12 +201,10 @@ and visit the website at http://siproxd.sourceforge.net/
There is a siproxd mailinglist available on sourceforge.
Thomas Ries (tries@gmx.net)
GnuPG Public Key:
pub 1024D/87BCDC94 2000-03-19 Thomas Ries (tries@gmx.net)
Key fingerprint = 13D1 19F5 77D0 4CEC 8D3F A24E 09FC C18A 87BC DC94
VoIP: 17476691342@proxy01.sipphone.com
GnuPG: pub 1024D/87BCDC94 2000-03-19 Thomas Ries <tries@gmx.net>
- Fingerprint = 13D1 19F5 77D0 4CEC 8D3F A24E 09FC C18A 87BC DC94
- Key via pgp.openpkg.org / http://www.ries.ch.vu/87BCDC94.pub
VoIP: sip:17476691342@proxy01.sipphone.com | sip:thomas@ries.homeip.net
CREDITS
+7 -15
View File
@@ -1,4 +1,4 @@
Release Notes for siproxd-0.3.5
Release Notes for siproxd-0.3.6
===============================
- Fli4l OPT_SIP (still experimental) available, check
@@ -8,6 +8,7 @@ Release Notes for siproxd-0.3.5
masquerading firewall
- Includes an RTP data stream proxy for *incoming* audio data
(outgoing RTP data should be handled by IP masquerading by the firewall)
- Includes Linux/IPCHAINS support for UDP masquerading tunnels as RTP proxy
- Port range to be used for incoming RTP traffic is configurable
(-> easy to set up apropriate firewall rules for incoming traffic)
- RTP proxy can handle multiple RTP streams (eg. audio + video)
@@ -20,7 +21,7 @@ Release Notes for siproxd-0.3.5
with individual passwords for each user
- Logging to syslog in daemon mode
- Access control (IP based) for incoming traffic
- RPM support (release includes SRC rpm and binary RPMS for Redhat 6.0, 7.2)
- RPM support
- works with "dial-up" conenctions (dynamic IP addresses)
- The host part of UA registration entries can be masqueraded
(mask_host, masked_host config items) Siemens SIP phones seem to
@@ -43,6 +44,7 @@ Reported to build on:
- OpenBSD 2.9
Reported interoperability (tested with softphones):
- Grandstream BudgeTone-100 series (they only work with IPCHAINS RTP proxy)
- Linphone (local and remote UA) (http://www.linphone.org)
- Kphone (local and remote UA) (http://www.wirlab.net/kphone/)
- MSN messenger 4.6 (remote and local UA)
@@ -58,24 +60,14 @@ Known bugs:
-----
md5sum for siproxd-0.3.5.tar.gz: 8db82f78bf71a04570a85bf897f5d5e5
md5sum for siproxd-0.3.5-1rh60.i386.rpm:5bfe3403b00d2c19af5ca38ea7111337
md5sum for siproxd-0.3.5-1rh72.i386.rpm:3e45667fe56608fdf5f641ffc2a7a602
md5sum for siproxd-0.3.5-1.src.rpm: cde88a553cc8fc20ede2bca0d694d5c9
md5sum for siproxd-0.3.6.tar.gz:
GnuPG signature for siproxd-0.3.5.tar.gz archive:
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)
iD8DBQA/UNGOCfzBioe83JQRAgloAKCaMZGhuqpWMio1vVYmzGm4BcpWSACfZlrb
y2OJ7ZqlqO8P8yLlCMOHdbo=
=sPU3
-----END PGP SIGNATURE-----
GnuPG signature for siproxd-0.3.6.tar.gz archive:
GnuPG: pub 1024D/87BCDC94 2000-03-19 Thomas Ries <tries@gmx.net>
- Fingerprint = 13D1 19F5 77D0 4CEC 8D3F A24E 09FC C18A 87BC DC94
- Key via pgp.openpkg.org / http://www.ries.ch.vu/87BCDC94.pub
VoIP: sip:17476691342@proxy01.sipphone.com
VoIP: sip:17476691342@proxy01.sipphone.com | sip:thomas@ries.homeip.net
-7
View File
@@ -32,11 +32,4 @@ TODOs, in random order:
- feature: don't bind to 0.0.0.0 address, but only to inbound/outbound IF's
(defined by IFNAME)
- support for "full duplex" RTP proxying
- optional: instead of using the RTP proxy, open up UDP masquerading
tunnels in the firewall and let the kernel do the work.
Anyway, there seems to be an issue with some hardphones (BudgeTone-100)
that do not work with the RTP proxy (no audio reception)
- maybe STUN support
+11
View File
@@ -159,6 +159,17 @@ A: Yes. Siproxd needs to know the public IP address, as this address is
7070 - 7079). Outgoing UDP packets must be masqueraded by the firewall.
See 'Q: How do I setup IP masquerading for the outgoing RTP traffic'.
---------------------------------------------------------------------------
Q: How do I configure siproxd to use ICPHAINS based UDP masquerading
tunnels for proxying the incomming RTP traffic?
A: Simple. In the config file set the configuration option
rtp_proxy_enable = 2. Siproxd *must* then be started by root, I
highly recommend to let siproxd drop privileges after startup
(user, chrootjail config options).
Note: The UDP port range for incomming RTP data still uses the same
range as configured in the config file.
---------------------------------------------------------------------------
yet unstructured:
+2 -2
View File
@@ -166,7 +166,7 @@ INFO("stopping RTP proxy stream for: %s@%s",
osip_message_get_call_id(request)->host);
#endif
/* stop the RTP proxying stream */
rtp_stop_fwd(osip_message_get_call_id(request), 0);
rtp_stop_fwd(osip_message_get_call_id(request));
}
break;
@@ -241,7 +241,7 @@ INFO("stopping RTP proxy stream for: %s@%s",
/* if this is CANCEL/BYE request, stop RTP proxying */
if (MSG_IS_BYE(request) || MSG_IS_CANCEL(request)) {
rtp_stop_fwd(osip_message_get_call_id(request), 0);
rtp_stop_fwd(osip_message_get_call_id(request));
}
break;
+39 -476
View File
@@ -20,17 +20,7 @@
#include "config.h"
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <osipparser2/osip_parser.h>
@@ -45,179 +35,29 @@ static char const ident[]="$Id: " __FILE__ ": " PACKAGE "-" VERSION "-"\
/* configuration storage */
extern struct siproxd_config configuration;
/* use a 'fast' mutex for synchronizing - as these are portable... */
pthread_mutex_t rtp_proxytable_mutex = PTHREAD_MUTEX_INITIALIZER;
/*
* table to remember all active rtp proxy streams
*/
rtp_proxytable_t rtp_proxytable[RTPPROXY_SIZE];
/* thread id of RTP proxy */
pthread_t rtpproxy_tid=0;
/* master fd_set */
static fd_set master_fdset;
static int master_fd_max;
/* forward declarations */
void *rtpproxy_main(void *i);
int rtp_recreate_fdset(void);
void sighdl_alm(int sig) {/* do nothing, just wake up from select() */};
/*
* initialize and create rtp_proxy thread
* initialize and create rtp_proxy
*
* RETURNS
* STS_SUCCESS on success
*/
int rtpproxy_init( void ) {
int sts;
int arg=0;
struct sigaction sigact;
int sts=STS_FAILURE;
/* clean proxy table */
memset (rtp_proxytable, 0, sizeof(rtp_proxytable));
if (configuration.rtp_proxy_enable == 0) {
sts = STS_SUCCESS;
} else if (configuration.rtp_proxy_enable == 1) { // Relay
sts = rtp_relay_init ();
} else if (configuration.rtp_proxy_enable == 2) { // MASQ tunnels
sts = rtp_masq_init ();
} else {
ERROR("CONFIG: rtp_proxy_enable has invalid value",
configuration.rtp_proxy_enable);
}
/* 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);
return STS_SUCCESS;
return sts;
}
/*
* main() of rtpproxy
*/
void *rtpproxy_main(void *arg) {
struct timeval tv;
fd_set fdset;
int fd_max;
time_t t, last_t=0;
int i;
int num_fd;
osip_call_id_t callid;
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);
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;
}
#ifdef MOREDEBUG /*&&&&*/
if (num_fd<0) {
int i;
WARN("select() returned error [%s]",strerror(errno));
for (i=0;i<RTPPROXY_SIZE;i++) {
DEBUGC(DBCLASS_RTP,"maxfd=%i",master_fd_max);
if (rtp_proxytable[i].sock != 0) {
DEBUGC(DBCLASS_RTP,"[%i] -> socket=%i",i, rtp_proxytable[i].sock);
}
} /* for i */
}
#endif
time(&t);
/*
* LOCK the MUTEX
*/
pthread_mutex_lock(&rtp_proxytable_mutex);
/*
* RTP relay configured
*/
if (configuration.rtp_proxy_enable == 1) {
/* do the relaying of received UDP packets */
rtp_relay(num_fd, &fdset, t);
}
/*
* RTP masquerading configured
*/
#if 0
if (configuration.rtp_proxy_enable == 2) {
/* do the masquerading - which means nothing here.
* we only have to care that the UDP tunnels are
* opened and closed */
/* &&&&
actually we have a problem here - as the incomming
RTP data is out of our hands, how shall I know if
this RTP stream now really has timed out or not...
We might do a 'poll' for the local maddr & mport
if it is still occupied.
So... what do we do here? I think for now I just let
the RTP stream expire and finished.
*/
}
#endif
/*
* 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].sock != 0) &&
(rtp_proxytable[i].timestamp+configuration.rtp_timeout)<t) {
/* time 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 sock=%i %s@%s (idx=%i) "
"has expired", rtp_proxytable[i].sock,
callid.number, callid.host, i);
rtp_stop_fwd(&callid, 1); /* don't lock the mutex, as we own
the lock already here */
}
}
} /* 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;
}
/*
* helper routines to control the RTP proxy thread
*/
/*
* start an rtp stream on the proxy
*
@@ -228,161 +68,23 @@ if (num_fd<0) {
int rtp_start_fwd (osip_call_id_t *callid, int media_stream_no,
struct in_addr outbound_ipaddr, int *outboundport,
struct in_addr lcl_client_ipaddr, int lcl_clientport) {
int j;
int sock, port;
int freeidx;
int sts=STS_SUCCESS;
int sts=STS_FAILURE;
if (configuration.rtp_proxy_enable == 0) return STS_SUCCESS;
if (callid == NULL) {
ERROR("rtp_start_fwd: callid is NULL!");
return STS_FAILURE;
if (configuration.rtp_proxy_enable == 0) {
sts = STS_SUCCESS;
} else if (configuration.rtp_proxy_enable == 1) { // Relay
sts = rtp_relay_start_fwd (callid, media_stream_no,
outbound_ipaddr, outboundport,
lcl_client_ipaddr, lcl_clientport);
} else if (configuration.rtp_proxy_enable == 2) { // MASQ tunnels
sts = rtp_masq_start_fwd (callid, media_stream_no,
outbound_ipaddr, outboundport,
lcl_client_ipaddr, lcl_clientport);
} else {
ERROR("CONFIG: rtp_proxy_enable has invalid value",
configuration.rtp_proxy_enable);
}
/*
* 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 (strlen(callid->number) > CALLIDNUM_SIZE) {
ERROR("rtp_start_fwd: received callid number "
"has too many characters (%i, max=%i)",
strlen(callid->number),CALLIDNUM_SIZE);
return STS_FAILURE;
}
if (strlen(callid->host) > CALLIDHOST_SIZE) {
ERROR("rtp_start_fwd: received callid host "
"has too many characters (%i, max=%i)",
strlen(callid->host),CALLIDHOST_SIZE);
return STS_FAILURE;
}
DEBUGC(DBCLASS_RTP,"starting RTP proxy stream for: %s@%s #=%i",
callid->number, callid->host, 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 and
* media_stream_no). This can be due to UDP repetitions of the
* INVITE request...
*/
for (j=0; j<RTPPROXY_SIZE; j++) {
if((strcmp(rtp_proxytable[j].callid_number, callid->number)==0) &&
(strcmp(rtp_proxytable[j].callid_host, callid->host)==0) &&
(rtp_proxytable[j].media_stream_no == media_stream_no) ) {
/* return the already known port number */
DEBUGC(DBCLASS_RTP,"RTP stream already active (port=%i, "
"id=%s, #=%i)", rtp_proxytable[j].outboundport,
rtp_proxytable[j].callid_number,
rtp_proxytable[j].media_stream_no);
*outboundport=rtp_proxytable[j].outboundport;
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].sock==0) {
freeidx=j;
break;
}
}
/* rtp_proxytable port pool full? */
if (freeidx == -1) {
ERROR("rtp_start_fwd: rtp_proxytable is full!");
sts = STS_FAILURE;
goto unlock_and_exit;
}
/*
* RTP relay configured
*/
if (configuration.rtp_proxy_enable == 1) {
sts = rtp_relay_start_fwd(&sock, &port, outbound_ipaddr);
/* could bind to desired port? */
if (sock == 0) {
ERROR("rtp_start_fwd: unable to bind to outbound port!");
sts = STS_FAILURE;
goto unlock_and_exit;
}
}
/*
* RTP masquerading configured
*/
if (configuration.rtp_proxy_enable == 2) {
/* do the masquerading - which means to open up
* an UDP tunnel in the firewall within the desired range */
sts = rtp_masq_start_fwd(freeidx, outbound_ipaddr, &port,
lcl_client_ipaddr, lcl_clientport);
if (sts != STS_SUCCESS) {
ERROR("rtp_start_fwd: unable to create masquerading tunnel!");
sts = STS_FAILURE;
goto unlock_and_exit;
}
sock=1; /* 0 indicates 'not allocated' - so we simply put in non-zero */
}
DEBUGC(DBCLASS_RTP,"rtp_start_fwd: port=%i, sock=%i freeidx=%i",
port, sock, freeidx);
/* found an unused port? No -> RTP port pool fully allocated */
if (port == 0) {
ERROR("rtp_start_fwd: no RTP port available. Check rtp_port_* config!");
sts = STS_FAILURE;
goto unlock_and_exit;
}
/* write entry into rtp_proxytable slot (freeidx) */
rtp_proxytable[freeidx].sock=sock;
strcpy(rtp_proxytable[freeidx].callid_number, callid->number);
strcpy(rtp_proxytable[freeidx].callid_host, callid->host);
rtp_proxytable[freeidx].media_stream_no = media_stream_no;
memcpy(&rtp_proxytable[freeidx].outbound_ipaddr,
&outbound_ipaddr, sizeof(struct in_addr));
rtp_proxytable[freeidx].outboundport=port;
memcpy(&rtp_proxytable[freeidx].inbound_client_ipaddr,
&lcl_client_ipaddr, sizeof(struct in_addr));
rtp_proxytable[freeidx].inbound_client_port=lcl_clientport;
time(&rtp_proxytable[freeidx].timestamp);
*outboundport=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;
}
@@ -394,158 +96,19 @@ unlock_and_exit:
* STS_SUCCESS on success
* STS_FAILURE on error
*/
int rtp_stop_fwd (osip_call_id_t *callid, int nolock) {
int i, sts;
int retsts=STS_SUCCESS;
int got_match=0;
if (configuration.rtp_proxy_enable == 0) return STS_SUCCESS;
int rtp_stop_fwd (osip_call_id_t *callid) {
int sts = STS_FAILURE;
if (callid == NULL) {
ERROR("rtp_stop_fwd: callid is NULL!");
return STS_FAILURE;
if (configuration.rtp_proxy_enable == 0) {
sts = STS_SUCCESS;
} else if (configuration.rtp_proxy_enable == 1) { // Relay
sts = rtp_relay_stop_fwd(callid, 0);
} else if (configuration.rtp_proxy_enable == 2) { // MASQ tunnels
sts = rtp_masq_stop_fwd(callid);
} else {
ERROR("CONFIG: rtp_proxy_enable has invalid value",
configuration.rtp_proxy_enable);
}
DEBUGC(DBCLASS_RTP,"stopping RTP proxy stream for: %s@%s",
callid->number, callid->host);
/*
* 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++) {
if ((callid->number==NULL) && (callid->host==NULL)) break;
if( rtp_proxytable[i].sock &&
(strcmp(rtp_proxytable[i].callid_number, callid->number)==0) &&
(strcmp(rtp_proxytable[i].callid_host, callid->host)==0) ) {
/*
* RTP relay configured
*/
if (configuration.rtp_proxy_enable == 1) {
sts = rtp_relay_stop_fwd(rtp_proxytable[i].sock);
DEBUGC(DBCLASS_RTP,"closed socket %i for RTP stream "
"%s:%s == %s:%s (idx=%i) sts=%i",
rtp_proxytable[i].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].sock,
strerror(errno), nolock,
callid->number, callid->host);
}
}
/*
* RTP masquerading configured
*/
if (configuration.rtp_proxy_enable == 2) {
/* do the masquerading - which means to open up
* an UDP tunnel in the firewall within the desired range */
sts = rtp_masq_stop_fwd(i);
}
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_stop_fwd: can't find active stream for %s@%s",
callid->number, callid->host);
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)
*/
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].sock != 0) {
FD_SET(rtp_proxytable[i].sock, &master_fdset);
if (rtp_proxytable[i].sock > master_fd_max) {
master_fd_max=rtp_proxytable[i].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_join(rtpproxy_tid, &thread_status);
}
DEBUGC(DBCLASS_RTP,"killed RTP proxy thread");
return;
return sts;
}
+10 -7
View File
@@ -36,15 +36,18 @@ typedef struct {
/*
* RTP relay
*/
void rtp_relay (int num_fd, fd_set *fdset, time_t t);
int rtp_relay_start_fwd(int *sock, int *port, struct in_addr outbound_ipaddr);
int rtp_relay_stop_fwd(int sock);
int rtp_relay_init(void);
int rtp_relay_start_fwd (osip_call_id_t *callid, int media_stream_no,
struct in_addr outbound_ipaddr, int *outboundport,
struct in_addr lcl_client_ipaddr, int lcl_clientport);
int rtp_relay_stop_fwd (osip_call_id_t *callid, int nolock);
/*
* RTP masquerading
*/
int rtp_masq_start_fwd(int proxy_idx,
struct in_addr outbound_ipaddr, int *outbound_lcl_port,
struct in_addr lcl_client_ipaddr, int lcl_clientport);
int rtp_masq_stop_fwd(int proxy_idx);
int rtp_masq_init(void);
int rtp_masq_start_fwd (osip_call_id_t *callid, int media_stream_no,
struct in_addr outbound_ipaddr, int *outboundport,
struct in_addr lcl_client_ipaddr, int lcl_clientport);
int rtp_masq_stop_fwd (osip_call_id_t *callid);
+162 -13
View File
@@ -60,18 +60,21 @@ extern rtp_proxytable_t rtp_proxytable[];
/* socket for controlling the MASQ tunnels */
static int masq_ctl_sock=0;
/*
* table to remember all active rtp proxy streams
*/
rtp_proxytable_t rtp_proxytable[RTPPROXY_SIZE];
/* table to remember all masquerading tunnels (1:1 with rtp_proxytable) */
struct ip_masq_ctl masq_table[RTPPROXY_SIZE];
/*
* local prototypes
*/
int _create_listening_masq(struct ip_masq_ctl *masq,
static int _create_listening_masq(struct ip_masq_ctl *masq,
struct in_addr lcl_addr, int lcl_port,
struct in_addr msq_addr, int msq_port);
int _delete_listening_masq(struct ip_masq_ctl *masq);
/************************************************************
THIS HERE WILL ONLY WORK IF SIPROXD IS STARTED SUID ROOT !!
However it is working when started root and then changed
@@ -79,19 +82,123 @@ int _delete_listening_masq(struct ip_masq_ctl *masq);
we need to fiddle with the masquerading
*************************************************************/
int rtp_masq_start_fwd(int proxy_idx,
/*
* initialize rtp_masq
*
* RETURNS
* STS_SUCCESS on success
*/
int rtp_masq_init( void ) {
/* clean proxy table */
memset (rtp_proxytable, 0, sizeof(rtp_proxytable));
return STS_SUCCESS;
}
int rtp_masq_start_fwd(osip_call_id_t *callid, int media_stream_no,
struct in_addr outbound_ipaddr, int *outbound_lcl_port,
struct in_addr lcl_client_ipaddr, int lcl_clientport) {
int sts, i;
DEBUGC(DBCLASS_RTP,"rtp_masq_start_fwd: local UA:%s:%i",
inet_ntoa(lcl_client_ipaddr),lcl_clientport);
int freeidx;
time_t t;
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 (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 (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;
}
/*
* Age proxy table:
* Just throw out expired (timed out) records. The proxy table
* here for the MASQ module is only used to eliminate "doubles"
* during INVITE/ACK. Later on, managing (aging & cleaning) the
* masquerading tunnels is done by the kernel (IPMASQ).
*/
time(&t);
for (i=0; i<RTPPROXY_SIZE; i++) {
if ( (rtp_proxytable[i].sock != 0) &&
((rtp_proxytable[i].timestamp+configuration.rtp_timeout)<t)) {
/* this one has expired, clean it up */
DEBUGC(DBCLASS_RTP,"cleaning proxy slot #%i %s@%s", i,
rtp_proxytable[i].callid_number,
rtp_proxytable[i].callid_host);
memset(&rtp_proxytable[i], 0, sizeof(rtp_proxytable[0]));
}
}
DEBUGC(DBCLASS_RTP,"rtp_masq_start_fwd: starting RTP proxy "
"stream for: %s@%s #=%i",
callid->number, callid->host, media_stream_no);
/*
* figure out, if this is an request to start an RTP proxy stream
* that is already existing (identified by SIP Call-ID and
* media_stream_no). This can be due to UDP repetitions of the
* INVITE request...
*/
for (i=0; i<RTPPROXY_SIZE; i++) {
if((strcmp(rtp_proxytable[i].callid_number, callid->number)==0) &&
(strcmp(rtp_proxytable[i].callid_host, callid->host)==0) &&
(rtp_proxytable[i].media_stream_no == media_stream_no) ) {
/* return the already known port number */
DEBUGC(DBCLASS_RTP,"RTP stream already active (port=%i, "
"id=%s, #=%i)", rtp_proxytable[i].outboundport,
rtp_proxytable[i].callid_number,
rtp_proxytable[i].media_stream_no);
return STS_SUCCESS;
}
}
/*
* find first free slot in rtp_proxytable
*/
freeidx=-1;
for (i=0; i<RTPPROXY_SIZE; i++) {
if (rtp_proxytable[i].sock==0) {
freeidx=i;
break;
}
}
/* rtp_proxytable port pool full? */
if (freeidx == -1) {
ERROR("rtp_masq_start_fwd: rtp_proxytable is full!");
return STS_FAILURE;
}
/*
* do loop over the range of available ports (7070-...) until able to
* allocate a UDP tunnel. If not successful - Buh! return port=0
*/
for (i=configuration.rtp_port_low; i<=configuration.rtp_port_high; i++) {
*outbound_lcl_port=i;
sts = _create_listening_masq(&masq_table[proxy_idx],
sts = _create_listening_masq(&masq_table[freeidx],
lcl_client_ipaddr, lcl_clientport,
outbound_ipaddr, *outbound_lcl_port);
/* if success break, else try further on */
@@ -99,21 +206,66 @@ int rtp_masq_start_fwd(int proxy_idx,
*outbound_lcl_port=0;
} /* for i */
if (*outbound_lcl_port) {
/* write entry into rtp_proxytable slot (freeidx) */
DEBUGC(DBCLASS_RTP,"rtp_masq_start_fwd: using proxy slot %i",freeidx);
rtp_proxytable[freeidx].sock=1;
strcpy(rtp_proxytable[freeidx].callid_number, callid->number);
strcpy(rtp_proxytable[freeidx].callid_host, callid->host);
rtp_proxytable[freeidx].media_stream_no = media_stream_no;
memcpy(&rtp_proxytable[freeidx].outbound_ipaddr,
&outbound_ipaddr, sizeof(struct in_addr));
rtp_proxytable[freeidx].outboundport=*outbound_lcl_port;
memcpy(&rtp_proxytable[freeidx].inbound_client_ipaddr,
&lcl_client_ipaddr, sizeof(struct in_addr));
rtp_proxytable[freeidx].inbound_client_port=lcl_clientport;
time(&rtp_proxytable[freeidx].timestamp);
}
DEBUGC(DBCLASS_RTP,"rtp_masq_start_fwd: masq address & port:%s:%i",
inet_ntoa(outbound_ipaddr),outbound_lcl_port);
return (*outbound_lcl_port)?STS_SUCCESS:STS_FAILURE;
}
int rtp_masq_stop_fwd(int proxy_idx) {
return _delete_listening_masq(&masq_table[proxy_idx]);
int rtp_masq_stop_fwd(osip_call_id_t *callid) {
int i;
int got_match=0;
/* let the UDP tunnel time-out */
if (callid == NULL) {
ERROR("rtp_relay_stop_fwd: callid is NULL!");
return STS_FAILURE;
}
for (i=0; i<RTPPROXY_SIZE; i++) {
if ((callid->number==NULL) || (callid->host==NULL)) break;
if( rtp_proxytable[i].sock &&
(strcmp(rtp_proxytable[i].callid_number, callid->number)==0) &&
(strcmp(rtp_proxytable[i].callid_host, callid->host)==0) ) {
DEBUGC(DBCLASS_RTP,"rtp_masq_stop_fwd: cleaning proxy slot %i",i);
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_masq_stop_fwd: can't find active stream for %s@%s",
callid->number, callid->host);
return STS_FAILURE;
}
return STS_SUCCESS;
}
/*
* helper routines
*/
int _create_listening_masq(struct ip_masq_ctl *masq,
static int _create_listening_masq(struct ip_masq_ctl *masq,
struct in_addr lcl_addr, int lcl_port,
struct in_addr msq_addr, int msq_port) {
int uid,euid;
@@ -180,9 +332,6 @@ exit:
return sts;
}
int _delete_listening_masq(struct ip_masq_ctl *masq) {
return STS_SUCCESS;
}
#else
/*
* don't have ipchains or iptables - dummy routines and complain
+434 -31
View File
@@ -20,13 +20,17 @@
#include "config.h"
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
//#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <osipparser2/osip_parser.h>
@@ -44,58 +48,281 @@ extern struct siproxd_config configuration;
/*
* table to remember all active rtp proxy streams
*/
extern rtp_proxytable_t rtp_proxytable[];
rtp_proxytable_t rtp_proxytable[RTPPROXY_SIZE];
/* use a 'fast' mutex for synchronizing - as these are portable... */
pthread_mutex_t rtp_proxytable_mutex = PTHREAD_MUTEX_INITIALIZER;
/* thread id of RTP proxy */
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() */};
void rtp_relay (int num_fd, fd_set *fdset, time_t t) {
int i;
int count;
/*
* 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);
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 int rtp_socket=0;
static char rtp_buff[RTP_BUFFER_SIZE];
/* check for data available and send to destination */
for (i=0;(i<RTPPROXY_SIZE) && (num_fd>0);i++) {
if ( (rtp_proxytable[i].sock != 0) &&
FD_ISSET(rtp_proxytable[i].sock, fdset) ) {
/* yup, have some data to send */
int count;
/* read from sock rtp_proxytable[i].sock*/
count=read(rtp_proxytable[i].sock, rtp_buff, RTP_BUFFER_SIZE);
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);
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;
}
#ifdef MOREDEBUG /*&&&&*/
if (num_fd<0) {
int i;
WARN("select() returned error [%s]",strerror(errno));
for (i=0;i<RTPPROXY_SIZE;i++) {
DEBUGC(DBCLASS_RTP,"maxfd=%i",master_fd_max);
if (rtp_proxytable[i].sock != 0) {
DEBUGC(DBCLASS_RTP,"[%i] -> socket=%i",i, rtp_proxytable[i].sock);
}
} /* for i */
}
#endif
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].sock != 0) &&
FD_ISSET(rtp_proxytable[i].sock, &fdset) ) {
/* yup, have some data to send */
/* read from sock rtp_proxytable[i].sock*/
count=read(rtp_proxytable[i].sock, rtp_buff, RTP_BUFFER_SIZE);
#ifdef MOREDEBUG /*&&&&*/
if (count<0) {WARN("read() returned error [%s]",strerror(errno));}
#endif
/* write to dest via socket rtp_inbound*/
sts=sipsock_send_udp(&rtp_socket,
/* write to dest via socket rtp_inbound*/
sts = sipsock_send_udp(&rtp_socket,
rtp_proxytable[i].inbound_client_ipaddr,
rtp_proxytable[i].inbound_client_port,
rtp_buff, count, 0); /* don't dump it */
#ifdef MOREDEBUG /*&&&&*/
if (sts != STS_SUCCESS) {WARN("sipsock_send_udp() returned error");}
#endif
/* update timestamp of last usage */
rtp_proxytable[i].timestamp=t;
/* update timestamp of last usage */
rtp_proxytable[i].timestamp=t;
num_fd--;
}
} /* for i */
num_fd--;
}
} /* 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].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 sock=%i %s@%s (idx=%i) "
"has expired", rtp_proxytable[i].sock,
callid.number, callid.host, i);
rtp_relay_stop_fwd(&callid, 1); /* don't lock the mutex, as we own
the lock already here */
}
}
} /* 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;
}
int rtp_relay_start_fwd(int *sock, int *port, struct in_addr outbound_ipaddr) {
/*
* 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, int media_stream_no,
struct in_addr outbound_ipaddr, int *outboundport,
struct in_addr lcl_client_ipaddr, int lcl_clientport) {
int i, j;
int sock, port;
int freeidx;
int sts=STS_SUCCESS;
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 (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 (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;
}
DEBUGC(DBCLASS_RTP,"starting RTP proxy stream for: %s@%s #=%i",
callid->number, callid->host, 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 and
* media_stream_no). This can be due to UDP repetitions of the
* INVITE request...
*/
for (j=0; j<RTPPROXY_SIZE; j++) {
if((strcmp(rtp_proxytable[j].callid_number, callid->number)==0) &&
(strcmp(rtp_proxytable[j].callid_host, callid->host)==0) &&
(rtp_proxytable[j].media_stream_no == media_stream_no) ) {
/* return the already known port number */
DEBUGC(DBCLASS_RTP,"RTP stream already active (port=%i, "
"id=%s, #=%i)", rtp_proxytable[j].outboundport,
rtp_proxytable[j].callid_number,
rtp_proxytable[j].media_stream_no);
*outboundport=rtp_proxytable[j].outboundport;
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].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;
sock=0;
port=0;
for (i=configuration.rtp_port_low; i<=configuration.rtp_port_high; i++) {
for (j=0; j<RTPPROXY_SIZE; j++) {
/* outbound port already in use */
@@ -106,20 +333,196 @@ int rtp_relay_start_fwd(int *sock, int *port, struct in_addr outbound_ipaddr) {
/* port is available, try to allocate */
if (j == RTPPROXY_SIZE) {
*port=i;
*sock=sockbind(outbound_ipaddr, *port, 0);
port=i;
sock=sockbind(outbound_ipaddr, port, 0);
/* if success break, else try further on */
if (*sock) break;
if (sock) break;
}
} /* for i */
return (*sock)?STS_SUCCESS:STS_FAILURE;
}
DEBUGC(DBCLASS_RTP,"rtp_relay_start_fwd: port=%i, sock=%i freeidx=%i",
port, sock, freeidx);
/* found an unused port? No -> RTP port pool fully allocated */
if (port == 0) {
ERROR("rtp_relay_start_fwd: no RTP port available. Check rtp_port_* config!");
sts = STS_FAILURE;
goto unlock_and_exit;
}
int rtp_relay_stop_fwd(int sock) {
int sts;
/* write entry into rtp_proxytable slot (freeidx) */
rtp_proxytable[freeidx].sock=sock;
strcpy(rtp_proxytable[freeidx].callid_number, callid->number);
strcpy(rtp_proxytable[freeidx].callid_host, callid->host);
rtp_proxytable[freeidx].media_stream_no = media_stream_no;
memcpy(&rtp_proxytable[freeidx].outbound_ipaddr,
&outbound_ipaddr, sizeof(struct in_addr));
rtp_proxytable[freeidx].outboundport=port;
memcpy(&rtp_proxytable[freeidx].inbound_client_ipaddr,
&lcl_client_ipaddr, sizeof(struct in_addr));
rtp_proxytable[freeidx].inbound_client_port=lcl_clientport;
time(&rtp_proxytable[freeidx].timestamp);
*outboundport=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
sts = close(sock);
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 nolock) {
int i, sts;
int retsts=STS_SUCCESS;
int got_match=0;
if (callid == NULL) {
ERROR("rtp_relay_stop_fwd: callid is NULL!");
return STS_FAILURE;
}
DEBUGC(DBCLASS_RTP,"stopping RTP proxy stream for: %s@%s",
callid->number, callid->host);
/*
* 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++) {
if ((callid->number==NULL) || (callid->host==NULL)) break;
if( rtp_proxytable[i].sock &&
(strcmp(rtp_proxytable[i].callid_number, callid->number)==0) &&
(strcmp(rtp_proxytable[i].callid_host, callid->host)==0) ) {
sts = close(rtp_proxytable[i].sock);
DEBUGC(DBCLASS_RTP,"closed socket %i for RTP stream "
"%s:%s == %s:%s (idx=%i) sts=%i",
rtp_proxytable[i].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].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",
callid->number, callid->host);
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].sock != 0) {
FD_SET(rtp_proxytable[i].sock, &master_fdset);
if (rtp_proxytable[i].sock > master_fd_max) {
master_fd_max=rtp_proxytable[i].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_join(rtpproxy_tid, &thread_status);
}
DEBUGC(DBCLASS_RTP,"killed RTP proxy thread");
return;
}
+2 -18
View File
@@ -144,17 +144,10 @@ int main (int argc, char *argv[])
/* daemonize if requested to */
if (configuration.daemonize) {
DEBUGC(DBCLASS_CONFIG,"daemonizing");
/* daemon() seems to be broken! starting the threads afterwards
with pthread_create will get stuck... */
#if HAVE_DAEMONxxSICK
if (daemon(1,0) == -1) {
ERROR("unable to daemonize: %s", strerror(errno));
};
# else
if (fork()!=0) exit(0);
setsid();
if (fork()!=0) exit(0);
#endif
log_set_tosyslog(1);
}
#ifdef MOREDEBUG /*&&&&*/
@@ -162,14 +155,7 @@ INFO("daemonizing done (pid=%i)", getpid());
#endif
/* initialize the RTP proxy thread */
#ifdef MOREDEBUG /*&&&&*/
INFO("b4 rtpproxy_init");
#endif
atexit(rtpproxy_kill); /* cancel RTP thread at exit */
rtpproxy_init();
#ifdef MOREDEBUG /*&&&&*/
INFO("rtpproxy_init done");
#endif
/* init the oSIP parser */
parser_init();
@@ -184,9 +170,6 @@ INFO("rtpproxy_init done");
ERROR("unable to bind to SIP listening socket - aborting");
exit(1);
}
#ifdef MOREDEBUG /*&&&&*/
INFO("sipsock_listen done");
#endif
INFO(PACKAGE"-"VERSION"-"BUILDSTR" started");
/*
@@ -236,6 +219,7 @@ INFO("got packet from %s [%s]", inet_ntoa(from.sin_addr), tmp);}
sts=osip_message_parse(my_msg, buff);
if (sts != 0) {
ERROR("osip_message_parse() failed... this is not good");
DUMP_BUFFER(-1, buff, i);
goto end_loop; /* skip and free resources */
}
+1 -1
View File
@@ -66,7 +66,7 @@ int rtpproxy_init( void ); /*X*/
int rtp_start_fwd (osip_call_id_t *callid, int media_stream_no, /*X*/
struct in_addr outbound_ipaddr, int *outboundport,
struct in_addr lcl_client_ipaddr, int lcl_clientport);
int rtp_stop_fwd (osip_call_id_t *callid, int nolock); /*X*/
int rtp_stop_fwd (osip_call_id_t *callid); /*X*/
void rtpproxy_kill( void ); /*X*/
/* accessctl.c */