mirror of
https://github.com/coturn/coturn.git
synced 2025-10-24 12:31:00 +02:00
MongoDB support: initial checkin
This commit is contained in:
parent
48537e9624
commit
5c3b773d9c
67
INSTALL
67
INSTALL
@ -212,13 +212,13 @@ do not allows that, then after the installation, you may have to adjust the
|
|||||||
system-wide shared library search path by using "ldconfig -n <libdirname>"
|
system-wide shared library search path by using "ldconfig -n <libdirname>"
|
||||||
(Linux), "ldconfig -m <libdirname>" (BSD) or "crle -u -l <libdirname>"
|
(Linux), "ldconfig -m <libdirname>" (BSD) or "crle -u -l <libdirname>"
|
||||||
(Solaris). Your system must be able to find the libevent2, openssl and
|
(Solaris). Your system must be able to find the libevent2, openssl and
|
||||||
(optionally) PostgreSQL and/or MySQL (MariaDB) and/or Redis shared libraries,
|
(optionally) PostgreSQL and/or MySQL (MariaDB) and/or MongoDB and/or Redis
|
||||||
either with the help of the system-wide library search configuration or by
|
shared libraries, either with the help of the system-wide library search
|
||||||
using LD_LIBRARY_PATH. "make install" will make a non-garantied effort to add
|
configuration or by using LD_LIBRARY_PATH. "make install" will make a
|
||||||
automatically PREFIX/lib and /usr/local/lib to the libraries search path,
|
non-garantied effort to add automatically PREFIX/lib and /usr/local/lib to
|
||||||
but if you have some libraries in different non-default directories
|
the libraries search path, but if you have some libraries in different
|
||||||
you will have to add them manually to the search path, or you
|
non-default directories you will have to add them manually to the search
|
||||||
will have to adjust LD_LIBRARY_PATH.
|
path, or you will have to adjust LD_LIBRARY_PATH.
|
||||||
|
|
||||||
V. PLATFORMS
|
V. PLATFORMS
|
||||||
|
|
||||||
@ -277,8 +277,8 @@ VII. WHICH EXTRA LIBRARIES AND UTILITIES YOU NEED
|
|||||||
In addition to common *NIX OS services and libraries, to compile this code,
|
In addition to common *NIX OS services and libraries, to compile this code,
|
||||||
OpenSSL (version 1.0.0a or better recommended) and libevent2 (version 2.0.5
|
OpenSSL (version 1.0.0a or better recommended) and libevent2 (version 2.0.5
|
||||||
or better) are required, the PostgreSQL C client development setup is
|
or better) are required, the PostgreSQL C client development setup is
|
||||||
optional, the MySQL (MariaDB) C client development setup is optional, and the
|
optional, the MySQL (MariaDB) C client development setup is optional, the MongoDB
|
||||||
Hiredis development files for Redis database access are optional.
|
C Driver and the Hiredis development files for Redis database access are optional.
|
||||||
For fully functional build, the extra set of libraries must be installed
|
For fully functional build, the extra set of libraries must be installed
|
||||||
in full version (the development headers and the libraries to link with).
|
in full version (the development headers and the libraries to link with).
|
||||||
For runtime, only runtime setup is required. If the build is modified for
|
For runtime, only runtime setup is required. If the build is modified for
|
||||||
@ -290,6 +290,7 @@ libraries can be downloaded from their web sites:
|
|||||||
- http://www.libevent.org (required);
|
- http://www.libevent.org (required);
|
||||||
- http://www.postgresql.org (optional);
|
- http://www.postgresql.org (optional);
|
||||||
- http://www.mysql.org (or http://mariadb.org) (optional);
|
- http://www.mysql.org (or http://mariadb.org) (optional);
|
||||||
|
- https://github.com/mongodb/mongo-c-driver (optional);
|
||||||
- http://redis.io (optional).
|
- http://redis.io (optional).
|
||||||
|
|
||||||
The installations are pretty straightforward - the usual
|
The installations are pretty straightforward - the usual
|
||||||
@ -352,6 +353,11 @@ installation:
|
|||||||
- you have to install gcc first:
|
- you have to install gcc first:
|
||||||
$ sudo yum install gcc
|
$ sudo yum install gcc
|
||||||
|
|
||||||
|
- mongo-c-driver packages are not available. MongoDB support
|
||||||
|
will not be compiled, unless you install it "manually" before
|
||||||
|
the TURN server compilation. Refer to https://github.com/mongodb/mongo-c-driver
|
||||||
|
for installation instructions of the driver.
|
||||||
|
|
||||||
- hiredis packages are not available, so do not issue the
|
- hiredis packages are not available, so do not issue the
|
||||||
hiredis installation commands. Redis support will not be
|
hiredis installation commands. Redis support will not be
|
||||||
compiled, unless you install it "manually" before the TURN
|
compiled, unless you install it "manually" before the TURN
|
||||||
@ -381,7 +387,7 @@ like this:
|
|||||||
Dynamic library paths:
|
Dynamic library paths:
|
||||||
|
|
||||||
You may also have to adjust the turn server start script, add PostgreSQL
|
You may also have to adjust the turn server start script, add PostgreSQL
|
||||||
and/or MySQL and/or Redis runtime library path to LD_LIBRARY_PATH.
|
and/or MySQL and/or MongoDB and/or Redis runtime library path to LD_LIBRARY_PATH.
|
||||||
Or you may find that it would be more convenient to adjust the
|
Or you may find that it would be more convenient to adjust the
|
||||||
system-wide shared library search path by using commands:
|
system-wide shared library search path by using commands:
|
||||||
|
|
||||||
@ -412,17 +418,17 @@ absolute paths or @rpath/... .
|
|||||||
|
|
||||||
See also the next section.
|
See also the next section.
|
||||||
|
|
||||||
NOTE: See "PostgreSQL setup" and "MySQL setup" and "Redis setup" sections
|
NOTE: See "PostgreSQL setup" and "MySQL setup" and "MongoDB setup" and
|
||||||
below for more database setup information.
|
"Redis setup" sections below for more database setup information.
|
||||||
|
|
||||||
NOTE: If you do not install PostgreSQL or MySQL or Redis then you will
|
NOTE: If you do not install PostgreSQL or MySQL or MongoDB or Redis then you will
|
||||||
be limited to flat files for user database. It will work great for
|
be limited to flat files for user database. It will work great for
|
||||||
smaller user databases (like 100 users) but for larger systems you
|
smaller user databases (like 100 users) but for larger systems you
|
||||||
will need PostgreSQL or MySQL or Redis.
|
will need PostgreSQL or MySQL or MongoDB or Redis.
|
||||||
|
|
||||||
NOTE: To run PostgreSQL or MySQL or Redis server on the same system,
|
NOTE: To run PostgreSQL or MySQL or MongoDB or Redis server on the same system,
|
||||||
you will also have to install a corresponding PostgreSQL or MySQL or
|
you will also have to install a corresponding PostgreSQL or MySQL or
|
||||||
Redis server package. The DB C development packages only provide
|
MongoDB or Redis server package. The DB C development packages only provide
|
||||||
development libraries, and client libraries only provide client
|
development libraries, and client libraries only provide client
|
||||||
access utilities and runtime libraries. The server packages may
|
access utilities and runtime libraries. The server packages may
|
||||||
include everything - client, C development and server runtime.
|
include everything - client, C development and server runtime.
|
||||||
@ -892,7 +898,28 @@ Or in the turnserver.conf file:
|
|||||||
|
|
||||||
mysql-userdb="host=localhost dbname=turn user=turn password=turn connect_timeout=30"
|
mysql-userdb="host=localhost dbname=turn user=turn password=turn connect_timeout=30"
|
||||||
|
|
||||||
XVI. Redis setup
|
XVI. MongoDB setup
|
||||||
|
|
||||||
|
The MongoDB setup is well documented on their site http://docs.mongodb.org/manual/.
|
||||||
|
|
||||||
|
If the TURN server was compiled with MongoDB support (mongo-c-driver is the C client
|
||||||
|
library for MongoDB), then we can use the TURN server database parameter
|
||||||
|
--mongo-userdb. The value of this parameter is a connection string
|
||||||
|
for the MongoDB database. The format of the connection string is described at
|
||||||
|
http://hergert.me/docs/mongo-c-driver/mongoc_uri.html:
|
||||||
|
|
||||||
|
"mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]"
|
||||||
|
|
||||||
|
So, an example of the MongoDB database parameter in the TURN server command
|
||||||
|
line would be:
|
||||||
|
|
||||||
|
--mongo-userdb="mongodb://localhost:27017/turndb"
|
||||||
|
|
||||||
|
Or in the turnserver.conf file:
|
||||||
|
|
||||||
|
mongo-userdb="mongodb://localhost:27017/turndb"
|
||||||
|
|
||||||
|
XVII. Redis setup
|
||||||
|
|
||||||
The Redis setup is well documented on their site http://redis.io.
|
The Redis setup is well documented on their site http://redis.io.
|
||||||
The TURN Server Redis database schema description can be found
|
The TURN Server Redis database schema description can be found
|
||||||
@ -961,20 +988,20 @@ Redis TURN admin commands:
|
|||||||
$ bin/turnadmin -A -N "host=localhost dbname=0 user=turn password=turn" -u gorst -r north.gov -p hero
|
$ bin/turnadmin -A -N "host=localhost dbname=0 user=turn password=turn" -u gorst -r north.gov -p hero
|
||||||
$ bin/turnadmin -A -N "host=localhost dbname=0 user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic
|
$ bin/turnadmin -A -N "host=localhost dbname=0 user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic
|
||||||
|
|
||||||
XV. Performance tuning
|
XVIII. Performance tuning
|
||||||
|
|
||||||
This topic is covered in the wiki page:
|
This topic is covered in the wiki page:
|
||||||
|
|
||||||
http://code.google.com/p/coturn/wiki/turn_performance_and_load_balance
|
http://code.google.com/p/coturn/wiki/turn_performance_and_load_balance
|
||||||
|
|
||||||
XVI. TURN Server setup
|
XIX. TURN Server setup
|
||||||
|
|
||||||
Read the project wiki pages: http://code.google.com/p/coturn/w/list
|
Read the project wiki pages: http://code.google.com/p/coturn/w/list
|
||||||
|
|
||||||
Also, check the project from page links to the TURN/WebRTC configuration examples.
|
Also, check the project from page links to the TURN/WebRTC configuration examples.
|
||||||
It may give you an idea how it can be done.
|
It may give you an idea how it can be done.
|
||||||
|
|
||||||
XVI. Management interface
|
XX. Management interface
|
||||||
|
|
||||||
You have a telnet interface (enabled by default) to access the turnserver process,
|
You have a telnet interface (enabled by default) to access the turnserver process,
|
||||||
to view its state, to gather some statistical information, and to make some changes
|
to view its state, to gather some statistical information, and to make some changes
|
||||||
|
|||||||
@ -27,8 +27,11 @@ IMPL_DEPS = ${COMMON_DEPS} ${IMPL_HEADERS} ${IMPL_MODS}
|
|||||||
HIREDIS_HEADERS = src/apps/common/hiredis_libevent2.h
|
HIREDIS_HEADERS = src/apps/common/hiredis_libevent2.h
|
||||||
HIREDIS_MODS = src/apps/common/hiredis_libevent2.c
|
HIREDIS_MODS = src/apps/common/hiredis_libevent2.c
|
||||||
|
|
||||||
SERVERAPP_HEADERS = src/apps/relay/userdb.h src/apps/relay/tls_listener.h src/apps/relay/mainrelay.h src/apps/relay/turncli.h src/apps/relay/dtls_listener.h src/apps/relay/libtelnet.h ${HIREDIS_HEADERS}
|
USERDB_HEADERS = src/apps/relay/dbdrivers/dbdriver.h src/apps/relay/dbdrivers/dbd_pgsql.h src/apps/relay/dbdrivers/dbd_mysql.h src/apps/relay/dbdrivers/dbd_mongo.h src/apps/relay/dbdrivers/dbd_redis.h
|
||||||
SERVERAPP_MODS = src/apps/relay/mainrelay.c src/apps/relay/netengine.c src/apps/relay/libtelnet.c src/apps/relay/turncli.c src/apps/relay/userdb.c src/apps/relay/tls_listener.c src/apps/relay/dtls_listener.c ${HIREDIS_MODS}
|
USERDB_MODS = src/apps/relay/dbdrivers/dbdriver.c src/apps/relay/dbdrivers/dbd_pgsql.c src/apps/relay/dbdrivers/dbd_mysql.c src/apps/relay/dbdrivers/dbd_mongo.c src/apps/relay/dbdrivers/dbd_redis.c
|
||||||
|
|
||||||
|
SERVERAPP_HEADERS = src/apps/relay/userdb.h src/apps/relay/tls_listener.h src/apps/relay/mainrelay.h src/apps/relay/turncli.h src/apps/relay/dtls_listener.h src/apps/relay/libtelnet.h ${HIREDIS_HEADERS} ${USERDB_HEADERS}
|
||||||
|
SERVERAPP_MODS = src/apps/relay/mainrelay.c src/apps/relay/netengine.c src/apps/relay/libtelnet.c src/apps/relay/turncli.c src/apps/relay/userdb.c src/apps/relay/tls_listener.c src/apps/relay/dtls_listener.c ${HIREDIS_MODS} ${USERDB_MODS}
|
||||||
SERVERAPP_DEPS = ${SERVERTURN_MODS} ${SERVERTURN_DEPS} ${SERVERAPP_MODS} ${SERVERAPP_HEADERS} ${COMMON_DEPS} ${IMPL_DEPS} lib/libturnclient.a
|
SERVERAPP_DEPS = ${SERVERTURN_MODS} ${SERVERTURN_DEPS} ${SERVERAPP_MODS} ${SERVERAPP_HEADERS} ${COMMON_DEPS} ${IMPL_DEPS} lib/libturnclient.a
|
||||||
|
|
||||||
TURN_BUILD_RESULTS = bin/turnutils_stunclient bin/turnutils_rfc5769check bin/turnutils_uclient bin/turnserver bin/turnutils_peer lib/libturnclient.a include/turn/ns_turn_defs.h
|
TURN_BUILD_RESULTS = bin/turnutils_stunclient bin/turnutils_rfc5769check bin/turnutils_uclient bin/turnserver bin/turnutils_peer lib/libturnclient.a include/turn/ns_turn_defs.h
|
||||||
|
|||||||
@ -92,6 +92,8 @@ Options with required values:
|
|||||||
See the --psql-userdb option in the turnserver section.
|
See the --psql-userdb option in the turnserver section.
|
||||||
-M, --mysql-userdb MySQL user database connection string.
|
-M, --mysql-userdb MySQL user database connection string.
|
||||||
See the --mysql-userdb option in the turnserver section.
|
See the --mysql-userdb option in the turnserver section.
|
||||||
|
-J, --mongo-userdb MongoDB user database connection string.
|
||||||
|
See the --mysql-mongo option in the turnserver section.
|
||||||
-N, --redis-userdb Redis user database connection string.
|
-N, --redis-userdb Redis user database connection string.
|
||||||
See the --redis-userdb option in the turnserver section.
|
See the --redis-userdb option in the turnserver section.
|
||||||
-u, --user User name.
|
-u, --user User name.
|
||||||
|
|||||||
@ -57,7 +57,7 @@ turnserver - a TURN relay server implementation.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
|
|
||||||
$ turnserver [-n | -c <config-file> ] [flags] [ --userdb=<userdb-file> | --psql-userdb=<db-conn-string> | --mysql-userdb=<db-conn-string> | --redis-userdb=<db-conn-string> ] [-z | --no-auth | -a | --lt-cred-mech ] [options]
|
$ turnserver [-n | -c <config-file> ] [flags] [ --userdb=<userdb-file> | --psql-userdb=<db-conn-string> | --mysql-userdb=<db-conn-string> | --mongo-userdb=<db-conn-string> | --redis-userdb=<db-conn-string> ] [-z | --no-auth | -a | --lt-cred-mech ] [options]
|
||||||
$ turnserver -h
|
$ turnserver -h
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@ -113,6 +113,17 @@ User database settings:
|
|||||||
Also, see http://www.mysql.org or http://mariadb.org
|
Also, see http://www.mysql.org or http://mariadb.org
|
||||||
for full MySQL documentation.
|
for full MySQL documentation.
|
||||||
|
|
||||||
|
-J, --mongo-userdb User database connection string for MongoDB.
|
||||||
|
This database can be used for long-term and short-term credentials mechanisms,
|
||||||
|
and it can store the secret value for secret-based timed authentication in TURN RESP API.
|
||||||
|
The connection string format is like that:
|
||||||
|
|
||||||
|
"mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]"
|
||||||
|
See the INSTALL file for more explanations and examples.
|
||||||
|
|
||||||
|
Also, see http://docs.mongodb.org/manual/
|
||||||
|
for full MongoDB documentation.
|
||||||
|
|
||||||
-N, --redis-userdb User database connection string for Redis.
|
-N, --redis-userdb User database connection string for Redis.
|
||||||
This database can be used for long-term and short-term credentials mechanisms,
|
This database can be used for long-term and short-term credentials mechanisms,
|
||||||
and it can store the secret value for secret-based timed authentication in TURN RESP API.
|
and it can store the secret value for secret-based timed authentication in TURN RESP API.
|
||||||
@ -138,9 +149,9 @@ Flags:
|
|||||||
|
|
||||||
-a, --lt-cred-mech Use long-term credentials mechanism (this one you need for WebRTC usage).
|
-a, --lt-cred-mech Use long-term credentials mechanism (this one you need for WebRTC usage).
|
||||||
This option can be used with either flat file user database or
|
This option can be used with either flat file user database or
|
||||||
PostgreSQL DB or MySQL DB or Redis for user keys storage.
|
PostgreSQL DB or MySQL DB or MongoDB or Redis for user keys storage.
|
||||||
-A, --st-cred-mech Use the short-term credentials mechanism. This option requires
|
-A, --st-cred-mech Use the short-term credentials mechanism. This option requires
|
||||||
a PostgreSQL or MySQL or Redis DB for short term passwords storage.
|
a PostgreSQL or MySQL or MongoDB or Redis DB for short term passwords storage.
|
||||||
|
|
||||||
-z, --no-auth Do not use any credentials mechanism, allow anonymous access.
|
-z, --no-auth Do not use any credentials mechanism, allow anonymous access.
|
||||||
Opposite to -a and -A options. This is default option when no
|
Opposite to -a and -A options. This is default option when no
|
||||||
@ -461,7 +472,7 @@ Options with required values:
|
|||||||
no Redis stats DB used). This database keeps allocations status information, and it can
|
no Redis stats DB used). This database keeps allocations status information, and it can
|
||||||
be also used for publishing and delivering traffic and allocation event notifications.
|
be also used for publishing and delivering traffic and allocation event notifications.
|
||||||
This database option can be used independently of --redis-userdb option,
|
This database option can be used independently of --redis-userdb option,
|
||||||
and actually Redis can be used for status/statistics and MySQL or PostgreSQL can
|
and actually Redis can be used for status/statistics and MySQL or MongoDB or PostgreSQL can
|
||||||
be used for the user database.
|
be used for the user database.
|
||||||
The connection string has the same parameters as redis-userdb connection string.
|
The connection string has the same parameters as redis-userdb connection string.
|
||||||
|
|
||||||
@ -533,7 +544,7 @@ for that you have a number of options:
|
|||||||
|
|
||||||
b) userdb config file.
|
b) userdb config file.
|
||||||
|
|
||||||
c) a database table (PostgreSQL or MySQL). You will have to set keys with
|
c) a database table (PostgreSQL or MySQL or MongoDB). You will have to set keys with
|
||||||
turnadmin utility (see docs and wiki for turnadmin). You cannot use open passwords
|
turnadmin utility (see docs and wiki for turnadmin). You cannot use open passwords
|
||||||
in the database.
|
in the database.
|
||||||
|
|
||||||
@ -717,7 +728,9 @@ turndb/testredisdbsetup.sh as an example.
|
|||||||
can be administered separately, and each realm can have its own set of users and its own
|
can be administered separately, and each realm can have its own set of users and its own
|
||||||
performance options (max-bps, user-quota, total-quota).
|
performance options (max-bps, user-quota, total-quota).
|
||||||
|
|
||||||
7) Of course, the turnserver can be used in non-secure mode, when users are allowed to establish
|
7) If you use MongoDB, the database will be setup for you automatically.
|
||||||
|
|
||||||
|
8) Of course, the turnserver can be used in non-secure mode, when users are allowed to establish
|
||||||
sessions anonymously. But in most cases (like WebRTC) that will not work.
|
sessions anonymously. But in most cases (like WebRTC) that will not work.
|
||||||
|
|
||||||
For the status and statistics database, there are two choices:
|
For the status and statistics database, there are two choices:
|
||||||
|
|||||||
56
configure
vendored
56
configure
vendored
@ -13,6 +13,8 @@ cleanup() {
|
|||||||
rm -rf ${PQ_TMPCPROGB}
|
rm -rf ${PQ_TMPCPROGB}
|
||||||
rm -rf ${MYSQL_TMPCPROGC}
|
rm -rf ${MYSQL_TMPCPROGC}
|
||||||
rm -rf ${MYSQL_TMPCPROGB}
|
rm -rf ${MYSQL_TMPCPROGB}
|
||||||
|
rm -rf ${MONGO_TMPCPROGC}
|
||||||
|
rm -rf ${MONGO_TMPCPROGB}
|
||||||
rm -rf ${D_TMPCPROGC}
|
rm -rf ${D_TMPCPROGC}
|
||||||
rm -rf ${D_TMPCPROGB}
|
rm -rf ${D_TMPCPROGB}
|
||||||
rm -rf ${E_TMPCPROGC}
|
rm -rf ${E_TMPCPROGC}
|
||||||
@ -124,6 +126,30 @@ testlibmysql() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testlibmongoc() {
|
||||||
|
for inc in ${PREFIX}/libmongoc-1.0 ${PREFIX}/libbson-1.0 /usr/local/include/libmongoc-1.0 /usr/local/include/libbson-1.0 /usr/libmongoc-1.0 -I/usr/libbson-1.0
|
||||||
|
do
|
||||||
|
if [ -d ${inc} ] ; then
|
||||||
|
MONGO_CFLAGS="${MONGO_CFLAGS} -I${inc}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
MONGO_LIBS="-lmongoc-1.0 -lbson-1.0"
|
||||||
|
${CC} ${MONGO_TMPCPROGC} -o ${MONGO_TMPCPROGB} ${OSCFLAGS} ${DBCFLAGS} ${DBLIBS} ${MONGO_CFLAGS} ${MONGO_LIBS} ${OSLIBS} 2>>/dev/null
|
||||||
|
ER=$?
|
||||||
|
if ! [ ${ER} -eq 0 ] ; then
|
||||||
|
${ECHO_CMD}
|
||||||
|
${ECHO_CMD} "MONGODB DEVELOPMENT LIBRARIES (libmongoc-1.0 and libbson-1.0) AND/OR HEADER (mongoc.h)"
|
||||||
|
${ECHO_CMD} " ARE NOT INSTALLED PROPERLY ON THIS SYSTEM."
|
||||||
|
${ECHO_CMD} " THAT'S OK BUT THE TURN SERVER IS BUILDING WITHOUT MONGODB SUPPORT."
|
||||||
|
${ECHO_CMD}
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
DBCFLAGS="${DBCFLAGS} ${MONGO_CFLAGS}"
|
||||||
|
DBLIBS="${DBLIBS} ${MONGO_LIBS}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
testlib() {
|
testlib() {
|
||||||
testlibraw l${1}
|
testlibraw l${1}
|
||||||
}
|
}
|
||||||
@ -666,6 +692,19 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
!
|
!
|
||||||
|
|
||||||
|
MONGO_TMPCPROG=__test__ccomp__libmongoc__$$
|
||||||
|
MONGO_TMPCPROGC=${TMPDIR}/${MONGO_TMPCPROG}.c
|
||||||
|
MONGO_TMPCPROGB=${TMPDIR}/${MONGO_TMPCPROG}
|
||||||
|
|
||||||
|
cat > ${MONGO_TMPCPROGC} <<!
|
||||||
|
#include <mongoc.h>
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
return (argc+
|
||||||
|
(int)(mongoc_client_new("mongodb://localhost:27017")!=0)+
|
||||||
|
(int)(argv[0][0]));
|
||||||
|
}
|
||||||
|
!
|
||||||
|
|
||||||
##########################
|
##########################
|
||||||
# What is our compiler ?
|
# What is our compiler ?
|
||||||
##########################
|
##########################
|
||||||
@ -940,6 +979,23 @@ else
|
|||||||
TURN_NO_MYSQL="-DTURN_NO_MYSQL"
|
TURN_NO_MYSQL="-DTURN_NO_MYSQL"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
###########################
|
||||||
|
# Test MongoDB
|
||||||
|
###########################
|
||||||
|
|
||||||
|
if [ -z "${TURN_NO_MONGO}" ] ; then
|
||||||
|
|
||||||
|
testlibmongoc
|
||||||
|
ER=$?
|
||||||
|
if ! [ ${ER} -eq 0 ] ; then
|
||||||
|
${ECHO_CMD} "MongoDB found."
|
||||||
|
else
|
||||||
|
TURN_NO_MYSQL="-DTURN_NO_MONGO"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
TURN_NO_MYSQL="-DTURN_NO_MONGO"
|
||||||
|
fi
|
||||||
|
|
||||||
###########################
|
###########################
|
||||||
# Test Redis
|
# Test Redis
|
||||||
###########################
|
###########################
|
||||||
|
|||||||
@ -161,14 +161,14 @@
|
|||||||
# Uncomment to use long-term credential mechanism.
|
# Uncomment to use long-term credential mechanism.
|
||||||
# By default no credentials mechanism is used (any user allowed).
|
# By default no credentials mechanism is used (any user allowed).
|
||||||
# This option can be used with either flat file user database or
|
# This option can be used with either flat file user database or
|
||||||
# PostgreSQL DB or MySQL DB or Redis DB for user keys storage.
|
# PostgreSQL DB or MySQL DB or MongoDB or Redis DB for user keys storage.
|
||||||
#
|
#
|
||||||
#lt-cred-mech
|
#lt-cred-mech
|
||||||
|
|
||||||
# Uncomment to use short-term credential mechanism.
|
# Uncomment to use short-term credential mechanism.
|
||||||
# By default no credentials mechanism is used (any user allowed).
|
# By default no credentials mechanism is used (any user allowed).
|
||||||
# For short-term credential mechanism you have to use PostgreSQL or
|
# For short-term credential mechanism you have to use PostgreSQL or
|
||||||
# MySQL or Redis database for user password storage.
|
# MySQL or MongoDB or Redis database for user password storage.
|
||||||
#
|
#
|
||||||
#st-cred-mech
|
#st-cred-mech
|
||||||
|
|
||||||
@ -241,7 +241,7 @@
|
|||||||
# 'Dynamic' user accounts database file name.
|
# 'Dynamic' user accounts database file name.
|
||||||
# Only users for long-term mechanism can be stored in a flat file,
|
# Only users for long-term mechanism can be stored in a flat file,
|
||||||
# short-term mechanism will not work with option, the short-term
|
# short-term mechanism will not work with option, the short-term
|
||||||
# mechanism required PostgreSQL or MySQL or Redis database.
|
# mechanism required PostgreSQL or MySQL or MongoDB or Redis database.
|
||||||
# 'Dynamic' long-term user accounts are dynamically checked by the turnserver process,
|
# 'Dynamic' long-term user accounts are dynamically checked by the turnserver process,
|
||||||
# so that they can be changed while the turnserver is running.
|
# so that they can be changed while the turnserver is running.
|
||||||
#
|
#
|
||||||
@ -268,6 +268,14 @@
|
|||||||
#
|
#
|
||||||
#mysql-userdb="host=<host> dbname=<database-name> user=<database-user> password=<database-user-password> port=<port> connect_timeout=<seconds>"
|
#mysql-userdb="host=<host> dbname=<database-name> user=<database-user> password=<database-user-password> port=<port> connect_timeout=<seconds>"
|
||||||
|
|
||||||
|
# MongoDB database connection string in the case that we are using MongoDB
|
||||||
|
# as the user database.
|
||||||
|
# This database can be used for long-term and short-term credential mechanisms
|
||||||
|
# and it can store the secret value for secret-based timed authentication in TURN RESP API.
|
||||||
|
# Use string format is described at http://hergert.me/docs/mongo-c-driver/mongoc_uri.html
|
||||||
|
#
|
||||||
|
#mongo-userdb="mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]"
|
||||||
|
|
||||||
# Redis database connection string in the case that we are using Redis
|
# Redis database connection string in the case that we are using Redis
|
||||||
# as the user database.
|
# as the user database.
|
||||||
# This database can be used for long-term and short-term credential mechanisms
|
# This database can be used for long-term and short-term credential mechanisms
|
||||||
|
|||||||
@ -10,7 +10,7 @@ service, you have to:
|
|||||||
|
|
||||||
b) For user accounts settings, if using the turnserver
|
b) For user accounts settings, if using the turnserver
|
||||||
with authentication: create and edit /etc/turnuserdb.conf
|
with authentication: create and edit /etc/turnuserdb.conf
|
||||||
file, or set up PostgreSQL or MySQL or Redis database for user accounts.
|
file, or set up PostgreSQL or MySQL or MongoDB or Redis database for user accounts.
|
||||||
Use /usr/local/etc/turnuserdb.conf.default as example for flat file DB,
|
Use /usr/local/etc/turnuserdb.conf.default as example for flat file DB,
|
||||||
or use /usr/local/share/turnserver/schema.sql as SQL database schema,
|
or use /usr/local/share/turnserver/schema.sql as SQL database schema,
|
||||||
or use /usr/local/share/turnserver/schema.userdb.redis as Redis
|
or use /usr/local/share/turnserver/schema.userdb.redis as Redis
|
||||||
|
|||||||
916
src/apps/relay/dbdrivers/dbd_mongo.c
Normal file
916
src/apps/relay/dbdrivers/dbd_mongo.c
Normal file
@ -0,0 +1,916 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011, 2012, 2013 Citrix Systems
|
||||||
|
* Copyright (C) 2014 Vivocha S.p.A.
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the project nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../mainrelay.h"
|
||||||
|
#include "dbd_mongo.h"
|
||||||
|
|
||||||
|
#if !defined(TURN_NO_MONGO)
|
||||||
|
#include <mongoc.h>
|
||||||
|
#include <bson.h>
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
const char * MONGO_DEFAULT_DB = "turn";
|
||||||
|
|
||||||
|
struct _MONGO {
|
||||||
|
mongoc_uri_t * uri;
|
||||||
|
mongoc_client_t * client;
|
||||||
|
const char * database;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _MONGO MONGO;
|
||||||
|
|
||||||
|
static void mongo_logger(mongoc_log_level_t log_level, const char * log_domain, const char * message, void * user_data) {
|
||||||
|
UNUSED_ARG(log_domain);
|
||||||
|
UNUSED_ARG(user_data);
|
||||||
|
|
||||||
|
TURN_LOG_LEVEL l;
|
||||||
|
|
||||||
|
switch(log_level) {
|
||||||
|
case MONGOC_LOG_LEVEL_ERROR:
|
||||||
|
l = TURN_LOG_LEVEL_ERROR;
|
||||||
|
break;
|
||||||
|
case MONGOC_LOG_LEVEL_WARNING:
|
||||||
|
l = TURN_LOG_LEVEL_WARNING;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
l = TURN_LOG_LEVEL_INFO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
TURN_LOG_FUNC(l, "%s\n", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MongoFree(MONGO * info) {
|
||||||
|
if(info) {
|
||||||
|
if(info->uri) mongoc_uri_destroy(info->uri);
|
||||||
|
if(info->client) mongoc_client_destroy(info->client);
|
||||||
|
turn_free(info, sizeof(MONGO));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static MONGO * get_mydb_connection(const char *realm) {
|
||||||
|
UNUSED_ARG(realm);
|
||||||
|
|
||||||
|
persistent_users_db_t * pud = get_persistent_users_db();
|
||||||
|
|
||||||
|
MONGO * mydbconnection = (MONGO *)(pud->connection);
|
||||||
|
|
||||||
|
if(!mydbconnection) {
|
||||||
|
mongoc_init();
|
||||||
|
mongoc_log_set_handler(&mongo_logger, NULL);
|
||||||
|
|
||||||
|
mydbconnection = (MONGO *)turn_malloc(sizeof(MONGO));
|
||||||
|
mydbconnection->uri = mongoc_uri_new(pud->userdb);
|
||||||
|
|
||||||
|
if (!mydbconnection->uri) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open parse MongoDB URI <%s>, connection string format error\n", pud->userdb);
|
||||||
|
MongoFree(mydbconnection);
|
||||||
|
mydbconnection = NULL;
|
||||||
|
} else {
|
||||||
|
mydbconnection->client = mongoc_client_new_from_uri(mydbconnection->uri);
|
||||||
|
if (!mydbconnection->client) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize MongoDB connection\n");
|
||||||
|
MongoFree(mydbconnection);
|
||||||
|
mydbconnection = NULL;
|
||||||
|
} else {
|
||||||
|
mydbconnection->database = mongoc_uri_get_database(mydbconnection->uri);
|
||||||
|
if (!mydbconnection->database) mydbconnection->database = MONGO_DEFAULT_DB;
|
||||||
|
pud->connection = mydbconnection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mydbconnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mongoc_collection_t * mongo_get_collection(const char * name) {
|
||||||
|
MONGO * mc = get_mydb_connection(NULL);
|
||||||
|
|
||||||
|
if(!mc) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error gettting a connection to MongoDB\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mongoc_collection_t * collection;
|
||||||
|
collection = mongoc_client_get_collection(mc->client, mc->database, name);
|
||||||
|
|
||||||
|
if (!collection) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MongoDB collection '%s'\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static int mongo_get_auth_secrets(secrets_list_t *sl, u08bits *realm) {
|
||||||
|
mongoc_collection_t * collection = mongo_get_collection("turn_secret");
|
||||||
|
|
||||||
|
if(!collection)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bson_t query;
|
||||||
|
bson_init(&query);
|
||||||
|
BSON_APPEND_UTF8(&query, "realm", (const char *)realm);
|
||||||
|
|
||||||
|
bson_t fields;
|
||||||
|
bson_init(&fields);
|
||||||
|
BSON_APPEND_INT32(&fields, "value", 1);
|
||||||
|
|
||||||
|
mongoc_cursor_t * cursor;
|
||||||
|
cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, &query, &fields, NULL);
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!cursor) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error querying MongoDB collection 'turn_secret'\n");
|
||||||
|
} else {
|
||||||
|
const bson_t * item;
|
||||||
|
uint32_t length;
|
||||||
|
bson_iter_t iter;
|
||||||
|
const char * value;
|
||||||
|
while(mongoc_cursor_next(cursor, &item)) {
|
||||||
|
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "value") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||||
|
value = bson_iter_utf8(&iter, &length);
|
||||||
|
add_to_secrets_list(sl, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mongoc_cursor_destroy(cursor);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mongoc_collection_destroy(collection);
|
||||||
|
bson_destroy(&query);
|
||||||
|
bson_destroy(&fields);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mongo_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) {
|
||||||
|
mongoc_collection_t * collection = mongo_get_collection("turnusers_lt");
|
||||||
|
|
||||||
|
if(!collection)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bson_t query;
|
||||||
|
bson_init(&query);
|
||||||
|
BSON_APPEND_UTF8(&query, "name", (const char *)usname);
|
||||||
|
BSON_APPEND_UTF8(&query, "realm", (const char *)realm);
|
||||||
|
|
||||||
|
bson_t fields;
|
||||||
|
bson_init(&fields);
|
||||||
|
BSON_APPEND_INT32(&fields, "hmackey", 1);
|
||||||
|
|
||||||
|
mongoc_cursor_t * cursor;
|
||||||
|
cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 1, 0, &query, &fields, NULL);
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!cursor) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error querying MongoDB collection 'turnusers_lt'\n");
|
||||||
|
} else {
|
||||||
|
const bson_t * item;
|
||||||
|
uint32_t length;
|
||||||
|
bson_iter_t iter;
|
||||||
|
const char * value;
|
||||||
|
if (mongoc_cursor_next(cursor, &item)) {
|
||||||
|
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "hmackey") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||||
|
value = bson_iter_utf8(&iter, &length);
|
||||||
|
size_t sz = get_hmackey_size(turn_params.shatype) * 2;
|
||||||
|
if(length < sz) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key format: string length=%d (must be %d): user %s\n", (int)length, (int)sz, usname);
|
||||||
|
} else {
|
||||||
|
char kval[sizeof(hmackey_t) + sizeof(hmackey_t) + 1];
|
||||||
|
ns_bcopy(value, kval, sz);
|
||||||
|
kval[sz] = 0;
|
||||||
|
if(convert_string_key_to_binary(kval, key, sz / 2) < 0) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key: %s, user %s\n", kval, usname);
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mongoc_cursor_destroy(cursor);
|
||||||
|
}
|
||||||
|
mongoc_collection_destroy(collection);
|
||||||
|
bson_destroy(&query);
|
||||||
|
bson_destroy(&fields);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mongo_get_user_pwd(u08bits *usname, st_password_t pwd) {
|
||||||
|
mongoc_collection_t * collection = mongo_get_collection("turnusers_st");
|
||||||
|
|
||||||
|
if(!collection)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bson_t query;
|
||||||
|
bson_init(&query);
|
||||||
|
BSON_APPEND_UTF8(&query, "name", (const char *)usname);
|
||||||
|
|
||||||
|
bson_t fields;
|
||||||
|
bson_init(&fields);
|
||||||
|
BSON_APPEND_INT32(&fields, "password", 1);
|
||||||
|
|
||||||
|
mongoc_cursor_t * cursor;
|
||||||
|
cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 1, 0, &query, &fields, NULL);
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!cursor) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error querying MongoDB collection 'turnusers_st'\n");
|
||||||
|
} else {
|
||||||
|
const bson_t * item;
|
||||||
|
uint32_t length;
|
||||||
|
bson_iter_t iter;
|
||||||
|
const char * value;
|
||||||
|
if (mongoc_cursor_next(cursor, &item)) {
|
||||||
|
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "password") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||||
|
value = bson_iter_utf8(&iter, &length);
|
||||||
|
|
||||||
|
if(length < 1) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong password data for user %s, size in MongoDB is zero(0)\n", usname);
|
||||||
|
} else {
|
||||||
|
ns_bcopy(value, pwd, length);
|
||||||
|
pwd[length] = 0;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mongoc_cursor_destroy(cursor);
|
||||||
|
}
|
||||||
|
mongoc_collection_destroy(collection);
|
||||||
|
bson_destroy(&query);
|
||||||
|
bson_destroy(&fields);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mongo_set_user_key(u08bits *usname, u08bits *realm, const char *key) {
|
||||||
|
mongoc_collection_t * collection = mongo_get_collection("turnusers_lt");
|
||||||
|
|
||||||
|
if(!collection)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bson_t query;
|
||||||
|
bson_init(&query);
|
||||||
|
BSON_APPEND_UTF8(&query, "name", (const char *)usname);
|
||||||
|
BSON_APPEND_UTF8(&query, "realm", (const char *)realm);
|
||||||
|
|
||||||
|
bson_t doc;
|
||||||
|
bson_init(&doc);
|
||||||
|
BSON_APPEND_UTF8(&doc, "name", (const char *)usname);
|
||||||
|
BSON_APPEND_UTF8(&doc, "realm", (const char *)realm);
|
||||||
|
BSON_APPEND_UTF8(&doc, "hmackey", (const char *)key);
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!mongoc_collection_update(collection, MONGOC_UPDATE_UPSERT, &query, &doc, NULL, NULL)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating secret key information\n");
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
mongoc_collection_destroy(collection);
|
||||||
|
bson_destroy(&doc);
|
||||||
|
bson_destroy(&query);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mongo_set_user_pwd(u08bits *usname, st_password_t pwd) {
|
||||||
|
mongoc_collection_t * collection = mongo_get_collection("turnusers_st");
|
||||||
|
|
||||||
|
if(!collection)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bson_t query;
|
||||||
|
bson_init(&query);
|
||||||
|
BSON_APPEND_UTF8(&query, "name", (const char *)usname);
|
||||||
|
|
||||||
|
bson_t doc;
|
||||||
|
bson_init(&doc);
|
||||||
|
BSON_APPEND_UTF8(&doc, "name", (const char *)usname);
|
||||||
|
BSON_APPEND_UTF8(&doc, "password", (const char *)pwd);
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!mongoc_collection_update(collection, MONGOC_UPDATE_UPSERT, &query, &doc, NULL, NULL)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating secret key information\n");
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
mongoc_collection_destroy(collection);
|
||||||
|
bson_destroy(&doc);
|
||||||
|
bson_destroy(&query);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mongo_del_user(u08bits *usname, int is_st, u08bits *realm) {
|
||||||
|
mongoc_collection_t * collection = mongo_get_collection(is_st ? "turnusers_st" : "turnusers_lt");
|
||||||
|
|
||||||
|
if(!collection)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bson_t query;
|
||||||
|
bson_init(&query);
|
||||||
|
BSON_APPEND_UTF8(&query, "name", (const char *)usname);
|
||||||
|
if(!is_st) {
|
||||||
|
BSON_APPEND_UTF8(&query, "realm", (const char *)realm);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!mongoc_collection_delete(collection, MONGOC_DELETE_SINGLE_REMOVE, &query, NULL, NULL)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting user key information\n");
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
mongoc_collection_destroy(collection);
|
||||||
|
bson_destroy(&query);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mongo_list_users(int is_st, u08bits *realm) {
|
||||||
|
const char * collection_name = is_st ? "turnusers_st" : "turnusers_lt";
|
||||||
|
mongoc_collection_t * collection = mongo_get_collection(collection_name);
|
||||||
|
|
||||||
|
if(!collection)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bson_t query, child;
|
||||||
|
bson_init(&query);
|
||||||
|
bson_append_document_begin(&query, "$orderby", -1, &child);
|
||||||
|
bson_append_int32(&child, "name", -1, 1);
|
||||||
|
bson_append_document_end(&query, &child);
|
||||||
|
bson_append_document_begin(&query, "$query", -1, &child);
|
||||||
|
if (!is_st && realm && realm[0]) {
|
||||||
|
BSON_APPEND_UTF8(&child, "realm", (const char *)realm);
|
||||||
|
}
|
||||||
|
bson_append_document_end(&query, &child);
|
||||||
|
|
||||||
|
bson_t fields;
|
||||||
|
bson_init(&fields);
|
||||||
|
BSON_APPEND_INT32(&fields, "name", 1);
|
||||||
|
|
||||||
|
mongoc_cursor_t * cursor;
|
||||||
|
cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, &query, &fields, NULL);
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!cursor) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error querying MongoDB collection '%s'\n", collection_name);
|
||||||
|
} else {
|
||||||
|
const bson_t * item;
|
||||||
|
uint32_t length;
|
||||||
|
bson_iter_t iter;
|
||||||
|
const char * value;
|
||||||
|
while (mongoc_cursor_next(cursor, &item)) {
|
||||||
|
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "name") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||||
|
value = bson_iter_utf8(&iter, &length);
|
||||||
|
if (length) {
|
||||||
|
printf("%s\n", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mongoc_cursor_destroy(cursor);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
mongoc_collection_destroy(collection);
|
||||||
|
bson_destroy(&query);
|
||||||
|
bson_destroy(&fields);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mongo_show_secret(u08bits *realm) {
|
||||||
|
mongoc_collection_t * collection = mongo_get_collection("turn_secret");
|
||||||
|
|
||||||
|
if(!collection)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bson_t query;
|
||||||
|
bson_init(&query);
|
||||||
|
BSON_APPEND_UTF8(&query, "realm", (const char *)realm);
|
||||||
|
|
||||||
|
bson_t fields;
|
||||||
|
bson_init(&fields);
|
||||||
|
BSON_APPEND_INT32(&fields, "value", 1);
|
||||||
|
|
||||||
|
mongoc_cursor_t * cursor;
|
||||||
|
cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, &query, &fields, NULL);
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!cursor) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error querying MongoDB collection 'turn_secret'\n");
|
||||||
|
} else {
|
||||||
|
const bson_t * item;
|
||||||
|
uint32_t length;
|
||||||
|
bson_iter_t iter;
|
||||||
|
const char * value;
|
||||||
|
while (mongoc_cursor_next(cursor, &item)) {
|
||||||
|
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "value") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||||
|
value = bson_iter_utf8(&iter, &length);
|
||||||
|
if (length) {
|
||||||
|
printf("%s\n", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mongoc_cursor_destroy(cursor);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
mongoc_collection_destroy(collection);
|
||||||
|
bson_destroy(&query);
|
||||||
|
bson_destroy(&fields);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mongo_del_secret(u08bits *secret, u08bits *realm) {
|
||||||
|
mongoc_collection_t * collection = mongo_get_collection("turn_secret");
|
||||||
|
|
||||||
|
if(!collection)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bson_t query;
|
||||||
|
bson_init(&query);
|
||||||
|
BSON_APPEND_UTF8(&query, "realm", (const char *)realm);
|
||||||
|
if(secret && (secret[0]!=0)) {
|
||||||
|
BSON_APPEND_UTF8(&query, "value", (const char *)secret);
|
||||||
|
}
|
||||||
|
|
||||||
|
mongoc_collection_delete(collection, 0, &query, NULL, NULL);
|
||||||
|
mongoc_collection_destroy(collection);
|
||||||
|
bson_destroy(&query);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mongo_set_secret(u08bits *secret, u08bits *realm) {
|
||||||
|
mongoc_collection_t * collection = mongo_get_collection("turn_secret");
|
||||||
|
|
||||||
|
if(!collection)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bson_t query;
|
||||||
|
bson_init(&query);
|
||||||
|
BSON_APPEND_UTF8(&query, "realm", (const char *)realm);
|
||||||
|
BSON_APPEND_UTF8(&query, "value", (const char *)secret);
|
||||||
|
|
||||||
|
int res = mongoc_collection_insert(collection, MONGOC_INSERT_NONE, &query, NULL, NULL);
|
||||||
|
mongoc_collection_destroy(collection);
|
||||||
|
bson_destroy(&query);
|
||||||
|
|
||||||
|
if (!res) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating secret key information\n");
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mongo_add_origin(u08bits *origin, u08bits *realm) {
|
||||||
|
mongoc_collection_t * collection = mongo_get_collection("realm");
|
||||||
|
|
||||||
|
if(!collection)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
bson_t query, doc, child;
|
||||||
|
bson_init(&query);
|
||||||
|
BSON_APPEND_UTF8(&query, "realm", (const char *)realm);
|
||||||
|
bson_init(&doc);
|
||||||
|
bson_append_document_begin(&doc, "$addToSet", -1, &child);
|
||||||
|
BSON_APPEND_UTF8(&child, "origin", (const char *)origin);
|
||||||
|
bson_append_document_end(&doc, &child);
|
||||||
|
|
||||||
|
if (!mongoc_collection_update(collection, MONGOC_UPDATE_UPSERT, &query, &doc, NULL, NULL)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating realm origin information\n");
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
mongoc_collection_destroy(collection);
|
||||||
|
bson_destroy(&query);
|
||||||
|
bson_destroy(&doc);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mongo_del_origin(u08bits *origin) {
|
||||||
|
mongoc_collection_t * collection = mongo_get_collection("realm");
|
||||||
|
|
||||||
|
if(!collection)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
bson_t query, doc, child;
|
||||||
|
bson_init(&query);
|
||||||
|
bson_init(&doc);
|
||||||
|
bson_append_document_begin(&doc, "$pull", -1, &child);
|
||||||
|
BSON_APPEND_UTF8(&child, "origin", (const char *)origin);
|
||||||
|
bson_append_document_end(&doc, &child);
|
||||||
|
|
||||||
|
if (!mongoc_collection_update(collection, MONGOC_UPDATE_MULTI_UPDATE, &query, &doc, NULL, NULL)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting origin information\n");
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
mongoc_collection_destroy(collection);
|
||||||
|
bson_destroy(&query);
|
||||||
|
bson_destroy(&doc);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mongo_list_origins(u08bits *realm) {
|
||||||
|
mongoc_collection_t * collection = mongo_get_collection("realm");
|
||||||
|
|
||||||
|
if(!collection)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bson_t query, child;
|
||||||
|
bson_init(&query);
|
||||||
|
bson_append_document_begin(&query, "$orderby", -1, &child);
|
||||||
|
BSON_APPEND_INT32(&child, "realm", 1);
|
||||||
|
bson_append_document_end(&query, &child);
|
||||||
|
bson_append_document_begin(&query, "$query", -1, &child);
|
||||||
|
if (realm && realm[0]) {
|
||||||
|
BSON_APPEND_UTF8(&child, "realm", (const char *)realm);
|
||||||
|
}
|
||||||
|
bson_append_document_end(&query, &child);
|
||||||
|
|
||||||
|
bson_t fields;
|
||||||
|
bson_init(&fields);
|
||||||
|
BSON_APPEND_INT32(&fields, "origin", 1);
|
||||||
|
BSON_APPEND_INT32(&fields, "realm", 1);
|
||||||
|
|
||||||
|
mongoc_cursor_t * cursor;
|
||||||
|
cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, &query, &fields, NULL);
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!cursor) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error querying MongoDB collection 'realm'\n");
|
||||||
|
} else {
|
||||||
|
const bson_t * item;
|
||||||
|
uint32_t length;
|
||||||
|
bson_iter_t iter;
|
||||||
|
|
||||||
|
while (mongoc_cursor_next(cursor, &item)) {
|
||||||
|
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "realm") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||||
|
const char * _realm = bson_iter_utf8(&iter, &length);
|
||||||
|
|
||||||
|
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "origin") && BSON_ITER_HOLDS_ARRAY(&iter)) {
|
||||||
|
const uint8_t *docbuf = NULL;
|
||||||
|
uint32_t doclen = 0;
|
||||||
|
bson_t origin_array;
|
||||||
|
bson_iter_t origin_iter;
|
||||||
|
|
||||||
|
bson_iter_array(&iter, &doclen, &docbuf);
|
||||||
|
bson_init_static(&origin_array, docbuf, doclen);
|
||||||
|
|
||||||
|
if (bson_iter_init(&origin_iter, &origin_array)) {
|
||||||
|
while(bson_iter_next(&origin_iter)) {
|
||||||
|
if (BSON_ITER_HOLDS_UTF8(&origin_iter)) {
|
||||||
|
const char * _origin = bson_iter_utf8(&origin_iter, &length);
|
||||||
|
printf("%s ==>> %s\n", _realm, _origin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mongoc_cursor_destroy(cursor);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
mongoc_collection_destroy(collection);
|
||||||
|
bson_destroy(&query);
|
||||||
|
bson_destroy(&fields);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mongo_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) {
|
||||||
|
mongoc_collection_t * collection = mongo_get_collection("realm");
|
||||||
|
|
||||||
|
if(!collection)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bson_t query, doc, child;
|
||||||
|
bson_init(&query);
|
||||||
|
BSON_APPEND_UTF8(&query, "realm", (const char *)realm);
|
||||||
|
bson_init(&doc);
|
||||||
|
|
||||||
|
char * _k = (char *)turn_malloc(9 + strlen(opt));
|
||||||
|
strcpy(_k, "options.");
|
||||||
|
strcat(_k, opt);
|
||||||
|
|
||||||
|
if (value > 0) {
|
||||||
|
bson_append_document_begin(&doc, "$set", -1, &child);
|
||||||
|
BSON_APPEND_INT32(&child, _k, (int32_t)value);
|
||||||
|
bson_append_document_end(&doc, &child);
|
||||||
|
} else {
|
||||||
|
bson_append_document_begin(&doc, "$unset", -1, &child);
|
||||||
|
BSON_APPEND_INT32(&child, _k, 1);
|
||||||
|
bson_append_document_end(&doc, &child);
|
||||||
|
}
|
||||||
|
free(_k);
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!mongoc_collection_update(collection, MONGOC_UPDATE_MULTI_UPDATE, &query, &doc, NULL, NULL)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting origin information\n");
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
mongoc_collection_destroy(collection);
|
||||||
|
bson_destroy(&query);
|
||||||
|
bson_destroy(&doc);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mongo_list_realm_options(u08bits *realm) {
|
||||||
|
mongoc_collection_t * collection = mongo_get_collection("realm");
|
||||||
|
|
||||||
|
if(!collection)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bson_t query, child;
|
||||||
|
bson_init(&query);
|
||||||
|
bson_append_document_begin(&query, "$orderby", -1, &child);
|
||||||
|
BSON_APPEND_INT32(&child, "realm", 1);
|
||||||
|
bson_append_document_end(&query, &child);
|
||||||
|
bson_append_document_begin(&query, "$query", -1, &child);
|
||||||
|
if (realm && realm[0]) {
|
||||||
|
BSON_APPEND_UTF8(&child, "realm", (const char *)realm);
|
||||||
|
}
|
||||||
|
bson_append_document_end(&query, &child);
|
||||||
|
|
||||||
|
bson_t fields;
|
||||||
|
bson_init(&fields);
|
||||||
|
BSON_APPEND_INT32(&fields, "options", 1);
|
||||||
|
BSON_APPEND_INT32(&fields, "realm", 1);
|
||||||
|
|
||||||
|
mongoc_cursor_t * cursor;
|
||||||
|
cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, &query, &fields, NULL);
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!cursor) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error querying MongoDB collection 'realm'\n");
|
||||||
|
} else {
|
||||||
|
const bson_t * item;
|
||||||
|
uint32_t length;
|
||||||
|
bson_iter_t iter;
|
||||||
|
|
||||||
|
while (mongoc_cursor_next(cursor, &item)) {
|
||||||
|
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "realm") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||||
|
const char * _realm = bson_iter_utf8(&iter, &length);
|
||||||
|
|
||||||
|
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "options") && BSON_ITER_HOLDS_DOCUMENT(&iter)) {
|
||||||
|
const uint8_t *docbuf = NULL;
|
||||||
|
uint32_t doclen = 0;
|
||||||
|
bson_t options;
|
||||||
|
bson_iter_t options_iter;
|
||||||
|
|
||||||
|
bson_iter_document(&iter, &doclen, &docbuf);
|
||||||
|
bson_init_static(&options, docbuf, doclen);
|
||||||
|
|
||||||
|
if (bson_iter_init(&options_iter, &options)) {
|
||||||
|
while(bson_iter_next(&options_iter)) {
|
||||||
|
const char * _k = bson_iter_key(&options_iter);
|
||||||
|
printf("key %s, type %d\n", _k, bson_iter_type(&options_iter));
|
||||||
|
if (BSON_ITER_HOLDS_DOUBLE(&options_iter)) {
|
||||||
|
int32_t _v = (int32_t)bson_iter_double(&options_iter);
|
||||||
|
printf("%s[%s]=%d\n", _k, _realm, _v);
|
||||||
|
} else if (BSON_ITER_HOLDS_INT32(&options_iter)) {
|
||||||
|
int32_t _v = bson_iter_int32(&options_iter);
|
||||||
|
printf("%s[%s]=%d\n", _k, _realm, _v);
|
||||||
|
} else if (BSON_ITER_HOLDS_INT64(&options_iter)) {
|
||||||
|
int32_t _v = (int32_t)bson_iter_int64(&options_iter);
|
||||||
|
printf("%s[%s]=%d\n", _k, _realm, _v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mongoc_cursor_destroy(cursor);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
mongoc_collection_destroy(collection);
|
||||||
|
bson_destroy(&query);
|
||||||
|
bson_destroy(&fields);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mongo_auth_ping(void * rch) {
|
||||||
|
UNUSED_ARG(rch);
|
||||||
|
// NOOP
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mongo_get_ip_list(const char *kind, ip_range_list_t * list) {
|
||||||
|
char * collection_name = (char *)turn_malloc(strlen(kind) + 9);
|
||||||
|
sprintf(collection_name, "%s_peer_ip", kind);
|
||||||
|
mongoc_collection_t * collection = mongo_get_collection(collection_name);
|
||||||
|
turn_free(collection_name, strlen(kind) + 9);
|
||||||
|
|
||||||
|
if(!collection)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bson_t query;
|
||||||
|
bson_init(&query);
|
||||||
|
|
||||||
|
bson_t fields;
|
||||||
|
bson_init(&fields);
|
||||||
|
BSON_APPEND_INT32(&fields, "ip_range", 1);
|
||||||
|
|
||||||
|
mongoc_cursor_t * cursor;
|
||||||
|
cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, &query, &fields, NULL);
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!cursor) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error querying MongoDB collection '%s'\n", collection_name);
|
||||||
|
} else {
|
||||||
|
const bson_t * item;
|
||||||
|
uint32_t length;
|
||||||
|
bson_iter_t iter;
|
||||||
|
const char * value;
|
||||||
|
while(mongoc_cursor_next(cursor, &item)) {
|
||||||
|
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "value") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||||
|
value = bson_iter_utf8(&iter, &length);
|
||||||
|
add_ip_list_range(value, list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mongoc_cursor_destroy(cursor);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
mongoc_collection_destroy(collection);
|
||||||
|
bson_destroy(&query);
|
||||||
|
bson_destroy(&fields);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mongo_reread_realms(secrets_list_t * realms_list) {
|
||||||
|
UNUSED_ARG(realms_list);
|
||||||
|
|
||||||
|
mongoc_collection_t * collection = mongo_get_collection("realm");
|
||||||
|
|
||||||
|
if(!collection)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bson_t query;
|
||||||
|
bson_init(&query);
|
||||||
|
|
||||||
|
bson_t fields;
|
||||||
|
bson_init(&fields);
|
||||||
|
BSON_APPEND_INT32(&fields, "realm", 1);
|
||||||
|
BSON_APPEND_INT32(&fields, "origin", 1);
|
||||||
|
BSON_APPEND_INT32(&fields, "options", 1);
|
||||||
|
|
||||||
|
mongoc_cursor_t * cursor;
|
||||||
|
cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, &query, &fields, NULL);
|
||||||
|
|
||||||
|
if (!cursor) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error querying MongoDB collection 'realm'\n");
|
||||||
|
} else {
|
||||||
|
ur_string_map *o_to_realm_new = ur_string_map_create(free);
|
||||||
|
|
||||||
|
const bson_t * item;
|
||||||
|
uint32_t length;
|
||||||
|
bson_iter_t iter;
|
||||||
|
|
||||||
|
while (mongoc_cursor_next(cursor, &item)) {
|
||||||
|
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "realm") && BSON_ITER_HOLDS_UTF8(&iter)) {
|
||||||
|
char * _realm = strdup(bson_iter_utf8(&iter, &length));
|
||||||
|
|
||||||
|
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "origin") && BSON_ITER_HOLDS_ARRAY(&iter)) {
|
||||||
|
const uint8_t *docbuf = NULL;
|
||||||
|
uint32_t doclen = 0;
|
||||||
|
bson_t origin_array;
|
||||||
|
bson_iter_t origin_iter;
|
||||||
|
|
||||||
|
bson_iter_array(&iter, &doclen, &docbuf);
|
||||||
|
bson_init_static(&origin_array, docbuf, doclen);
|
||||||
|
|
||||||
|
if (bson_iter_init(&origin_iter, &origin_array)) {
|
||||||
|
while(bson_iter_next(&origin_iter)) {
|
||||||
|
if (BSON_ITER_HOLDS_UTF8(&origin_iter)) {
|
||||||
|
const char * _origin = bson_iter_utf8(&origin_iter, &length);
|
||||||
|
ur_string_map_value_type value = strdup(_origin);
|
||||||
|
ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type)_realm, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
realm_params_t* rp = get_realm(_realm);
|
||||||
|
lock_realms();
|
||||||
|
rp->options.perf_options.max_bps = turn_params.max_bps;
|
||||||
|
rp->options.perf_options.total_quota = turn_params.total_quota;
|
||||||
|
rp->options.perf_options.user_quota = turn_params.user_quota;
|
||||||
|
unlock_realms();
|
||||||
|
|
||||||
|
if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "options") && BSON_ITER_HOLDS_DOCUMENT(&iter)) {
|
||||||
|
const uint8_t *docbuf = NULL;
|
||||||
|
uint32_t doclen = 0;
|
||||||
|
bson_t options;
|
||||||
|
bson_iter_t options_iter;
|
||||||
|
|
||||||
|
bson_iter_document(&iter, &doclen, &docbuf);
|
||||||
|
bson_init_static(&options, docbuf, doclen);
|
||||||
|
|
||||||
|
if (bson_iter_init(&options_iter, &options)) {
|
||||||
|
while(bson_iter_next(&options_iter)) {
|
||||||
|
const char * _k = bson_iter_key(&options_iter);
|
||||||
|
int32_t _v;
|
||||||
|
if (BSON_ITER_HOLDS_DOUBLE(&options_iter)) {
|
||||||
|
_v = (int32_t)bson_iter_double(&options_iter);
|
||||||
|
} else if (BSON_ITER_HOLDS_INT32(&options_iter)) {
|
||||||
|
_v = bson_iter_int32(&options_iter);
|
||||||
|
} else if (BSON_ITER_HOLDS_INT64(&options_iter)) {
|
||||||
|
_v = (int32_t)bson_iter_int64(&options_iter);
|
||||||
|
}
|
||||||
|
if (_v) {
|
||||||
|
if(!strcmp(_k,"max-bps"))
|
||||||
|
rp->options.perf_options.max_bps = (band_limit_t)_v;
|
||||||
|
else if(!strcmp(_k,"total-quota"))
|
||||||
|
rp->options.perf_options.total_quota = (vint)_v;
|
||||||
|
else if(!strcmp(_k,"user-quota"))
|
||||||
|
rp->options.perf_options.user_quota = (vint)_v;
|
||||||
|
else {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown realm option: %s\n", _k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(_realm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update_o_to_realm(o_to_realm_new);
|
||||||
|
mongoc_cursor_destroy(cursor);
|
||||||
|
}
|
||||||
|
mongoc_collection_destroy(collection);
|
||||||
|
bson_destroy(&query);
|
||||||
|
bson_destroy(&fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static turn_dbdriver_t driver = {
|
||||||
|
&mongo_get_auth_secrets,
|
||||||
|
&mongo_get_user_key,
|
||||||
|
&mongo_get_user_pwd,
|
||||||
|
&mongo_set_user_key,
|
||||||
|
&mongo_set_user_pwd,
|
||||||
|
&mongo_del_user,
|
||||||
|
&mongo_list_users,
|
||||||
|
&mongo_show_secret,
|
||||||
|
&mongo_del_secret,
|
||||||
|
&mongo_set_secret,
|
||||||
|
&mongo_add_origin,
|
||||||
|
&mongo_del_origin,
|
||||||
|
&mongo_list_origins,
|
||||||
|
&mongo_set_realm_option_one,
|
||||||
|
&mongo_list_realm_options,
|
||||||
|
&mongo_auth_ping,
|
||||||
|
&mongo_get_ip_list,
|
||||||
|
&mongo_reread_realms
|
||||||
|
};
|
||||||
|
|
||||||
|
turn_dbdriver_t * get_mongo_dbdriver(void) {
|
||||||
|
return &driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
turn_dbdriver_t * get_mongo_dbdriver(void) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
49
src/apps/relay/dbdrivers/dbd_mongo.h
Normal file
49
src/apps/relay/dbdrivers/dbd_mongo.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011, 2012, 2013 Citrix Systems
|
||||||
|
* Copyright (C) 2014 Vivocha S.p.A.
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the project nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DBD_MONGODB__
|
||||||
|
#define __DBD_MONGODB__
|
||||||
|
|
||||||
|
#include "dbdriver.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
turn_dbdriver_t * get_mongo_dbdriver(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/// __DBD_MONGODB__///
|
||||||
|
|
||||||
870
src/apps/relay/dbdrivers/dbd_mysql.c
Normal file
870
src/apps/relay/dbdrivers/dbd_mysql.c
Normal file
@ -0,0 +1,870 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011, 2012, 2013 Citrix Systems
|
||||||
|
* Copyright (C) 2014 Vivocha S.p.A.
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the project nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../mainrelay.h"
|
||||||
|
#include "dbd_mysql.h"
|
||||||
|
|
||||||
|
#if !defined(TURN_NO_MYSQL)
|
||||||
|
#include <mysql.h>
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static int donot_print_connection_success = 0;
|
||||||
|
|
||||||
|
struct _Myconninfo {
|
||||||
|
char *host;
|
||||||
|
char *dbname;
|
||||||
|
char *user;
|
||||||
|
char *password;
|
||||||
|
unsigned int port;
|
||||||
|
unsigned int connect_timeout;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _Myconninfo Myconninfo;
|
||||||
|
|
||||||
|
static void MyconninfoFree(Myconninfo *co) {
|
||||||
|
if(co) {
|
||||||
|
if(co->host) turn_free(co->host,strlen(co->host)+1);
|
||||||
|
if(co->dbname) turn_free(co->dbname, strlen(co->dbname)+1);
|
||||||
|
if(co->user) turn_free(co->user, strlen(co->user)+1);
|
||||||
|
if(co->password) turn_free(co->password, strlen(co->password)+1);
|
||||||
|
ns_bzero(co,sizeof(Myconninfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Myconninfo *MyconninfoParse(char *userdb, char **errmsg) {
|
||||||
|
Myconninfo *co = (Myconninfo*)turn_malloc(sizeof(Myconninfo));
|
||||||
|
ns_bzero(co,sizeof(Myconninfo));
|
||||||
|
if(userdb) {
|
||||||
|
char *s0=strdup(userdb);
|
||||||
|
char *s = s0;
|
||||||
|
|
||||||
|
while(s && *s) {
|
||||||
|
|
||||||
|
while(*s && (*s==' ')) ++s;
|
||||||
|
char *snext = strstr(s," ");
|
||||||
|
if(snext) {
|
||||||
|
*snext = 0;
|
||||||
|
++snext;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* seq = strstr(s,"=");
|
||||||
|
if(!seq) {
|
||||||
|
MyconninfoFree(co);
|
||||||
|
co = NULL;
|
||||||
|
if(errmsg) {
|
||||||
|
*errmsg = strdup(s);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*seq = 0;
|
||||||
|
if(!strcmp(s,"host"))
|
||||||
|
co->host = strdup(seq+1);
|
||||||
|
else if(!strcmp(s,"ip"))
|
||||||
|
co->host = strdup(seq+1);
|
||||||
|
else if(!strcmp(s,"addr"))
|
||||||
|
co->host = strdup(seq+1);
|
||||||
|
else if(!strcmp(s,"ipaddr"))
|
||||||
|
co->host = strdup(seq+1);
|
||||||
|
else if(!strcmp(s,"hostaddr"))
|
||||||
|
co->host = strdup(seq+1);
|
||||||
|
else if(!strcmp(s,"dbname"))
|
||||||
|
co->dbname = strdup(seq+1);
|
||||||
|
else if(!strcmp(s,"db"))
|
||||||
|
co->dbname = strdup(seq+1);
|
||||||
|
else if(!strcmp(s,"database"))
|
||||||
|
co->dbname = strdup(seq+1);
|
||||||
|
else if(!strcmp(s,"user"))
|
||||||
|
co->user = strdup(seq+1);
|
||||||
|
else if(!strcmp(s,"uname"))
|
||||||
|
co->user = strdup(seq+1);
|
||||||
|
else if(!strcmp(s,"name"))
|
||||||
|
co->user = strdup(seq+1);
|
||||||
|
else if(!strcmp(s,"username"))
|
||||||
|
co->user = strdup(seq+1);
|
||||||
|
else if(!strcmp(s,"password"))
|
||||||
|
co->password = strdup(seq+1);
|
||||||
|
else if(!strcmp(s,"pwd"))
|
||||||
|
co->password = strdup(seq+1);
|
||||||
|
else if(!strcmp(s,"passwd"))
|
||||||
|
co->password = strdup(seq+1);
|
||||||
|
else if(!strcmp(s,"secret"))
|
||||||
|
co->password = strdup(seq+1);
|
||||||
|
else if(!strcmp(s,"port"))
|
||||||
|
co->port = (unsigned int)atoi(seq+1);
|
||||||
|
else if(!strcmp(s,"p"))
|
||||||
|
co->port = (unsigned int)atoi(seq+1);
|
||||||
|
else if(!strcmp(s,"connect_timeout"))
|
||||||
|
co->connect_timeout = (unsigned int)atoi(seq+1);
|
||||||
|
else if(!strcmp(s,"timeout"))
|
||||||
|
co->connect_timeout = (unsigned int)atoi(seq+1);
|
||||||
|
else {
|
||||||
|
MyconninfoFree(co);
|
||||||
|
co = NULL;
|
||||||
|
if(errmsg) {
|
||||||
|
*errmsg = strdup(s);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = snext;
|
||||||
|
}
|
||||||
|
|
||||||
|
turn_free(s0, strlen(s0)+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!(co->dbname))
|
||||||
|
co->dbname=strdup("0");
|
||||||
|
if(!(co->host))
|
||||||
|
co->host=strdup("127.0.0.1");
|
||||||
|
if(!(co->user))
|
||||||
|
co->user=strdup("");
|
||||||
|
if(!(co->password))
|
||||||
|
co->password=strdup("");
|
||||||
|
|
||||||
|
return co;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MYSQL *get_mydb_connection(void) {
|
||||||
|
persistent_users_db_t *pud = get_persistent_users_db();
|
||||||
|
|
||||||
|
MYSQL *mydbconnection = (MYSQL*)(pud->connection);
|
||||||
|
|
||||||
|
if(mydbconnection) {
|
||||||
|
if(mysql_ping(mydbconnection)) {
|
||||||
|
mysql_close(mydbconnection);
|
||||||
|
mydbconnection=NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!mydbconnection) {
|
||||||
|
char *errmsg=NULL;
|
||||||
|
Myconninfo *co=MyconninfoParse(pud->userdb, &errmsg);
|
||||||
|
if(!co) {
|
||||||
|
if(errmsg) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open MySQL DB connection <%s>, connection string format error: %s\n",pud->userdb,errmsg);
|
||||||
|
turn_free(errmsg,strlen(errmsg)+1);
|
||||||
|
} else {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open MySQL DB connection <%s>, connection string format error\n",pud->userdb);
|
||||||
|
}
|
||||||
|
} else if(errmsg) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open MySQL DB connection <%s>, connection string format error: %s\n",pud->userdb,errmsg);
|
||||||
|
turn_free(errmsg,strlen(errmsg)+1);
|
||||||
|
MyconninfoFree(co);
|
||||||
|
} else if(!(co->dbname)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "MySQL Database name is not provided: <%s>\n",pud->userdb);
|
||||||
|
MyconninfoFree(co);
|
||||||
|
} else {
|
||||||
|
mydbconnection = mysql_init(NULL);
|
||||||
|
if(!mydbconnection) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize MySQL DB connection\n");
|
||||||
|
} else {
|
||||||
|
if(co->connect_timeout)
|
||||||
|
mysql_options(mydbconnection,MYSQL_OPT_CONNECT_TIMEOUT,&(co->connect_timeout));
|
||||||
|
MYSQL *conn = mysql_real_connect(mydbconnection, co->host, co->user, co->password, co->dbname, co->port, NULL, CLIENT_IGNORE_SIGPIPE);
|
||||||
|
if(!conn) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open MySQL DB connection: <%s>, runtime error\n",pud->userdb);
|
||||||
|
mysql_close(mydbconnection);
|
||||||
|
mydbconnection=NULL;
|
||||||
|
} else if(mysql_select_db(mydbconnection, co->dbname)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot connect to MySQL DB: %s\n",co->dbname);
|
||||||
|
mysql_close(mydbconnection);
|
||||||
|
mydbconnection=NULL;
|
||||||
|
} else if(!donot_print_connection_success) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "MySQL DB connection success: %s\n",pud->userdb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MyconninfoFree(co);
|
||||||
|
}
|
||||||
|
pud->connection = mydbconnection;
|
||||||
|
}
|
||||||
|
return mydbconnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static int mysql_get_auth_secrets(secrets_list_t *sl, u08bits *realm) {
|
||||||
|
int ret = -1;
|
||||||
|
MYSQL * myc = get_mydb_connection();
|
||||||
|
if(myc) {
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
snprintf(statement,sizeof(statement)-1,"select value from turn_secret where realm='%s'",realm);
|
||||||
|
int res = mysql_query(myc, statement);
|
||||||
|
if(res) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||||
|
} else {
|
||||||
|
MYSQL_RES *mres = mysql_store_result(myc);
|
||||||
|
if(!mres) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||||
|
} else if(mysql_field_count(myc)==1) {
|
||||||
|
for(;;) {
|
||||||
|
MYSQL_ROW row = mysql_fetch_row(mres);
|
||||||
|
if(!row) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if(row[0]) {
|
||||||
|
unsigned long *lengths = mysql_fetch_lengths(mres);
|
||||||
|
if(lengths) {
|
||||||
|
size_t sz = lengths[0];
|
||||||
|
char auth_secret[TURN_LONG_STRING_SIZE];
|
||||||
|
ns_bcopy(row[0],auth_secret,sz);
|
||||||
|
auth_secret[sz]=0;
|
||||||
|
add_to_secrets_list(sl,auth_secret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mres)
|
||||||
|
mysql_free_result(mres);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mysql_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) {
|
||||||
|
int ret = -1;
|
||||||
|
MYSQL * myc = get_mydb_connection();
|
||||||
|
if(myc) {
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
snprintf(statement,sizeof(statement),"select hmackey from turnusers_lt where name='%s' and realm='%s'",usname,realm);
|
||||||
|
int res = mysql_query(myc, statement);
|
||||||
|
if(res) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||||
|
} else {
|
||||||
|
MYSQL_RES *mres = mysql_store_result(myc);
|
||||||
|
if(!mres) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||||
|
} else if(mysql_field_count(myc)!=1) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement);
|
||||||
|
} else {
|
||||||
|
MYSQL_ROW row = mysql_fetch_row(mres);
|
||||||
|
if(row && row[0]) {
|
||||||
|
unsigned long *lengths = mysql_fetch_lengths(mres);
|
||||||
|
if(lengths) {
|
||||||
|
size_t sz = get_hmackey_size(turn_params.shatype)*2;
|
||||||
|
if(lengths[0]<sz) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key format: string length=%d (must be %d): user %s\n",(int)lengths[0],(int)sz,usname);
|
||||||
|
} else {
|
||||||
|
char kval[sizeof(hmackey_t)+sizeof(hmackey_t)+1];
|
||||||
|
ns_bcopy(row[0],kval,sz);
|
||||||
|
kval[sz]=0;
|
||||||
|
if(convert_string_key_to_binary(kval, key, sz/2)<0) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key: %s, user %s\n",kval,usname);
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mres)
|
||||||
|
mysql_free_result(mres);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mysql_get_user_pwd(u08bits *usname, st_password_t pwd) {
|
||||||
|
int ret = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
snprintf(statement,sizeof(statement),"select password from turnusers_st where name='%s'",usname);
|
||||||
|
|
||||||
|
MYSQL * myc = get_mydb_connection();
|
||||||
|
if(myc) {
|
||||||
|
int res = mysql_query(myc, statement);
|
||||||
|
if(res) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||||
|
} else {
|
||||||
|
MYSQL_RES *mres = mysql_store_result(myc);
|
||||||
|
if(!mres) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||||
|
} else if(mysql_field_count(myc)!=1) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement);
|
||||||
|
} else {
|
||||||
|
MYSQL_ROW row = mysql_fetch_row(mres);
|
||||||
|
if(row && row[0]) {
|
||||||
|
unsigned long *lengths = mysql_fetch_lengths(mres);
|
||||||
|
if(lengths) {
|
||||||
|
if(lengths[0]<1) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong password data for user %s, size in MySQL DB is zero(0)\n",usname);
|
||||||
|
} else {
|
||||||
|
ns_bcopy(row[0],pwd,lengths[0]);
|
||||||
|
pwd[lengths[0]]=0;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mres)
|
||||||
|
mysql_free_result(mres);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mysql_set_user_key(u08bits *usname, u08bits *realm, const char *key) {
|
||||||
|
int ret = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
MYSQL * myc = get_mydb_connection();
|
||||||
|
if(myc) {
|
||||||
|
snprintf(statement,sizeof(statement),"insert into turnusers_lt (realm,name,hmackey) values('%s','%s','%s')",realm,usname,key);
|
||||||
|
int res = mysql_query(myc, statement);
|
||||||
|
if(res) {
|
||||||
|
snprintf(statement,sizeof(statement),"update turnusers_lt set hmackey='%s' where name='%s' and realm='%s'",key,usname,realm);
|
||||||
|
res = mysql_query(myc, statement);
|
||||||
|
if(res) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating user key information: %s\n",mysql_error(myc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mysql_set_user_pwd(u08bits *usname, st_password_t pwd) {
|
||||||
|
int ret = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
MYSQL * myc = get_mydb_connection();
|
||||||
|
if(myc) {
|
||||||
|
snprintf(statement,sizeof(statement),"insert into turnusers_st values('%s','%s')",usname,pwd);
|
||||||
|
int res = mysql_query(myc, statement);
|
||||||
|
if(res) {
|
||||||
|
snprintf(statement,sizeof(statement),"update turnusers_st set password='%s' where name='%s'",pwd,usname);
|
||||||
|
res = mysql_query(myc, statement);
|
||||||
|
if(res) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating user key information: %s\n",mysql_error(myc));
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mysql_del_user(u08bits *usname, int is_st, u08bits *realm) {
|
||||||
|
int ret = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
MYSQL * myc = get_mydb_connection();
|
||||||
|
if(myc) {
|
||||||
|
if(is_st) {
|
||||||
|
snprintf(statement,sizeof(statement),"delete from turnusers_st where name='%s'",usname);
|
||||||
|
} else {
|
||||||
|
snprintf(statement,sizeof(statement),"delete from turnusers_lt where name='%s' and realm='%s'",usname,realm);
|
||||||
|
}
|
||||||
|
int res = mysql_query(myc, statement);
|
||||||
|
if(res) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting user key information: %s\n",mysql_error(myc));
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mysql_list_users(int is_st, u08bits *realm) {
|
||||||
|
int ret = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
MYSQL * myc = get_mydb_connection();
|
||||||
|
if(myc) {
|
||||||
|
if(is_st) {
|
||||||
|
snprintf(statement,sizeof(statement),"select name from turnusers_st order by name");
|
||||||
|
} else if(realm && realm[0]) {
|
||||||
|
snprintf(statement,sizeof(statement),"select name from turnusers_lt where realm='%s' order by name",realm);
|
||||||
|
} else {
|
||||||
|
snprintf(statement,sizeof(statement),"select name from turnusers_lt order by name");
|
||||||
|
}
|
||||||
|
int res = mysql_query(myc, statement);
|
||||||
|
if(res) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||||
|
} else {
|
||||||
|
MYSQL_RES *mres = mysql_store_result(myc);
|
||||||
|
if(!mres) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||||
|
} else if(mysql_field_count(myc)!=1) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement);
|
||||||
|
} else {
|
||||||
|
for(;;) {
|
||||||
|
MYSQL_ROW row = mysql_fetch_row(mres);
|
||||||
|
if(!row) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if(row[0]) {
|
||||||
|
printf("%s\n",row[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mres)
|
||||||
|
mysql_free_result(mres);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mysql_show_secret(u08bits *realm) {
|
||||||
|
int ret = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
snprintf(statement,sizeof(statement)-1,"select value from turn_secret where realm='%s'",realm);
|
||||||
|
|
||||||
|
donot_print_connection_success=1;
|
||||||
|
|
||||||
|
MYSQL * myc = get_mydb_connection();
|
||||||
|
if(myc) {
|
||||||
|
int res = mysql_query(myc, statement);
|
||||||
|
if(res) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||||
|
} else {
|
||||||
|
MYSQL_RES *mres = mysql_store_result(myc);
|
||||||
|
if(!mres) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||||
|
} else if(mysql_field_count(myc)!=1) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement);
|
||||||
|
} else {
|
||||||
|
for(;;) {
|
||||||
|
MYSQL_ROW row = mysql_fetch_row(mres);
|
||||||
|
if(!row) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if(row[0]) {
|
||||||
|
printf("%s\n",row[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mres)
|
||||||
|
mysql_free_result(mres);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mysql_del_secret(u08bits *secret, u08bits *realm) {
|
||||||
|
int ret = 1;
|
||||||
|
donot_print_connection_success=1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
MYSQL * myc = get_mydb_connection();
|
||||||
|
if (myc) {
|
||||||
|
if(!secret || (secret[0]==0))
|
||||||
|
snprintf(statement,sizeof(statement),"delete from turn_secret where realm='%s'",realm);
|
||||||
|
else
|
||||||
|
snprintf(statement,sizeof(statement),"delete from turn_secret where value='%s' and realm='%s'",secret,realm);
|
||||||
|
mysql_query(myc, statement);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mysql_set_secret(u08bits *secret, u08bits *realm) {
|
||||||
|
int ret = 1;
|
||||||
|
donot_print_connection_success = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
MYSQL * myc = get_mydb_connection();
|
||||||
|
if (myc) {
|
||||||
|
snprintf(statement,sizeof(statement),"insert into turn_secret (realm,value) values('%s','%s')",realm,secret);
|
||||||
|
int res = mysql_query(myc, statement);
|
||||||
|
if (res) {
|
||||||
|
TURN_LOG_FUNC(
|
||||||
|
TURN_LOG_LEVEL_ERROR,
|
||||||
|
"Error inserting/updating secret key information: %s\n",
|
||||||
|
mysql_error(myc));
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mysql_add_origin(u08bits *origin, u08bits *realm) {
|
||||||
|
int ret = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
MYSQL * myc = get_mydb_connection();
|
||||||
|
if (myc) {
|
||||||
|
snprintf(statement,sizeof(statement),"insert into turn_origin_to_realm (origin,realm) values('%s','%s')",origin,realm);
|
||||||
|
int res = mysql_query(myc, statement);
|
||||||
|
if (res) {
|
||||||
|
TURN_LOG_FUNC(
|
||||||
|
TURN_LOG_LEVEL_ERROR,
|
||||||
|
"Error inserting origin information: %s\n",
|
||||||
|
mysql_error(myc));
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mysql_del_origin(u08bits *origin) {
|
||||||
|
int ret = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
MYSQL * myc = get_mydb_connection();
|
||||||
|
if (myc) {
|
||||||
|
snprintf(statement,sizeof(statement),"delete from turn_origin_to_realm where origin='%s'",origin);
|
||||||
|
int res = mysql_query(myc, statement);
|
||||||
|
if (res) {
|
||||||
|
TURN_LOG_FUNC(
|
||||||
|
TURN_LOG_LEVEL_ERROR,
|
||||||
|
"Error deleting origin information: %s\n",
|
||||||
|
mysql_error(myc));
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mysql_list_origins(u08bits *realm) {
|
||||||
|
int ret = 1;
|
||||||
|
donot_print_connection_success = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
MYSQL * myc = get_mydb_connection();
|
||||||
|
if(myc) {
|
||||||
|
if(realm && realm[0]) {
|
||||||
|
snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm where realm='%s' order by origin",realm);
|
||||||
|
} else {
|
||||||
|
snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm order by origin,realm");
|
||||||
|
}
|
||||||
|
int res = mysql_query(myc, statement);
|
||||||
|
if(res) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||||
|
} else {
|
||||||
|
MYSQL_RES *mres = mysql_store_result(myc);
|
||||||
|
if(!mres) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||||
|
} else if(mysql_field_count(myc)!=2) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement);
|
||||||
|
} else {
|
||||||
|
for(;;) {
|
||||||
|
MYSQL_ROW row = mysql_fetch_row(mres);
|
||||||
|
if(!row) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if(row[0] && row[1]) {
|
||||||
|
printf("%s ==>> %s\n",row[0],row[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mres)
|
||||||
|
mysql_free_result(mres);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mysql_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) {
|
||||||
|
int ret = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
MYSQL * myc = get_mydb_connection();
|
||||||
|
if (myc) {
|
||||||
|
{
|
||||||
|
snprintf(statement,sizeof(statement),"delete from turn_realm_option where realm='%s' and opt='%s'",realm,opt);
|
||||||
|
mysql_query(myc, statement);
|
||||||
|
}
|
||||||
|
if(value>0) {
|
||||||
|
snprintf(statement,sizeof(statement),"insert into turn_realm_option (realm,opt,value) values('%s','%s','%lu')",realm,opt,(unsigned long)value);
|
||||||
|
int res = mysql_query(myc, statement);
|
||||||
|
if (res) {
|
||||||
|
TURN_LOG_FUNC(
|
||||||
|
TURN_LOG_LEVEL_ERROR,
|
||||||
|
"Error inserting realm option information: %s\n",
|
||||||
|
mysql_error(myc));
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mysql_list_realm_options(u08bits *realm) {
|
||||||
|
int ret = 1;
|
||||||
|
donot_print_connection_success = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
MYSQL * myc = get_mydb_connection();
|
||||||
|
if(myc) {
|
||||||
|
if(realm && realm[0]) {
|
||||||
|
snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option where realm='%s' order by realm,opt",realm);
|
||||||
|
} else {
|
||||||
|
snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option order by realm,opt");
|
||||||
|
}
|
||||||
|
int res = mysql_query(myc, statement);
|
||||||
|
if(res) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||||
|
} else {
|
||||||
|
MYSQL_RES *mres = mysql_store_result(myc);
|
||||||
|
if(!mres) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||||
|
} else if(mysql_field_count(myc)!=3) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown error retrieving MySQL DB information: %s\n",statement);
|
||||||
|
} else {
|
||||||
|
for(;;) {
|
||||||
|
MYSQL_ROW row = mysql_fetch_row(mres);
|
||||||
|
if(!row) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if(row[0] && row[1] && row[2]) {
|
||||||
|
printf("%s[%s]=%s\n",row[1],row[0],row[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mres)
|
||||||
|
mysql_free_result(mres);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mysql_auth_ping(void * rch) {
|
||||||
|
UNUSED_ARG(rch);
|
||||||
|
donot_print_connection_success = 1;
|
||||||
|
MYSQL * myc = get_mydb_connection();
|
||||||
|
if(myc) {
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
STRCPY(statement,"select value from turn_secret");
|
||||||
|
int res = mysql_query(myc, statement);
|
||||||
|
if(res) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||||
|
} else {
|
||||||
|
MYSQL_RES *mres = mysql_store_result(myc);
|
||||||
|
if(!mres) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information: %s\n",mysql_error(myc));
|
||||||
|
} else {
|
||||||
|
mysql_free_result(mres);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mysql_get_ip_list(const char *kind, ip_range_list_t * list) {
|
||||||
|
int ret = 1;
|
||||||
|
MYSQL * myc = get_mydb_connection();
|
||||||
|
if(myc) {
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
snprintf(statement,sizeof(statement),"select ip_range from %s_peer_ip",kind);
|
||||||
|
int res = mysql_query(myc, statement);
|
||||||
|
if(res == 0) {
|
||||||
|
MYSQL_RES *mres = mysql_store_result(myc);
|
||||||
|
if(mres && mysql_field_count(myc)==1) {
|
||||||
|
for(;;) {
|
||||||
|
MYSQL_ROW row = mysql_fetch_row(mres);
|
||||||
|
if(!row) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if(row[0]) {
|
||||||
|
unsigned long *lengths = mysql_fetch_lengths(mres);
|
||||||
|
if(lengths) {
|
||||||
|
size_t sz = lengths[0];
|
||||||
|
char kval[TURN_LONG_STRING_SIZE];
|
||||||
|
ns_bcopy(row[0],kval,sz);
|
||||||
|
kval[sz]=0;
|
||||||
|
add_ip_list_range(kval,list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mres)
|
||||||
|
mysql_free_result(mres);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mysql_reread_realms(secrets_list_t * realms_list) {
|
||||||
|
MYSQL * myc = get_mydb_connection();
|
||||||
|
if(myc) {
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
{
|
||||||
|
snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm");
|
||||||
|
int res = mysql_query(myc, statement);
|
||||||
|
if(res == 0) {
|
||||||
|
MYSQL_RES *mres = mysql_store_result(myc);
|
||||||
|
if(mres && mysql_field_count(myc)==2) {
|
||||||
|
|
||||||
|
ur_string_map *o_to_realm_new = ur_string_map_create(free);
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
MYSQL_ROW row = mysql_fetch_row(mres);
|
||||||
|
if(!row) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if(row[0] && row[1]) {
|
||||||
|
unsigned long *lengths = mysql_fetch_lengths(mres);
|
||||||
|
if(lengths) {
|
||||||
|
size_t sz = lengths[0];
|
||||||
|
char oval[513];
|
||||||
|
ns_bcopy(row[0],oval,sz);
|
||||||
|
oval[sz]=0;
|
||||||
|
char *rval=strdup(row[1]);
|
||||||
|
get_realm(rval);
|
||||||
|
ur_string_map_value_type value = strdup(rval);
|
||||||
|
ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) oval, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update_o_to_realm(o_to_realm_new);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mres)
|
||||||
|
mysql_free_result(mres);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
size_t rlsz = 0;
|
||||||
|
|
||||||
|
lock_realms();
|
||||||
|
rlsz = realms_list->sz;
|
||||||
|
unlock_realms();
|
||||||
|
|
||||||
|
for (i = 0; i<rlsz; ++i) {
|
||||||
|
|
||||||
|
char *realm = realms_list->secrets[i];
|
||||||
|
|
||||||
|
realm_params_t* rp = get_realm(realm);
|
||||||
|
|
||||||
|
lock_realms();
|
||||||
|
rp->options.perf_options.max_bps = turn_params.max_bps;
|
||||||
|
unlock_realms();
|
||||||
|
|
||||||
|
lock_realms();
|
||||||
|
rp->options.perf_options.total_quota = turn_params.total_quota;
|
||||||
|
unlock_realms();
|
||||||
|
|
||||||
|
lock_realms();
|
||||||
|
rp->options.perf_options.user_quota = turn_params.user_quota;
|
||||||
|
unlock_realms();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option");
|
||||||
|
int res = mysql_query(myc, statement);
|
||||||
|
if(res == 0) {
|
||||||
|
MYSQL_RES *mres = mysql_store_result(myc);
|
||||||
|
if(mres && mysql_field_count(myc)==3) {
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
MYSQL_ROW row = mysql_fetch_row(mres);
|
||||||
|
if(!row) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if(row[0] && row[1] && row[2]) {
|
||||||
|
unsigned long *lengths = mysql_fetch_lengths(mres);
|
||||||
|
if(lengths) {
|
||||||
|
char rval[513];
|
||||||
|
size_t sz = lengths[0];
|
||||||
|
ns_bcopy(row[0],rval,sz);
|
||||||
|
rval[sz]=0;
|
||||||
|
char oval[513];
|
||||||
|
sz = lengths[1];
|
||||||
|
ns_bcopy(row[1],oval,sz);
|
||||||
|
oval[sz]=0;
|
||||||
|
char vval[513];
|
||||||
|
sz = lengths[2];
|
||||||
|
ns_bcopy(row[2],vval,sz);
|
||||||
|
vval[sz]=0;
|
||||||
|
realm_params_t* rp = get_realm(rval);
|
||||||
|
if(!strcmp(oval,"max-bps"))
|
||||||
|
rp->options.perf_options.max_bps = (band_limit_t)atol(vval);
|
||||||
|
else if(!strcmp(oval,"total-quota"))
|
||||||
|
rp->options.perf_options.total_quota = (vint)atoi(vval);
|
||||||
|
else if(!strcmp(oval,"user-quota"))
|
||||||
|
rp->options.perf_options.user_quota = (vint)atoi(vval);
|
||||||
|
else {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown realm option: %s\n", oval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mres)
|
||||||
|
mysql_free_result(mres);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static turn_dbdriver_t driver = {
|
||||||
|
&mysql_get_auth_secrets,
|
||||||
|
&mysql_get_user_key,
|
||||||
|
&mysql_get_user_pwd,
|
||||||
|
&mysql_set_user_key,
|
||||||
|
&mysql_set_user_pwd,
|
||||||
|
&mysql_del_user,
|
||||||
|
&mysql_list_users,
|
||||||
|
&mysql_show_secret,
|
||||||
|
&mysql_del_secret,
|
||||||
|
&mysql_set_secret,
|
||||||
|
&mysql_add_origin,
|
||||||
|
&mysql_del_origin,
|
||||||
|
&mysql_list_origins,
|
||||||
|
&mysql_set_realm_option_one,
|
||||||
|
&mysql_list_realm_options,
|
||||||
|
&mysql_auth_ping,
|
||||||
|
&mysql_get_ip_list,
|
||||||
|
&mysql_reread_realms
|
||||||
|
};
|
||||||
|
|
||||||
|
turn_dbdriver_t * get_mysql_dbdriver(void) {
|
||||||
|
return &driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
turn_dbdriver_t * get_mysql_dbdriver(void) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
49
src/apps/relay/dbdrivers/dbd_mysql.h
Normal file
49
src/apps/relay/dbdrivers/dbd_mysql.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011, 2012, 2013 Citrix Systems
|
||||||
|
* Copyright (C) 2014 Vivocha S.p.A.
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the project nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DBD_MYSQL__
|
||||||
|
#define __DBD_MYSQL__
|
||||||
|
|
||||||
|
#include "dbdriver.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
turn_dbdriver_t * get_mysql_dbdriver(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/// __DBD_MYSQL__///
|
||||||
|
|
||||||
668
src/apps/relay/dbdrivers/dbd_pgsql.c
Normal file
668
src/apps/relay/dbdrivers/dbd_pgsql.c
Normal file
@ -0,0 +1,668 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011, 2012, 2013 Citrix Systems
|
||||||
|
* Copyright (C) 2014 Vivocha S.p.A.
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the project nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../mainrelay.h"
|
||||||
|
#include "dbd_pgsql.h"
|
||||||
|
|
||||||
|
#if !defined(TURN_NO_PQ)
|
||||||
|
#include <libpq-fe.h>
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static int donot_print_connection_success = 0;
|
||||||
|
|
||||||
|
static PGconn *get_pqdb_connection(void) {
|
||||||
|
persistent_users_db_t *pud = get_persistent_users_db();
|
||||||
|
|
||||||
|
PGconn *pqdbconnection = (PGconn*)(pud->connection);
|
||||||
|
if(pqdbconnection) {
|
||||||
|
ConnStatusType status = PQstatus(pqdbconnection);
|
||||||
|
if(status != CONNECTION_OK) {
|
||||||
|
PQfinish(pqdbconnection);
|
||||||
|
pqdbconnection = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!pqdbconnection) {
|
||||||
|
char *errmsg=NULL;
|
||||||
|
PQconninfoOption *co = PQconninfoParse(pud->userdb, &errmsg);
|
||||||
|
if(!co) {
|
||||||
|
if(errmsg) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection <%s>, connection string format error: %s\n",pud->userdb,errmsg);
|
||||||
|
turn_free(errmsg,strlen(errmsg)+1);
|
||||||
|
} else {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, unknown connection string format error\n",pud->userdb);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PQconninfoFree(co);
|
||||||
|
if(errmsg)
|
||||||
|
turn_free(errmsg,strlen(errmsg)+1);
|
||||||
|
pqdbconnection = PQconnectdb(pud->userdb);
|
||||||
|
if(!pqdbconnection) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, runtime error\n",pud->userdb);
|
||||||
|
} else {
|
||||||
|
ConnStatusType status = PQstatus(pqdbconnection);
|
||||||
|
if(status != CONNECTION_OK) {
|
||||||
|
PQfinish(pqdbconnection);
|
||||||
|
pqdbconnection = NULL;
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, runtime error\n",pud->userdb);
|
||||||
|
} else if(!donot_print_connection_success){
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "PostgreSQL DB connection success: %s\n",pud->userdb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pud->connection = pqdbconnection;
|
||||||
|
}
|
||||||
|
return pqdbconnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static int pgsql_get_auth_secrets(secrets_list_t *sl, u08bits *realm) {
|
||||||
|
int ret = 1;
|
||||||
|
PGconn * pqc = get_pqdb_connection();
|
||||||
|
if(pqc) {
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
snprintf(statement,sizeof(statement)-1,"select value from turn_secret where realm='%s'",realm);
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
|
||||||
|
if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
|
||||||
|
} else {
|
||||||
|
int i = 0;
|
||||||
|
for(i=0;i<PQntuples(res);i++) {
|
||||||
|
char *kval = PQgetvalue(res,i,0);
|
||||||
|
if(kval) {
|
||||||
|
add_to_secrets_list(sl,kval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(res) {
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pgsql_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) {
|
||||||
|
int ret = 1;
|
||||||
|
PGconn * pqc = get_pqdb_connection();
|
||||||
|
if(pqc) {
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
snprintf(statement,sizeof(statement),"select hmackey from turnusers_lt where name='%s' and realm='%s'",usname,realm);
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
|
||||||
|
if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK) || (PQntuples(res)!=1)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
|
||||||
|
} else {
|
||||||
|
char *kval = PQgetvalue(res,0,0);
|
||||||
|
int len = PQgetlength(res,0,0);
|
||||||
|
if(kval) {
|
||||||
|
size_t sz = get_hmackey_size(turn_params.shatype);
|
||||||
|
if(((size_t)len<sz*2)||(strlen(kval)<sz*2)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key format: %s, user %s\n",kval,usname);
|
||||||
|
} else if(convert_string_key_to_binary(kval, key, sz)<0) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key: %s, user %s\n",kval,usname);
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong hmackey data for user %s: NULL\n",usname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(res)
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pgsql_get_user_pwd(u08bits *usname, st_password_t pwd) {
|
||||||
|
int ret = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
snprintf(statement,sizeof(statement),"select password from turnusers_st where name='%s'",usname);
|
||||||
|
|
||||||
|
PGconn * pqc = get_pqdb_connection();
|
||||||
|
if(pqc) {
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
|
||||||
|
if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK) || (PQntuples(res)!=1)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
|
||||||
|
} else {
|
||||||
|
char *kval = PQgetvalue(res,0,0);
|
||||||
|
if(kval) {
|
||||||
|
strncpy((char*)pwd,kval,sizeof(st_password_t));
|
||||||
|
ret = 0;
|
||||||
|
} else {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong password data for user %s: NULL\n",usname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(res) {
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pgsql_set_user_key(u08bits *usname, u08bits *realm, const char *key) {
|
||||||
|
int ret = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
PGconn *pqc = get_pqdb_connection();
|
||||||
|
if(pqc) {
|
||||||
|
snprintf(statement,sizeof(statement),"insert into turnusers_lt (realm,name,hmackey) values('%s','%s','%s')",realm,usname,key);
|
||||||
|
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
|
||||||
|
if(res) {
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
snprintf(statement,sizeof(statement),"update turnusers_lt set hmackey='%s' where name='%s' and realm='%s'",key,usname,realm);
|
||||||
|
res = PQexec(pqc, statement);
|
||||||
|
if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating user information: %s\n",PQerrorMessage(pqc));
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(res) {
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pgsql_set_user_pwd(u08bits *usname, st_password_t pwd) {
|
||||||
|
int ret = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
PGconn *pqc = get_pqdb_connection();
|
||||||
|
if(pqc) {
|
||||||
|
snprintf(statement,sizeof(statement),"insert into turnusers_st values('%s','%s')",usname,pwd);
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
|
||||||
|
if(res) {
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
snprintf(statement,sizeof(statement),"update turnusers_st set password='%s' where name='%s'",pwd,usname);
|
||||||
|
res = PQexec(pqc, statement);
|
||||||
|
if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating user information: %s\n",PQerrorMessage(pqc));
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(res) {
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pgsql_del_user(u08bits *usname, int is_st, u08bits *realm) {
|
||||||
|
int ret = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
PGconn *pqc = get_pqdb_connection();
|
||||||
|
if(pqc) {
|
||||||
|
if(is_st) {
|
||||||
|
snprintf(statement,sizeof(statement),"delete from turnusers_st where name='%s'",usname);
|
||||||
|
} else {
|
||||||
|
snprintf(statement,sizeof(statement),"delete from turnusers_lt where name='%s' and realm='%s'",usname,realm);
|
||||||
|
}
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
if(res) {
|
||||||
|
PQclear(res);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pgsql_list_users(int is_st, u08bits *realm) {
|
||||||
|
int ret = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
PGconn *pqc = get_pqdb_connection();
|
||||||
|
if(pqc) {
|
||||||
|
if(is_st) {
|
||||||
|
snprintf(statement,sizeof(statement),"select name from turnusers_st order by name");
|
||||||
|
} else if(realm && realm[0]) {
|
||||||
|
snprintf(statement,sizeof(statement),"select name from turnusers_lt where realm='%s' order by name",realm);
|
||||||
|
} else {
|
||||||
|
snprintf(statement,sizeof(statement),"select name from turnusers_lt order by name");
|
||||||
|
}
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
|
||||||
|
} else {
|
||||||
|
int i = 0;
|
||||||
|
for(i=0;i<PQntuples(res);i++) {
|
||||||
|
char *kval = PQgetvalue(res,i,0);
|
||||||
|
if(kval) {
|
||||||
|
printf("%s\n",kval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
if(res) {
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pgsql_show_secret(u08bits *realm) {
|
||||||
|
int ret = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
snprintf(statement,sizeof(statement)-1,"select value from turn_secret where realm='%s'",realm);
|
||||||
|
|
||||||
|
donot_print_connection_success=1;
|
||||||
|
|
||||||
|
PGconn *pqc = get_pqdb_connection();
|
||||||
|
if(pqc) {
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
|
||||||
|
} else {
|
||||||
|
int i = 0;
|
||||||
|
for(i=0;i<PQntuples(res);i++) {
|
||||||
|
char *kval = PQgetvalue(res,i,0);
|
||||||
|
if(kval) {
|
||||||
|
printf("%s\n",kval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
if(res) {
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pgsql_del_secret(u08bits *secret, u08bits *realm) {
|
||||||
|
int ret = 1;
|
||||||
|
donot_print_connection_success=1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
PGconn *pqc = get_pqdb_connection();
|
||||||
|
if (pqc) {
|
||||||
|
if(!secret || (secret[0]==0))
|
||||||
|
snprintf(statement,sizeof(statement),"delete from turn_secret where realm='%s'",realm);
|
||||||
|
else
|
||||||
|
snprintf(statement,sizeof(statement),"delete from turn_secret where value='%s' and realm='%s'",secret,realm);
|
||||||
|
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
if (res) {
|
||||||
|
PQclear(res);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pgsql_set_secret(u08bits *secret, u08bits *realm) {
|
||||||
|
int ret = 1;
|
||||||
|
donot_print_connection_success = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
PGconn *pqc = get_pqdb_connection();
|
||||||
|
if (pqc) {
|
||||||
|
snprintf(statement,sizeof(statement),"insert into turn_secret (realm,value) values('%s','%s')",realm,secret);
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
if (!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
|
||||||
|
TURN_LOG_FUNC(
|
||||||
|
TURN_LOG_LEVEL_ERROR,
|
||||||
|
"Error inserting/updating secret key information: %s\n",
|
||||||
|
PQerrorMessage(pqc));
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
if (res) {
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pgsql_add_origin(u08bits *origin, u08bits *realm) {
|
||||||
|
int ret = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
PGconn *pqc = get_pqdb_connection();
|
||||||
|
if(pqc) {
|
||||||
|
snprintf(statement,sizeof(statement),"insert into turn_origin_to_realm (origin,realm) values('%s','%s')",origin,realm);
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting origin information: %s\n",PQerrorMessage(pqc));
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
if(res) {
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pgsql_del_origin(u08bits *origin) {
|
||||||
|
int ret = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
PGconn *pqc = get_pqdb_connection();
|
||||||
|
if(pqc) {
|
||||||
|
snprintf(statement,sizeof(statement),"delete from turn_origin_to_realm where origin='%s'",origin);
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting origin information: %s\n",PQerrorMessage(pqc));
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
if(res) {
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pgsql_list_origins(u08bits *realm) {
|
||||||
|
int ret = 1;
|
||||||
|
donot_print_connection_success = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
PGconn *pqc = get_pqdb_connection();
|
||||||
|
if(pqc) {
|
||||||
|
if(realm && realm[0]) {
|
||||||
|
snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm where realm='%s' order by origin",realm);
|
||||||
|
} else {
|
||||||
|
snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm order by origin,realm");
|
||||||
|
}
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
|
||||||
|
} else {
|
||||||
|
int i = 0;
|
||||||
|
for(i=0;i<PQntuples(res);i++) {
|
||||||
|
char *oval = PQgetvalue(res,i,0);
|
||||||
|
if(oval) {
|
||||||
|
char *rval = PQgetvalue(res,i,1);
|
||||||
|
if(rval) {
|
||||||
|
printf("%s ==>> %s\n",oval,rval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
if(res) {
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pgsql_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) {
|
||||||
|
int ret = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
PGconn *pqc = get_pqdb_connection();
|
||||||
|
if(pqc) {
|
||||||
|
{
|
||||||
|
snprintf(statement,sizeof(statement),"delete from turn_realm_option where realm='%s' and opt='%s'",realm,opt);
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
if(res) {
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(value>0) {
|
||||||
|
snprintf(statement,sizeof(statement),"insert into turn_realm_option (realm,opt,value) values('%s','%s','%lu')",realm,opt,(unsigned long)value);
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting realm option information: %s\n",PQerrorMessage(pqc));
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
if(res) {
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pgsql_list_realm_options(u08bits *realm) {
|
||||||
|
int ret = 1;
|
||||||
|
donot_print_connection_success = 1;
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
PGconn *pqc = get_pqdb_connection();
|
||||||
|
if(pqc) {
|
||||||
|
if(realm && realm[0]) {
|
||||||
|
snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option where realm='%s' order by realm,opt",realm);
|
||||||
|
} else {
|
||||||
|
snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option order by realm,opt");
|
||||||
|
}
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
|
||||||
|
} else {
|
||||||
|
int i = 0;
|
||||||
|
for(i=0;i<PQntuples(res);i++) {
|
||||||
|
char *rval = PQgetvalue(res,i,0);
|
||||||
|
if(rval) {
|
||||||
|
char *oval = PQgetvalue(res,i,1);
|
||||||
|
if(oval) {
|
||||||
|
char *vval = PQgetvalue(res,i,2);
|
||||||
|
if(vval) {
|
||||||
|
printf("%s[%s]=%s\n",oval,rval,vval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
if(res) {
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pgsql_auth_ping(void * rch) {
|
||||||
|
UNUSED_ARG(rch);
|
||||||
|
donot_print_connection_success = 1;
|
||||||
|
PGconn * pqc = get_pqdb_connection();
|
||||||
|
if(pqc) {
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
STRCPY(statement,"select value from turn_secret");
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
|
||||||
|
if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(res) {
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pgsql_get_ip_list(const char *kind, ip_range_list_t * list) {
|
||||||
|
int ret = 1;
|
||||||
|
PGconn * pqc = get_pqdb_connection();
|
||||||
|
if(pqc) {
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
snprintf(statement,sizeof(statement),"select ip_range from %s_peer_ip",kind);
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
|
||||||
|
if(res && (PQresultStatus(res) == PGRES_TUPLES_OK)) {
|
||||||
|
int i = 0;
|
||||||
|
for(i=0;i<PQntuples(res);i++) {
|
||||||
|
char *kval = PQgetvalue(res,i,0);
|
||||||
|
if(kval) {
|
||||||
|
add_ip_list_range(kval,list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(res) {
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pgsql_reread_realms(secrets_list_t * realms_list) {
|
||||||
|
PGconn * pqc = get_pqdb_connection();
|
||||||
|
if(pqc) {
|
||||||
|
char statement[TURN_LONG_STRING_SIZE];
|
||||||
|
|
||||||
|
{
|
||||||
|
snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm");
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
|
||||||
|
if(res && (PQresultStatus(res) == PGRES_TUPLES_OK)) {
|
||||||
|
|
||||||
|
ur_string_map *o_to_realm_new = ur_string_map_create(free);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for(i=0;i<PQntuples(res);i++) {
|
||||||
|
char *oval = PQgetvalue(res,i,0);
|
||||||
|
if(oval) {
|
||||||
|
char *rval = PQgetvalue(res,i,1);
|
||||||
|
if(rval) {
|
||||||
|
get_realm(rval);
|
||||||
|
ur_string_map_value_type value = strdup(rval);
|
||||||
|
ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) oval, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update_o_to_realm(o_to_realm_new);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(res) {
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
size_t rlsz = 0;
|
||||||
|
|
||||||
|
lock_realms();
|
||||||
|
rlsz = realms_list->sz;
|
||||||
|
unlock_realms();
|
||||||
|
|
||||||
|
for (i = 0; i<rlsz; ++i) {
|
||||||
|
|
||||||
|
char *realm = realms_list->secrets[i];
|
||||||
|
|
||||||
|
realm_params_t* rp = get_realm(realm);
|
||||||
|
|
||||||
|
lock_realms();
|
||||||
|
rp->options.perf_options.max_bps = turn_params.max_bps;
|
||||||
|
unlock_realms();
|
||||||
|
|
||||||
|
lock_realms();
|
||||||
|
rp->options.perf_options.total_quota = turn_params.total_quota;
|
||||||
|
unlock_realms();
|
||||||
|
|
||||||
|
lock_realms();
|
||||||
|
rp->options.perf_options.user_quota = turn_params.user_quota;
|
||||||
|
unlock_realms();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option");
|
||||||
|
PGresult *res = PQexec(pqc, statement);
|
||||||
|
|
||||||
|
if(res && (PQresultStatus(res) == PGRES_TUPLES_OK)) {
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for(i=0;i<PQntuples(res);i++) {
|
||||||
|
char *rval = PQgetvalue(res,i,0);
|
||||||
|
char *oval = PQgetvalue(res,i,1);
|
||||||
|
char *vval = PQgetvalue(res,i,2);
|
||||||
|
if(rval && oval && vval) {
|
||||||
|
realm_params_t* rp = get_realm(rval);
|
||||||
|
if(!strcmp(oval,"max-bps"))
|
||||||
|
rp->options.perf_options.max_bps = (band_limit_t)atol(vval);
|
||||||
|
else if(!strcmp(oval,"total-quota"))
|
||||||
|
rp->options.perf_options.total_quota = (vint)atoi(vval);
|
||||||
|
else if(!strcmp(oval,"user-quota"))
|
||||||
|
rp->options.perf_options.user_quota = (vint)atoi(vval);
|
||||||
|
else {
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown realm option: %s\n", oval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(res) {
|
||||||
|
PQclear(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static turn_dbdriver_t driver = {
|
||||||
|
&pgsql_get_auth_secrets,
|
||||||
|
&pgsql_get_user_key,
|
||||||
|
&pgsql_get_user_pwd,
|
||||||
|
&pgsql_set_user_key,
|
||||||
|
&pgsql_set_user_pwd,
|
||||||
|
&pgsql_del_user,
|
||||||
|
&pgsql_list_users,
|
||||||
|
&pgsql_show_secret,
|
||||||
|
&pgsql_del_secret,
|
||||||
|
&pgsql_set_secret,
|
||||||
|
&pgsql_add_origin,
|
||||||
|
&pgsql_del_origin,
|
||||||
|
&pgsql_list_origins,
|
||||||
|
&pgsql_set_realm_option_one,
|
||||||
|
&pgsql_list_realm_options,
|
||||||
|
&pgsql_auth_ping,
|
||||||
|
&pgsql_get_ip_list,
|
||||||
|
&pgsql_reread_realms
|
||||||
|
};
|
||||||
|
|
||||||
|
turn_dbdriver_t * get_pgsql_dbdriver(void) {
|
||||||
|
return &driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
turn_dbdriver_t * get_pgsql_dbdriver(void) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
49
src/apps/relay/dbdrivers/dbd_pgsql.h
Normal file
49
src/apps/relay/dbdrivers/dbd_pgsql.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011, 2012, 2013 Citrix Systems
|
||||||
|
* Copyright (C) 2014 Vivocha S.p.A.
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the project nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DBD_POSTGRESQL__
|
||||||
|
#define __DBD_POSTGRESQL__
|
||||||
|
|
||||||
|
#include "dbdriver.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
turn_dbdriver_t * get_pgsql_dbdriver(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/// __DBD_POSTGRESQL__///
|
||||||
|
|
||||||
1150
src/apps/relay/dbdrivers/dbd_redis.c
Normal file
1150
src/apps/relay/dbdrivers/dbd_redis.c
Normal file
File diff suppressed because it is too large
Load Diff
49
src/apps/relay/dbdrivers/dbd_redis.h
Normal file
49
src/apps/relay/dbdrivers/dbd_redis.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011, 2012, 2013 Citrix Systems
|
||||||
|
* Copyright (C) 2014 Vivocha S.p.A.
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the project nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DBD_REDIS__
|
||||||
|
#define __DBD_REDIS__
|
||||||
|
|
||||||
|
#include "dbdriver.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
turn_dbdriver_t * get_redis_dbdriver(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/// __DBD_REDIS__///
|
||||||
|
|
||||||
90
src/apps/relay/dbdrivers/dbdriver.c
Normal file
90
src/apps/relay/dbdrivers/dbdriver.c
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011, 2012, 2013 Citrix Systems
|
||||||
|
* Copyright (C) 2014 Vivocha S.p.A.
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the project nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../mainrelay.h"
|
||||||
|
#include "dbdriver.h"
|
||||||
|
#include "dbd_pgsql.h"
|
||||||
|
#include "dbd_mysql.h"
|
||||||
|
#include "dbd_mongo.h"
|
||||||
|
#include "dbd_redis.h"
|
||||||
|
|
||||||
|
static turn_dbdriver_t * _driver;
|
||||||
|
|
||||||
|
int convert_string_key_to_binary(char* keysource, hmackey_t key, size_t sz) {
|
||||||
|
char is[3];
|
||||||
|
size_t i;
|
||||||
|
unsigned int v;
|
||||||
|
is[2]=0;
|
||||||
|
for(i=0;i<sz;i++) {
|
||||||
|
is[0]=keysource[i*2];
|
||||||
|
is[1]=keysource[i*2+1];
|
||||||
|
sscanf(is,"%02x",&v);
|
||||||
|
key[i]=(unsigned char)v;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
persistent_users_db_t * get_persistent_users_db(void) {
|
||||||
|
return &(turn_params.default_users_db.persistent_users_db);
|
||||||
|
}
|
||||||
|
|
||||||
|
turn_dbdriver_t * get_dbdriver() {
|
||||||
|
if (!_driver) {
|
||||||
|
switch(turn_params.default_users_db.userdb_type) {
|
||||||
|
#if !defined(TURN_NO_PQ)
|
||||||
|
case TURN_USERDB_TYPE_PQ:
|
||||||
|
_driver = get_pgsql_dbdriver();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if !defined(TURN_NO_MYSQL)
|
||||||
|
case TURN_USERDB_TYPE_MYSQL:
|
||||||
|
_driver = get_mysql_dbdriver();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if !defined(TURN_NO_MONGO)
|
||||||
|
case TURN_USERDB_TYPE_MONGO:
|
||||||
|
_driver = get_mongo_dbdriver();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if !defined(TURN_NO_HIREDIS)
|
||||||
|
case TURN_USERDB_TYPE_REDIS:
|
||||||
|
_driver = get_redis_dbdriver();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
78
src/apps/relay/dbdrivers/dbdriver.h
Normal file
78
src/apps/relay/dbdrivers/dbdriver.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011, 2012, 2013 Citrix Systems
|
||||||
|
* Copyright (C) 2014 Vivocha S.p.A.
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the project nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DBDRIVER__
|
||||||
|
#define __DBDRIVER__
|
||||||
|
|
||||||
|
#include "../userdb.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////
|
||||||
|
|
||||||
|
typedef struct _turn_dbdriver_t {
|
||||||
|
int (*get_auth_secrets)(secrets_list_t *sl, u08bits *realm);
|
||||||
|
int (*get_user_key)(u08bits *usname, u08bits *realm, hmackey_t key);
|
||||||
|
int (*get_user_pwd)(u08bits *usname, st_password_t pwd);
|
||||||
|
int (*set_user_key)(u08bits *usname, u08bits *realm, const char *key);
|
||||||
|
int (*set_user_pwd)(u08bits *usname, st_password_t pwd);
|
||||||
|
int (*del_user)(u08bits *usname, int is_st, u08bits *realm);
|
||||||
|
int (*list_users)(int is_st, u08bits *realm);
|
||||||
|
int (*show_secret)(u08bits *realm);
|
||||||
|
int (*del_secret)(u08bits *secret, u08bits *realm);
|
||||||
|
int (*set_secret)(u08bits *secret, u08bits *realm);
|
||||||
|
int (*add_origin)(u08bits *origin, u08bits *realm);
|
||||||
|
int (*del_origin)(u08bits *origin);
|
||||||
|
int (*list_origins)(u08bits *realm);
|
||||||
|
int (*set_realm_option_one)(u08bits *realm, unsigned long value, const char* opt);
|
||||||
|
int (*list_realm_options)(u08bits *realm);
|
||||||
|
void (*auth_ping)(void * rch);
|
||||||
|
int (*get_ip_list)(const char *kind, ip_range_list_t * list);
|
||||||
|
void (*reread_realms)(secrets_list_t * realms_list);
|
||||||
|
} turn_dbdriver_t;
|
||||||
|
|
||||||
|
/////////// USER DB CHECK //////////////////
|
||||||
|
|
||||||
|
int convert_string_key_to_binary(char* keysource, hmackey_t key, size_t sz);
|
||||||
|
persistent_users_db_t * get_persistent_users_db(void);
|
||||||
|
turn_dbdriver_t * get_dbdriver(void);
|
||||||
|
|
||||||
|
////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/// __DBDRIVER__///
|
||||||
|
|
||||||
@ -427,6 +427,11 @@ static char Usage[] = "Usage: turnserver [options]\n"
|
|||||||
" \"host=<ip-addr> dbname=<database-name> user=<database-user> \\\n password=<database-user-password> port=<db-port> connect_timeout=<seconds>\".\n"
|
" \"host=<ip-addr> dbname=<database-name> user=<database-user> \\\n password=<database-user-password> port=<db-port> connect_timeout=<seconds>\".\n"
|
||||||
" All parameters are optional.\n"
|
" All parameters are optional.\n"
|
||||||
#endif
|
#endif
|
||||||
|
#if !defined(TURN_NO_MONGO)
|
||||||
|
" -J, --mongo-userdb <connection-string> MongoDB connection string, if used (default - empty, no MongoDB used).\n"
|
||||||
|
" This database can be used for long-term and short-term credentials mechanisms,\n"
|
||||||
|
" and it can store the secret value(s) for secret-based timed authentication in TURN RESP API.\n"
|
||||||
|
#endif
|
||||||
#if !defined(TURN_NO_HIREDIS)
|
#if !defined(TURN_NO_HIREDIS)
|
||||||
" -N, --redis-userdb <connection-string> Redis user database connection string, if used (default - empty, no Redis DB used).\n"
|
" -N, --redis-userdb <connection-string> Redis user database connection string, if used (default - empty, no Redis DB used).\n"
|
||||||
" This database can be used for long-term and short-term credentials mechanisms,\n"
|
" This database can be used for long-term and short-term credentials mechanisms,\n"
|
||||||
@ -557,7 +562,7 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n"
|
|||||||
" -D, --delete-st delete a short-term mechanism user\n"
|
" -D, --delete-st delete a short-term mechanism user\n"
|
||||||
" -l, --list list all long-term mechanism users\n"
|
" -l, --list list all long-term mechanism users\n"
|
||||||
" -L, --list-st list all short-term mechanism users\n"
|
" -L, --list-st list all short-term mechanism users\n"
|
||||||
#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_HIREDIS)
|
#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_MONGO) || !defined(TURN_NO_HIREDIS)
|
||||||
" -s, --set-secret=<value> Add shared secret for TURN RESP API\n"
|
" -s, --set-secret=<value> Add shared secret for TURN RESP API\n"
|
||||||
" -S, --show-secret Show stored shared secrets for TURN REST API\n"
|
" -S, --show-secret Show stored shared secrets for TURN REST API\n"
|
||||||
" -X, --delete-secret=<value> Delete a shared secret\n"
|
" -X, --delete-secret=<value> Delete a shared secret\n"
|
||||||
@ -576,13 +581,16 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n"
|
|||||||
#if !defined(TURN_NO_MYSQL)
|
#if !defined(TURN_NO_MYSQL)
|
||||||
" -M, --mysql-userdb MySQL user database connection string, if MySQL DB is used.\n"
|
" -M, --mysql-userdb MySQL user database connection string, if MySQL DB is used.\n"
|
||||||
#endif
|
#endif
|
||||||
|
#if !defined(TURN_NO_MONGO)
|
||||||
|
" -J, --mongo-userdb MongoDB user database connection string, if MongoDB is used.\n"
|
||||||
|
#endif
|
||||||
#if !defined(TURN_NO_HIREDIS)
|
#if !defined(TURN_NO_HIREDIS)
|
||||||
" -N, --redis-userdb Redis user database connection string, if Redis DB is used.\n"
|
" -N, --redis-userdb Redis user database connection string, if Redis DB is used.\n"
|
||||||
#endif
|
#endif
|
||||||
" -u, --user Username\n"
|
" -u, --user Username\n"
|
||||||
" -r, --realm Realm for long-term mechanism only\n"
|
" -r, --realm Realm for long-term mechanism only\n"
|
||||||
" -p, --password Password\n"
|
" -p, --password Password\n"
|
||||||
#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_HIREDIS)
|
#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_MONGO) || !defined(TURN_NO_HIREDIS)
|
||||||
" -o, --origin Origin\n"
|
" -o, --origin Origin\n"
|
||||||
#endif
|
#endif
|
||||||
" -H, --sha256 Use SHA256 digest function to be used for the message integrity.\n"
|
" -H, --sha256 Use SHA256 digest function to be used for the message integrity.\n"
|
||||||
@ -595,9 +603,9 @@ static char AdminUsage[] = "Usage: turnadmin [command] [options]\n"
|
|||||||
" Setting to zero value means removal of the option.\n"
|
" Setting to zero value means removal of the option.\n"
|
||||||
" -h, --help Help\n";
|
" -h, --help Help\n";
|
||||||
|
|
||||||
#define OPTIONS "c:d:p:L:E:X:i:m:l:r:u:b:B:e:M:N:O:q:Q:s:C:vVofhznaAS"
|
#define OPTIONS "c:d:p:L:E:X:i:m:l:r:u:b:B:e:M:J:N:O:q:Q:s:C:vVofhznaAS"
|
||||||
|
|
||||||
#define ADMIN_OPTIONS "gGORIHlLkaADSdb:e:M:N:u:r:p:s:X:o:h"
|
#define ADMIN_OPTIONS "gGORIHlLkaADSdb:e:M:J:N:u:r:p:s:X:o:h"
|
||||||
|
|
||||||
enum EXTRA_OPTS {
|
enum EXTRA_OPTS {
|
||||||
NO_UDP_OPT=256,
|
NO_UDP_OPT=256,
|
||||||
@ -701,6 +709,9 @@ static const struct myoption long_options[] = {
|
|||||||
#if !defined(TURN_NO_MYSQL)
|
#if !defined(TURN_NO_MYSQL)
|
||||||
{ "mysql-userdb", required_argument, NULL, 'M' },
|
{ "mysql-userdb", required_argument, NULL, 'M' },
|
||||||
#endif
|
#endif
|
||||||
|
#if !defined(TURN_NO_MONGO)
|
||||||
|
{ "mongo-userdb", required_argument, NULL, 'J' },
|
||||||
|
#endif
|
||||||
#if !defined(TURN_NO_HIREDIS)
|
#if !defined(TURN_NO_HIREDIS)
|
||||||
{ "redis-userdb", required_argument, NULL, 'N' },
|
{ "redis-userdb", required_argument, NULL, 'N' },
|
||||||
{ "redis-statsdb", required_argument, NULL, 'O' },
|
{ "redis-statsdb", required_argument, NULL, 'O' },
|
||||||
@ -776,7 +787,7 @@ static const struct myoption admin_long_options[] = {
|
|||||||
{ "delete", no_argument, NULL, 'd' },
|
{ "delete", no_argument, NULL, 'd' },
|
||||||
{ "list", no_argument, NULL, 'l' },
|
{ "list", no_argument, NULL, 'l' },
|
||||||
{ "list-st", no_argument, NULL, 'L' },
|
{ "list-st", no_argument, NULL, 'L' },
|
||||||
#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_HIREDIS)
|
#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_MONGO) || !defined(TURN_NO_HIREDIS)
|
||||||
{ "set-secret", required_argument, NULL, 's' },
|
{ "set-secret", required_argument, NULL, 's' },
|
||||||
{ "show-secret", no_argument, NULL, 'S' },
|
{ "show-secret", no_argument, NULL, 'S' },
|
||||||
{ "delete-secret", required_argument, NULL, 'X' },
|
{ "delete-secret", required_argument, NULL, 'X' },
|
||||||
@ -792,6 +803,9 @@ static const struct myoption admin_long_options[] = {
|
|||||||
#if !defined(TURN_NO_MYSQL)
|
#if !defined(TURN_NO_MYSQL)
|
||||||
{ "mysql-userdb", required_argument, NULL, 'M' },
|
{ "mysql-userdb", required_argument, NULL, 'M' },
|
||||||
#endif
|
#endif
|
||||||
|
#if !defined(TURN_NO_MONGO)
|
||||||
|
{ "mongo-userdb", required_argument, NULL, 'J' },
|
||||||
|
#endif
|
||||||
#if !defined(TURN_NO_HIREDIS)
|
#if !defined(TURN_NO_HIREDIS)
|
||||||
{ "redis-userdb", required_argument, NULL, 'N' },
|
{ "redis-userdb", required_argument, NULL, 'N' },
|
||||||
#endif
|
#endif
|
||||||
@ -799,7 +813,7 @@ static const struct myoption admin_long_options[] = {
|
|||||||
{ "realm", required_argument, NULL, 'r' },
|
{ "realm", required_argument, NULL, 'r' },
|
||||||
{ "password", required_argument, NULL, 'p' },
|
{ "password", required_argument, NULL, 'p' },
|
||||||
{ "sha256", no_argument, NULL, 'H' },
|
{ "sha256", no_argument, NULL, 'H' },
|
||||||
#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_HIREDIS)
|
#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_MONGO) || !defined(TURN_NO_HIREDIS)
|
||||||
{ "add-origin", no_argument, NULL, 'O' },
|
{ "add-origin", no_argument, NULL, 'O' },
|
||||||
{ "del-origin", no_argument, NULL, 'R' },
|
{ "del-origin", no_argument, NULL, 'R' },
|
||||||
{ "list-origins", required_argument, NULL, 'I' },
|
{ "list-origins", required_argument, NULL, 'I' },
|
||||||
@ -1086,6 +1100,12 @@ static void set_option(int c, char *value)
|
|||||||
turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_MYSQL;
|
turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_MYSQL;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
#if !defined(TURN_NO_MONGO)
|
||||||
|
case 'J':
|
||||||
|
STRCPY(turn_params.default_users_db.persistent_users_db.userdb, value);
|
||||||
|
turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_MONGO;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
#if !defined(TURN_NO_HIREDIS)
|
#if !defined(TURN_NO_HIREDIS)
|
||||||
case 'N':
|
case 'N':
|
||||||
STRCPY(turn_params.default_users_db.persistent_users_db.userdb, value);
|
STRCPY(turn_params.default_users_db.persistent_users_db.userdb, value);
|
||||||
@ -1411,7 +1431,7 @@ static int adminmain(int argc, char **argv)
|
|||||||
ct = TA_LIST_USERS;
|
ct = TA_LIST_USERS;
|
||||||
is_st = 1;
|
is_st = 1;
|
||||||
break;
|
break;
|
||||||
#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_HIREDIS)
|
#if !defined(TURN_NO_PQ) || !defined(TURN_NO_MYSQL) || !defined(TURN_NO_MONGO) || !defined(TURN_NO_HIREDIS)
|
||||||
case 's':
|
case 's':
|
||||||
ct = TA_SET_SECRET;
|
ct = TA_SET_SECRET;
|
||||||
STRCPY(secret,optarg);
|
STRCPY(secret,optarg);
|
||||||
@ -1444,6 +1464,12 @@ static int adminmain(int argc, char **argv)
|
|||||||
turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_MYSQL;
|
turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_MYSQL;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
#if !defined(TURN_NO_MONGO)
|
||||||
|
case 'J':
|
||||||
|
STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg);
|
||||||
|
turn_params.default_users_db.userdb_type = TURN_USERDB_TYPE_MONGO;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
#if !defined(TURN_NO_HIREDIS)
|
#if !defined(TURN_NO_HIREDIS)
|
||||||
case 'N':
|
case 'N':
|
||||||
STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg);
|
STRCPY(turn_params.default_users_db.persistent_users_db.userdb,optarg);
|
||||||
@ -1558,6 +1584,12 @@ static void print_features(unsigned long mfn)
|
|||||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "MySQL is not supported\n");
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "MySQL is not supported\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(TURN_NO_MONGO)
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "MongoDB supported\n");
|
||||||
|
#else
|
||||||
|
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "MongoDB is not supported\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(OPENSSL_THREADS)
|
#if defined(OPENSSL_THREADS)
|
||||||
//TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL multithreading supported\n");
|
//TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "OpenSSL multithreading supported\n");
|
||||||
#else
|
#else
|
||||||
|
|||||||
@ -83,8 +83,6 @@
|
|||||||
|
|
||||||
#include "ns_ioalib_impl.h"
|
#include "ns_ioalib_impl.h"
|
||||||
|
|
||||||
#include "hiredis_libevent2.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -764,6 +764,11 @@ static void cli_print_configuration(struct cli_session* cs)
|
|||||||
cli_print_str(cs,"MySQL/MariaDB","DB type",0);
|
cli_print_str(cs,"MySQL/MariaDB","DB type",0);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
#if !defined(TURN_NO_MONGO)
|
||||||
|
case TURN_USERDB_TYPE_MONGO:
|
||||||
|
cli_print_str(cs,"MongoDB","DB type",0);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
#if !defined(TURN_NO_HIREDIS)
|
#if !defined(TURN_NO_HIREDIS)
|
||||||
case TURN_USERDB_TYPE_REDIS:
|
case TURN_USERDB_TYPE_REDIS:
|
||||||
cli_print_str(cs,"redis","DB type",0);
|
cli_print_str(cs,"redis","DB type",0);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -77,6 +77,10 @@ struct _realm_params_t {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void lock_realms(void);
|
||||||
|
void unlock_realms(void);
|
||||||
|
void update_o_to_realm(ur_string_map * o_to_realm_new);
|
||||||
|
|
||||||
//////////// USER DB //////////////////////////////
|
//////////// USER DB //////////////////////////////
|
||||||
|
|
||||||
struct auth_message {
|
struct auth_message {
|
||||||
@ -100,6 +104,9 @@ enum _TURN_USERDB_TYPE {
|
|||||||
#if !defined(TURN_NO_MYSQL)
|
#if !defined(TURN_NO_MYSQL)
|
||||||
,TURN_USERDB_TYPE_MYSQL
|
,TURN_USERDB_TYPE_MYSQL
|
||||||
#endif
|
#endif
|
||||||
|
#if !defined(TURN_NO_MONGO)
|
||||||
|
,TURN_USERDB_TYPE_MONGO
|
||||||
|
#endif
|
||||||
#if !defined(TURN_NO_HIREDIS)
|
#if !defined(TURN_NO_HIREDIS)
|
||||||
,TURN_USERDB_TYPE_REDIS
|
,TURN_USERDB_TYPE_REDIS
|
||||||
#endif
|
#endif
|
||||||
@ -194,7 +201,7 @@ void reread_realms(void);
|
|||||||
int add_user_account(char *user, int dynamic);
|
int add_user_account(char *user, int dynamic);
|
||||||
int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08bits *origin, TURNADMIN_COMMAND_TYPE ct, int is_st, perf_options_t* po);
|
int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08bits *origin, TURNADMIN_COMMAND_TYPE ct, int is_st, perf_options_t* po);
|
||||||
|
|
||||||
int add_ip_list_range(char* range, ip_range_list_t * list);
|
int add_ip_list_range(const char* range, ip_range_list_t * list);
|
||||||
|
|
||||||
///////////// Redis //////////////////////
|
///////////// Redis //////////////////////
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user