]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-11727: [mod_mariadb] Add MariaDB (MySQL) support
authorAndrey Volk <andywolk@gmail.com>
Wed, 12 Jun 2019 08:05:42 +0000 (12:05 +0400)
committerAndrey Volk <andywolk@gmail.com>
Tue, 23 Jul 2019 16:07:16 +0000 (20:07 +0400)
23 files changed:
Freeswitch.2017.sln
build/modules.conf.in
build/modules.conf.most
conf/rayo/autoload_configs/pre_load_modules.conf.xml
conf/rayo/autoload_configs/switch.conf.xml
conf/testing/autoload_configs/pre_load_modules.conf.xml
conf/testing/autoload_configs/switch.conf.xml
conf/vanilla/autoload_configs/pre_load_modules.conf.xml
conf/vanilla/autoload_configs/switch.conf.xml
configure.ac
debian/bootstrap.sh
debian/control-modules
freeswitch.spec
libs/.gitignore
src/mod/databases/mod_mariadb/Makefile.am [new file with mode: 0644]
src/mod/databases/mod_mariadb/mariadb_dsn.cpp [new file with mode: 0644]
src/mod/databases/mod_mariadb/mariadb_dsn.hpp [new file with mode: 0644]
src/mod/databases/mod_mariadb/mod_mariadb.2017.vcxproj [new file with mode: 0644]
src/mod/databases/mod_mariadb/mod_mariadb.c [new file with mode: 0644]
src/switch_core_sqldb.c
w32/Setup/Setup.2017.wixproj
w32/mariadb-connector-c-version.props [new file with mode: 0644]
w32/mariadb-connector-c.props [new file with mode: 0644]

index d649654ac52016324f82701671052c5aaa6f0ddb..537439a95d9dcbfbacac06d789d620242d2a2cda 100644 (file)
@@ -584,6 +584,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Databases", "Databases", "{
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_pgsql", "src\mod\databases\mod_pgsql\mod_pgsql.2017.vcxproj", "{1BA65811-5453-46F6-8190-9ECEEFEB7DF2}"\r
 EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_mariadb", "src\mod\databases\mod_mariadb\mod_mariadb.2017.vcxproj", "{0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC}"\r
+EndProject\r
 Global\r
        GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
                All|Win32 = All|Win32\r
@@ -2675,6 +2677,18 @@ Global
                {1BA65811-5453-46F6-8190-9ECEEFEB7DF2}.Release|Win32.Build.0 = Release|Win32\r
                {1BA65811-5453-46F6-8190-9ECEEFEB7DF2}.Release|x64.ActiveCfg = Release|x64\r
                {1BA65811-5453-46F6-8190-9ECEEFEB7DF2}.Release|x64.Build.0 = Release|x64\r
+               {0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC}.All|Win32.ActiveCfg = Release|Win32\r
+               {0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC}.All|Win32.Build.0 = Release|Win32\r
+               {0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC}.All|x64.ActiveCfg = Release|x64\r
+               {0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC}.All|x64.Build.0 = Release|x64\r
+               {0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC}.Debug|Win32.Build.0 = Debug|Win32\r
+               {0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC}.Debug|x64.ActiveCfg = Debug|x64\r
+               {0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC}.Debug|x64.Build.0 = Debug|x64\r
+               {0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC}.Release|Win32.ActiveCfg = Release|Win32\r
+               {0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC}.Release|Win32.Build.0 = Release|Win32\r
+               {0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC}.Release|x64.ActiveCfg = Release|x64\r
+               {0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC}.Release|x64.Build.0 = Release|x64\r
        EndGlobalSection\r
        GlobalSection(SolutionProperties) = preSolution\r
                HideSolutionNode = FALSE\r
@@ -2886,6 +2900,7 @@ Global
                {B19AE6FC-BFFF-428D-B483-3BBEAECCC618} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78}\r
                {BC1FD72E-1CD5-4525-A7F5-17C5740BFDED} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B}\r
                {1BA65811-5453-46F6-8190-9ECEEFEB7DF2} = {31C2761D-20E0-4BF8-98B9-E32F0D8DD6E1}\r
+               {0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC} = {31C2761D-20E0-4BF8-98B9-E32F0D8DD6E1}\r
        EndGlobalSection\r
        GlobalSection(ExtensibilityGlobals) = postSolution\r
                SolutionGuid = {09840DE7-9208-45AA-9667-1A71EE93BD1E}\r
index 6b26354d8f10dc603864241df5c6c7b47f235d08..8f2c2a6d24369b8c95d062d69223e7d0842218d9 100644 (file)
@@ -79,6 +79,7 @@ codecs/mod_opus
 #codecs/mod_silk
 #codecs/mod_siren
 #codecs/mod_theora
+#databases/mod_mariadb
 databases/mod_pgsql
 dialplans/mod_dialplan_asterisk
 #dialplans/mod_dialplan_directory
index c142b1a3d7bdf98b84d40726c608206718506f42..6f976dca38118326bad9593232498421f5e85846 100644 (file)
@@ -76,6 +76,7 @@ codecs/mod_sangoma_codec
 codecs/mod_silk
 codecs/mod_siren
 codecs/mod_theora
+#databases/mod_mariadb
 databases/mod_pgsql
 dialplans/mod_dialplan_asterisk
 dialplans/mod_dialplan_directory
index 659bf7b8d449ff1e6cad4de1b9b679c15156ded6..620a6c1cd93b51e9b0933d197c3eadb5d2a0138e 100644 (file)
@@ -1,6 +1,7 @@
 <configuration name="pre_load_modules.conf" description="Modules">\r
   <modules>\r
     <!-- Databases -->\r
+    <!-- <load module="mod_mariadb"/> -->\r
     <load module="mod_pgsql"/>\r
   </modules>\r
 </configuration>\r
index 7b26088a55d62e619904c2ada23c7ae585bd9192..d23d8322245f9a86d29010e59eef104fb2310102 100644 (file)
     -->
     <!-- <param name="core-db-dsn" value="pgsql://hostaddr=127.0.0.1 dbname=freeswitch user=freeswitch password='' options='-c client_min_messages=NOTICE' application_name='freeswitch'" /> -->
     <!-- <param name="core-db-dsn" value="postgresql://freeswitch:@127.0.0.1/freeswitch?options=-c%20client_min_messages%3DNOTICE&application_name=freeswitch" /> -->
+    <!-- <param name="core-db-dsn" value="mariadb://Server=localhost;Database=freeswitch;Uid=freeswitch;Pwd=pass;" /> -->
     <!-- <param name="core-db-dsn" value="dsn:username:password" /> -->
     <!-- 
         Allow to specify the sqlite db at a different location (In this example, move it to ramdrive for
index 659bf7b8d449ff1e6cad4de1b9b679c15156ded6..620a6c1cd93b51e9b0933d197c3eadb5d2a0138e 100644 (file)
@@ -1,6 +1,7 @@
 <configuration name="pre_load_modules.conf" description="Modules">\r
   <modules>\r
     <!-- Databases -->\r
+    <!-- <load module="mod_mariadb"/> -->\r
     <load module="mod_pgsql"/>\r
   </modules>\r
 </configuration>\r
index 36158810df84e5ee6ee2db322f9ba0b49b496da4..69783e62c5864691f49fb0028c4765c7ef49d22d 100644 (file)
     -->
     <!-- <param name="core-db-dsn" value="pgsql://hostaddr=127.0.0.1 dbname=freeswitch user=freeswitch password='' options='-c client_min_messages=NOTICE'" /> -->
     <!-- <param name="core-db-dsn" value="postgresql://freeswitch:@127.0.0.1/freeswitch?options=-c%20client_min_messages%3DNOTICE" /> -->
+    <!-- <param name="core-db-dsn" value="mariadb://Server=localhost;Database=freeswitch;Uid=freeswitch;Pwd=pass;" /> -->
     <!-- <param name="core-db-dsn" value="dsn:username:password" /> -->
     <!-- 
         Allow to specify the sqlite db at a different location (In this example, move it to ramdrive for
index 659bf7b8d449ff1e6cad4de1b9b679c15156ded6..620a6c1cd93b51e9b0933d197c3eadb5d2a0138e 100644 (file)
@@ -1,6 +1,7 @@
 <configuration name="pre_load_modules.conf" description="Modules">\r
   <modules>\r
     <!-- Databases -->\r
+    <!-- <load module="mod_mariadb"/> -->\r
     <load module="mod_pgsql"/>\r
   </modules>\r
 </configuration>\r
index 679862cc68ee66102426979c18740dbacb7f4617..5b3930e796578cf3a1cfaa74d3e0d56580075118 100644 (file)
     -->
     <!-- <param name="core-db-dsn" value="pgsql://hostaddr=127.0.0.1 dbname=freeswitch user=freeswitch password='' options='-c client_min_messages=NOTICE'" /> -->
     <!-- <param name="core-db-dsn" value="postgresql://freeswitch:@127.0.0.1/freeswitch?options=-c%20client_min_messages%3DNOTICE" /> -->
+    <!-- <param name="core-db-dsn" value="mariadb://Server=localhost;Database=freeswitch;Uid=freeswitch;Pwd=pass;" /> -->
     <!-- <param name="core-db-dsn" value="dsn:username:password" /> -->
     <!-- 
         Allow to specify the sqlite db at a different location (In this example, move it to ramdrive for
index 17dec43e16f114a79569a2e16c82f989b46a810f..5a2e3198f3cfeca99dcb2a4375863c7fb2466799 100644 (file)
@@ -705,6 +705,11 @@ AC_SUBST([POSTGRESQL_CFLAGS], [$POSTGRESQL_CFLAGS])
 AC_SUBST([POSTGRESQL_LDFLAGS], [$POSTGRESQL_LDFLAGS])
 AC_SUBST([POSTGRESQL_LIBDIR], [$POSTGRESQL_LIBDIR])
 
+
+PKG_CHECK_MODULES([MARIADB], [libmariadb >= 3.0.9],[
+  AM_CONDITIONAL([HAVE_MARIADB],[true])],[
+  AC_MSG_RESULT([no]); AM_CONDITIONAL([HAVE_MARIADB],[false])])
+
 AC_ARG_ENABLE(deprecated-core-db-events,
        [AS_HELP_STRING([--enable-deprecated-core-db-events], [Keep deprecated core db events])],,[enable_deprecated_core_db_events="no"])
 
@@ -1925,6 +1930,7 @@ AC_CONFIG_FILES([Makefile
                src/mod/codecs/mod_siren/Makefile
                src/mod/codecs/mod_skel_codec/Makefile
                src/mod/codecs/mod_theora/Makefile
+               src/mod/databases/mod_mariadb/Makefile
                src/mod/databases/mod_pgsql/Makefile
                src/mod/dialplans/mod_dialplan_asterisk/Makefile
                src/mod/dialplans/mod_dialplan_directory/Makefile
index 6dfaa2e019331a91db910cfe635f0f8b1bdf9c15..1ae65a89d00b6c6b1a2f07ba5d74a2a7d33eacc4 100755 (executable)
@@ -623,6 +623,7 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
  freeswitch-mod-memcache (= \${binary:Version}),
  freeswitch-mod-nibblebill (= \${binary:Version}),
  freeswitch-mod-oreka (= \${binary:Version}),
+ freeswitch-mod-mariadb (= \${binary:Version}),
  freeswitch-mod-pgsql (= \${binary:Version}),
  freeswitch-mod-png (= \${binary:Version}),
  freeswitch-mod-redis (= \${binary:Version}),
@@ -863,6 +864,7 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
  freeswitch-mod-memcache-dbg (= \${binary:Version}),
  freeswitch-mod-nibblebill-dbg (= \${binary:Version}),
  freeswitch-mod-oreka-dbg (= \${binary:Version}),
+ freeswitch-mod-mariadb-dbg (= \${binary:Version}),
  freeswitch-mod-pgsql-dbg (= \${binary:Version}),
  freeswitch-mod-png-dbg (= \${binary:Version}),
  freeswitch-mod-redis-dbg (= \${binary:Version}),
index 27b2322ceac3ed097b4eb3f63d5625d4c61f7b9e..dcf8f29a2198663846ea4fd1edfe17bcad169b9b 100644 (file)
@@ -393,6 +393,11 @@ Description: Adds mod_yuv
 
 ## mod/databases
 
+Module: databases/mod_mariadb
+Description: Adds mod_mariadb
+ Adds mod_mariadb.
+Build-Depends: libmariadb-dev
+
 Module: databases/mod_pgsql
 Description: Adds mod_pgsql
  Adds mod_pgsql.
index e371f472d0f06937fb4bc6b9d7cbb2402742ad26..bc94233a2427b769ef3a1a6a1741a4f5d7d57d69 100644 (file)
@@ -3,7 +3,7 @@
 # spec file for package freeswitch
 #
 # includes module(s): freeswitch-devel freeswitch-codec-passthru-amr freeswitch-codec-passthru-amrwb freeswitch-codec-passthru-g729 
-#                     freeswitch-codec-passthru-g7231 freeswitch-lua freeswitch-pgsql freeswitch-perl freeswitch-python freeswitch-v8 freeswitch-signalwire
+#                     freeswitch-codec-passthru-g7231 freeswitch-lua freeswitch-mariadb freeswitch-pgsql freeswitch-perl freeswitch-python freeswitch-v8 freeswitch-signalwire
 #                     freeswitch-lan-de freeswitch-lang-en freeswitch-lang-fr freeswitch-lang-hu freeswitch-lang-ru freeswitch-freetdm
 #                    and others
 #
@@ -842,6 +842,16 @@ Theora Video Codec support for FreeSWITCH open source telephony platform.
 #                              FreeSWITCH Database Modules
 ######################################################################################################################
 
+%package database-mariadb
+Summary:       MariaDB native support for FreeSWITCH
+Group:         System/Libraries
+Requires:      %{name} = %{version}-%{release}
+Requires:      mariadb-connector-c
+BuildRequires: mariadb-connector-c-devel
+
+%description database-mariadb
+MariaDB native support for FreeSWITCH.
+
 %package database-pgsql
 Summary:       PostgreSQL native support for FreeSWITCH
 Group:         System/Libraries
@@ -1534,7 +1544,7 @@ CODECS_MODULES+="codecs/mod_sangoma_codec"
 #                                      Database Modules
 #
 ######################################################################################################################
-DATABASES_MODULES="databases/mod_pgsql"
+DATABASES_MODULES="databases/mod_mariadb databases/mod_pgsql"
 
 ######################################################################################################################
 #
@@ -2290,6 +2300,9 @@ fi
 #
 ######################################################################################################################
 
+%files database-mariadb
+%{MODINSTDIR}/mod_mariadb.so*
+
 %files database-pgsql
 %{MODINSTDIR}/mod_pgsql.so*
 
index 10b50dda73d7b6bb4da2b1c32b5823119ec5129d..4410a4df8cfc3d628290fb30575b41d99c0f2695 100644 (file)
@@ -862,4 +862,5 @@ libks-*/
 libks*
 signalwire-client-c-*/
 signalwire-client-c-*
-
+mariadb-connector-c-*/
+mariadb-connector-c-*
diff --git a/src/mod/databases/mod_mariadb/Makefile.am b/src/mod/databases/mod_mariadb/Makefile.am
new file mode 100644 (file)
index 0000000..66dab08
--- /dev/null
@@ -0,0 +1,18 @@
+include $(top_srcdir)/build/modmake.rulesam
+MODNAME=mod_mariadb
+
+if HAVE_MARIADB
+
+mod_LTLIBRARIES = mod_mariadb.la
+mod_mariadb_la_SOURCES  = mariadb_dsn.cpp mod_mariadb.c
+mod_mariadb_la_CFLAGS   = $(AM_CFLAGS) $(MARIADB_CFLAGS)
+mod_mariadb_la_CXXFLAGS = -std=c++11 $(MARIADB_CFLAGS)
+mod_mariadb_la_LIBADD   = $(switch_builddir)/libfreeswitch.la $(MARIADB_LIBS)
+mod_mariadb_la_LDFLAGS  = -avoid-version -module -no-undefined -shared
+
+else
+install: error
+all: error
+error:
+       $(error You must install libmariadb-dev to build mod_mariadb. MariaDB supports non-blocking operations starting with version 5.5.21. libmariadb version should be >= 3.0.9 to support MySQL 8.0)
+endif
diff --git a/src/mod/databases/mod_mariadb/mariadb_dsn.cpp b/src/mod/databases/mod_mariadb/mariadb_dsn.cpp
new file mode 100644 (file)
index 0000000..eb7bfee
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+* mod_mariadb for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+* Copyright (C) 2019, Andrey Volk <andywolk@gmail.com>
+*
+* Version: MPL 1.1
+*
+* The contents of this file are subject to the Mozilla Public License Version
+* 1.1 (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+* for the specific language governing rights and limitations under the
+* License.
+*
+* The Original Code is ported from FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+*
+* The Initial Developer of the Original Code is
+* Anthony Minessale II <anthm@freeswitch.org>
+* Portions created by the Initial Developer are Copyright (C)
+* the Initial Developer. All Rights Reserved.
+*
+* Contributor(s):
+* Andrey Volk <andywolk@gmail.com>
+*
+* mariadb_dsn.cpp -- Connection string parser for MariaDB FreeSWITCH module
+*
+*/
+#include <switch.h>
+#include "mariadb_dsn.hpp"
+
+#include <string>
+#include <iterator>
+#include <vector>
+#include <unordered_map>
+#include <regex>
+#include <algorithm>
+#include <sstream>
+
+class mariadb_dsn {
+
+       std::string _host = "localhost";
+       std::string _user;
+       std::string _passwd;
+       std::string _db;
+       int _port = 3306;
+       std::string _unix_socket;
+       std::string _character_set;     
+       unsigned long _clientflag;
+
+public:        
+
+       template<typename Out>
+       void split(const std::string &s, char delim, Out result) {
+               std::stringstream ss(s);
+               std::string item;
+               while (std::getline(ss, item, delim)) {
+                       *(result++) = item;
+               }
+       }
+
+       std::vector<std::string> split(const std::string &s, char delim) {
+               std::vector<std::string> elems;
+               split(s, delim, std::back_inserter(elems));
+               return elems;
+       }
+
+       mariadb_dsn(MYSQL *mysql, const char *dsn, unsigned long clientflag)
+       {
+               _clientflag = clientflag;
+
+               if (dsn) {
+                       std::vector<std::string> params = split(std::string(dsn), ';');
+
+                       for (auto &param : params) {
+                               std::vector<std::string> pair = split(param, '=');
+                               if (pair.size() >= 2) {
+                                       std::string key = std::regex_replace(pair[0], std::regex("^ +| +$|( ) +"), "$1");
+                                       std::transform(key.begin(), key.end(), key.begin(), ::tolower);
+                                       std::string value = pair[1];
+
+                                       if ("server" == key || "host" == key) {
+                                               _host = value;
+                                       } else if ("uid" == key || "user" == key || "username" == key) {
+                                               _user = value;
+                                       } else if ("pwd" == key || "passwd" == key || "password" == key) {
+                                               _passwd = value;
+                                       } else if ("database" == key || "db" == key) {
+                                               _db = value;
+                                       } else if ("port" == key) {
+                                               _port = std::stoi(value);
+                                       } else if ("option" == key || "options" == key) {
+                                               unsigned long option;
+                                               std::stringstream(value) >> option;
+                                               _clientflag |= option;
+                                       } else if ("charset" == key) {
+                                               std::string charset = std::regex_replace(value, std::regex("^ +| +$|( ) +"), "$1");
+                                               int err = mysql_optionsv(mysql, MYSQL_SET_CHARSET_NAME, (void *)charset.c_str());
+                                               if (err) {
+                                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mysql_optionsv returned an error [MYSQL_SET_CHARSET_NAME=%s]: %s\n", charset.c_str(), mysql_error(mysql));
+                                               }
+                                       }
+                               }
+                       }
+
+               }
+       }
+
+       const char* host() const
+       {
+               return _host.c_str();
+       }
+
+       const char* user() const
+       {
+               return _user.c_str();
+       }
+
+       const char* passwd() const
+       {
+               return _passwd.c_str();
+       }
+
+       const char* db() const
+       {
+               return _db.c_str();
+       }
+
+       const int port() const
+       {
+               return _port;
+       }
+
+       const char* unix_socket() const
+       {
+               return ("" == _unix_socket) ? NULL : _unix_socket.c_str();
+       }
+
+       unsigned long clientflag()
+       {
+               return _clientflag;
+       }
+};
+
+MYSQL* STDCALL mysql_dsn_connect(MYSQL *mysql, const char *connection_string, unsigned long clientflag)
+{
+       mariadb_dsn dsn(mysql, connection_string, clientflag);
+       return mysql_real_connect(mysql, dsn.host(), dsn.user(), dsn.passwd(), dsn.db(), dsn.port(), dsn.unix_socket(), dsn.clientflag());
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
diff --git a/src/mod/databases/mod_mariadb/mariadb_dsn.hpp b/src/mod/databases/mod_mariadb/mariadb_dsn.hpp
new file mode 100644 (file)
index 0000000..a4b356f
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+* mod_mariadb for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+* Copyright (C) 2019, Andrey Volk <andywolk@gmail.com>
+*
+* Version: MPL 1.1
+*
+* The contents of this file are subject to the Mozilla Public License Version
+* 1.1 (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+* for the specific language governing rights and limitations under the
+* License.
+*
+* The Original Code is ported from FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+*
+* The Initial Developer of the Original Code is
+* Anthony Minessale II <anthm@freeswitch.org>
+* Portions created by the Initial Developer are Copyright (C)
+* the Initial Developer. All Rights Reserved.
+*
+* Contributor(s):
+* Andrey Volk <andywolk@gmail.com>
+*
+* mariadb_dsn.hpp -- Connection string parser header
+*
+*/
+
+#ifndef _MARIADB_DSN_H_
+#define _MARIADB_DSN_H_
+
+#include <mysql.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+MYSQL* STDCALL mysql_dsn_connect(MYSQL *mysql, const char *connection_string, unsigned long clientflag);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_MARIADB_DSN_H_
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
diff --git a/src/mod/databases/mod_mariadb/mod_mariadb.2017.vcxproj b/src/mod/databases/mod_mariadb/mod_mariadb.2017.vcxproj
new file mode 100644 (file)
index 0000000..9357c8e
--- /dev/null
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup Label="ProjectConfigurations">\r
+    <ProjectConfiguration Include="Debug|Win32">\r
+      <Configuration>Debug</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Debug|x64">\r
+      <Configuration>Debug</Configuration>\r
+      <Platform>x64</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Release|Win32">\r
+      <Configuration>Release</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Release|x64">\r
+      <Configuration>Release</Configuration>\r
+      <Platform>x64</Platform>\r
+    </ProjectConfiguration>\r
+  </ItemGroup>\r
+  <PropertyGroup Label="Globals">\r
+    <ProjectName>mod_mariadb</ProjectName>\r
+    <RootNamespace>mod_mariadb</RootNamespace>\r
+    <Keyword>Win32Proj</Keyword>\r
+    <ProjectGuid>{0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC}</ProjectGuid>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
+    <ConfigurationType>DynamicLibrary</ConfigurationType>\r
+    <CharacterSet>MultiByte</CharacterSet>\r
+    <PlatformToolset>v141</PlatformToolset>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
+    <ConfigurationType>DynamicLibrary</ConfigurationType>\r
+    <CharacterSet>MultiByte</CharacterSet>\r
+    <PlatformToolset>v141</PlatformToolset>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
+    <ConfigurationType>DynamicLibrary</ConfigurationType>\r
+    <CharacterSet>MultiByte</CharacterSet>\r
+    <PlatformToolset>v141</PlatformToolset>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
+    <ConfigurationType>DynamicLibrary</ConfigurationType>\r
+    <CharacterSet>MultiByte</CharacterSet>\r
+    <PlatformToolset>v141</PlatformToolset>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <Import Project="$(SolutionDir)w32/mariadb-connector-c.props" />\r
+  <ImportGroup Label="ExtensionSettings">\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="..\..\..\..\w32\module_release.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="..\..\..\..\w32\module_debug.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="..\..\..\..\w32\module_release.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="..\..\..\..\w32\module_debug.props" />\r
+  </ImportGroup>\r
+  <PropertyGroup Label="UserMacros" />\r
+  <PropertyGroup>\r
+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
+  </PropertyGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <ClCompile>\r
+      <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PrecompiledHeader>\r
+      </PrecompiledHeader>\r
+    </ClCompile>\r
+    <Link>\r
+      <AdditionalLibraryDirectories>;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
+      <GenerateDebugInformation>true</GenerateDebugInformation>\r
+      <DataExecutionPrevention>\r
+      </DataExecutionPrevention>\r
+    </Link>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
+    <Midl>\r
+      <TargetEnvironment>X64</TargetEnvironment>\r
+    </Midl>\r
+    <ClCompile>\r
+      <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PrecompiledHeader>\r
+      </PrecompiledHeader>\r
+    </ClCompile>\r
+    <Link>\r
+      <AdditionalLibraryDirectories>;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
+      <GenerateDebugInformation>true</GenerateDebugInformation>\r
+      <DataExecutionPrevention>\r
+      </DataExecutionPrevention>\r
+      <TargetMachine>MachineX64</TargetMachine>\r
+    </Link>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <ClCompile>\r
+      <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PrecompiledHeader>\r
+      </PrecompiledHeader>\r
+    </ClCompile>\r
+    <Link>\r
+      <AdditionalLibraryDirectories>;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
+      <DataExecutionPrevention>\r
+      </DataExecutionPrevention>\r
+    </Link>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
+    <Midl>\r
+      <TargetEnvironment>X64</TargetEnvironment>\r
+    </Midl>\r
+    <ClCompile>\r
+      <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PrecompiledHeader>\r
+      </PrecompiledHeader>\r
+    </ClCompile>\r
+    <Link>\r
+      <AdditionalLibraryDirectories>;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
+      <DataExecutionPrevention>\r
+      </DataExecutionPrevention>\r
+      <TargetMachine>MachineX64</TargetMachine>\r
+    </Link>\r
+  </ItemDefinitionGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="mariadb_dsn.cpp" />\r
+    <ClCompile Include="mod_mariadb.c" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="mariadb_dsn.hpp" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2017.vcxproj">\r
+      <Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>\r
+    </ProjectReference>\r
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <ImportGroup Label="ExtensionTargets">\r
+  </ImportGroup>\r
+</Project>
\ No newline at end of file
diff --git a/src/mod/databases/mod_mariadb/mod_mariadb.c b/src/mod/databases/mod_mariadb/mod_mariadb.c
new file mode 100644 (file)
index 0000000..e0eea5a
--- /dev/null
@@ -0,0 +1,1048 @@
+/*
+* mod_mariadb for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+* Copyright (C) 2019, Andrey Volk <andywolk@gmail.com>
+*
+* Version: MPL 1.1
+*
+* The contents of this file are subject to the Mozilla Public License Version
+* 1.1 (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+* for the specific language governing rights and limitations under the
+* License.
+*
+* The Original Code is ported from FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+*
+* The Initial Developer of the Original Code is
+* Anthony Minessale II <anthm@freeswitch.org>
+* Portions created by the Initial Developer are Copyright (C)
+* the Initial Developer. All Rights Reserved.
+*
+* Contributor(s):
+* Andrey Volk <andywolk@gmail.com>
+*
+* mod_mariadb.c -- MariaDB (MySQL) FreeSWITCH module
+*
+*/
+
+#include <switch.h>
+
+#ifndef _WIN32
+#include <poll.h>
+#else
+#include <winsock2.h>
+#endif
+
+#include <mysql.h>
+
+#include "mariadb_dsn.hpp"
+
+switch_loadable_module_interface_t *MODULE_INTERFACE;
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_mariadb_load);
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_mariadb_shutdown);
+SWITCH_MODULE_DEFINITION(mod_mariadb, mod_mariadb_load, mod_mariadb_shutdown, NULL);
+
+MYSQL *mariadb_dsn_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd,
+       const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag);
+void mariadb_dsn_close(MYSQL *mysql);
+int mariadb_db_set_connection(MYSQL *mysql, enum enum_server_command command, const char *arg,
+       size_t length, my_bool skipp_check, void *opt_arg);
+my_bool mariadb_db_dsn_reconnect(MYSQL *mysql);
+
+#define DEFAULT_MARIADB_RETRIES 120
+
+#ifndef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+typedef enum {
+       MARIADB_STATE_INIT,
+       MARIADB_STATE_DOWN,
+       MARIADB_STATE_CONNECTED,
+       MARIADB_STATE_ERROR
+} mariadb_state_t;
+
+struct mariadb_handle {
+       char *dsn;
+       char *sql;
+       MYSQL con;
+       my_socket sock;
+       mariadb_state_t state;
+       int affected_rows;
+       int num_retries;
+       switch_bool_t auto_commit;
+       switch_bool_t in_txn;
+       int stored_results;
+};
+
+typedef struct mariadb_handle mariadb_handle_t;
+
+struct mariadb_result {
+       MYSQL_RES *result;
+       char *err;
+       int rows;
+       int cols;
+};
+
+typedef struct mariadb_result mariadb_result_t;
+
+switch_status_t mariadb_handle_destroy(switch_database_interface_handle_t **dih);
+switch_status_t mariadb_flush(mariadb_handle_t *handle);
+static int db_is_up(mariadb_handle_t *handle);
+static char *mariadb_handle_get_error(mariadb_handle_t *handle);
+
+#define mariadb_handle_exec_base(handle, sql, err) mariadb_handle_exec_base_detailed(__FILE__, (char * )__SWITCH_FUNC__, __LINE__, handle, sql, err)
+#define mariadb_next_result(h, r) mariadb_next_result_timed(h, r, 10000)
+#define mariadb_finish_results(handle) mariadb_finish_results_real(__FILE__, (char * )__SWITCH_FUNC__, __LINE__, handle)
+
+static char *supported_prefixes[4] = { 0 };
+
+static int wait_for_mysql(mariadb_handle_t *handle, int status, int msec)
+{
+       int res = -1;
+#ifdef _WIN32
+       /*
+       On Windows, select() must be used due to a bug in WSAPoll()
+       which is supposed to be identical to BSD's poll(), but it is not,
+       "Windows 8 Bugs 309411 \96 WSAPoll does not report failed connections":
+       https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/18769abd-fca0-4d3c-9884-1a38ce27ae90/wsapoll-and-nonblocking-connects-to-nonexistent-ports?forum=wsk
+       */
+
+       fd_set rs, ws, es;
+       struct timeval tv, *timeout = NULL;
+
+       FD_ZERO(&rs);
+       FD_ZERO(&ws);
+       FD_ZERO(&es);
+
+       if (status & MYSQL_WAIT_READ) FD_SET(handle->sock, &rs);
+       if (status & MYSQL_WAIT_WRITE) FD_SET(handle->sock, &ws);
+       if (status & MYSQL_WAIT_EXCEPT) FD_SET(handle->sock, &es);
+
+       if (status & MYSQL_WAIT_TIMEOUT) {
+               tv.tv_sec = MIN(mysql_get_timeout_value(&handle->con), (unsigned int)msec * 1000);
+               tv.tv_usec = 0;
+               timeout = &tv;
+       }
+
+       res = select(1, &rs, &ws, &es, timeout);
+#else
+       struct pollfd pfd = { 0 };
+       int timeout = -1;
+
+       pfd.fd = handle->sock;
+       pfd.events |= (status & MYSQL_WAIT_READ ? POLLIN : 0);
+       pfd.events |= (status & MYSQL_WAIT_WRITE ? POLLOUT : 0);
+       pfd.events |= (status & MYSQL_WAIT_EXCEPT ? POLLPRI : 0);
+
+       if (status & MYSQL_WAIT_TIMEOUT) {
+               timeout = MIN(mysql_get_timeout_value(&handle->con), (unsigned int)msec * 1000);
+       }
+
+       do {
+               res = poll(&pfd, 1, timeout);
+       } while (res == -1 && errno == EINTR);
+#endif
+
+       if (res == 0) goto timeout;
+       else if (res < 0) goto error;
+
+       status = 0;
+
+#ifdef _WIN32
+       if (FD_ISSET(handle->sock, &rs)) status |= MYSQL_WAIT_READ;
+       if (FD_ISSET(handle->sock, &ws)) status |= MYSQL_WAIT_WRITE;
+       if (FD_ISSET(handle->sock, &es)) status |= MYSQL_WAIT_EXCEPT;
+#else
+       if (pfd.revents & POLLIN) status |= MYSQL_WAIT_READ;
+       if (pfd.revents & POLLOUT) status |= MYSQL_WAIT_WRITE;
+       if (pfd.revents & POLLPRI) status |= MYSQL_WAIT_EXCEPT;
+#endif
+
+       return status;
+
+error:
+       // en error
+timeout:
+       return MYSQL_WAIT_TIMEOUT;
+}
+
+
+static int db_is_up(mariadb_handle_t *handle)
+{
+       int ret = 0;
+       switch_event_t *event;
+       char *err_str = NULL;
+       int max_tries = DEFAULT_MARIADB_RETRIES;
+       int code = 0, recon = 0;
+
+       if (handle) {
+               max_tries = handle->num_retries;
+               if (max_tries < 1)
+                       max_tries = DEFAULT_MARIADB_RETRIES;
+       }
+
+top:
+
+       if (!handle) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No DB Handle\n");
+               goto done;
+       }
+
+       if (mysql_ping(&handle->con) != 0) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "mysql_ping returned bad connection [Error: %s]; reconnecting...\n", mysql_error(&handle->con));
+               handle->state = MARIADB_STATE_ERROR;
+               if (mariadb_reconnect(&handle->con) != 0) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "mariadb_reconnect returned bad connection -- reconnection failed! [Error: %s]\n", mysql_error(&handle->con));
+                       goto error;
+               }
+               handle->state = MARIADB_STATE_CONNECTED;
+               handle->sock = mysql_get_socket(&handle->con);
+       }
+
+       ret = 1;
+       goto done;
+
+error:
+       err_str = mariadb_handle_get_error(handle);
+
+       if (mysql_ping(&handle->con) != 0) {
+               handle->state = MARIADB_STATE_ERROR;
+               if (mariadb_reconnect(&handle->con) == 0) {
+                       handle->state = MARIADB_STATE_CONNECTED;
+                       recon = SWITCH_STATUS_SUCCESS;
+                       handle->sock = mysql_get_socket(&handle->con);
+               }
+       }
+
+       max_tries--;
+
+       if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) {
+               switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Failure-Message", "The sql server is not responding for DSN %s [%s][%d]",
+                       switch_str_nil(handle->dsn), switch_str_nil(err_str), code);
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The sql server is not responding for DSN %s [%s][%d]\n",
+                       switch_str_nil(handle->dsn), switch_str_nil(err_str), code);
+
+               if (recon == SWITCH_STATUS_SUCCESS) {
+                       switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "The connection has been re-established");
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "The connection has been re-established\n");
+               } else {
+                       switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "The connection could not be re-established");
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The connection could not be re-established\n");
+               }
+               if (!max_tries) {
+                       switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "Giving up!");
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Giving up!\n");
+               }
+
+               switch_event_fire(&event);
+       }
+
+       if (!max_tries) {
+               goto done;
+       }
+
+       switch_safe_free(err_str);
+       switch_yield(1000000);
+       goto top;
+
+done:
+
+       switch_safe_free(err_str);
+
+       return ret;
+}
+
+switch_status_t mariadb_SQLEndTran(mariadb_handle_t *handle, switch_bool_t commit)
+{
+       char * err_str = NULL;
+
+       if (!handle)
+               return SWITCH_STATUS_FALSE;
+
+       if (commit) {
+               char *sql = "COMMIT";
+               handle->stored_results = 0;
+               if (mysql_query(&handle->con, sql)) {
+                       err_str = mariadb_handle_get_error(handle);
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not commit transaction: %s\n", err_str);
+                       switch_safe_free(err_str);
+                       return SWITCH_STATUS_FALSE;
+               }
+       } else {
+               char *sql = "ROLLBACK";
+               handle->stored_results = 0;
+               if (mysql_query(&handle->con, sql)) {
+                       err_str = mariadb_handle_get_error(handle);
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not rollback transaction: %s\n", err_str);
+                       switch_safe_free(err_str);
+                       return SWITCH_STATUS_FALSE;
+               }
+       }
+       handle->in_txn = SWITCH_FALSE;
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t mariadb_next_result_timed(mariadb_handle_t *handle, mariadb_result_t **result_out, int msec)
+{
+       int status = 0;
+       mariadb_result_t *res;
+       switch_time_t start;
+       switch_time_t ctime;
+       unsigned int usec = msec * 1000;
+       char *err_str;
+
+       if (!handle) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "**BUG** Null handle passed to mariadb_next_result.\n");
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if (handle->stored_results)     {
+               if ( (status = mysql_next_result(&handle->con)) ) {
+                       if (status > 0) {
+                               err_str = mariadb_handle_get_error(handle);
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "An error occurred trying to get next for query (%s): %s\n", handle->sql, err_str);
+                               switch_safe_free(err_str);
+
+                               goto error;
+                       }
+
+                       return SWITCH_STATUS_SUCCESS;
+               }
+       }
+
+       if (!(res = malloc(sizeof(mariadb_result_t)))) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Malloc failed!\n");
+               goto error;
+       }
+
+       memset(res, 0, sizeof(mariadb_result_t));
+
+       if ( (status = mysql_store_result_start(&res->result, &handle->con)) ) {
+               /* Wait for a result to become available, up to msec milliseconds */
+               start = switch_micro_time_now();
+               while ((ctime = switch_micro_time_now()) - start <= usec) {
+                       int wait_time = (usec - (unsigned int)(ctime - start)) / 1000;
+
+                       /* Wait for the mariadb socket to be ready for data reads. */
+                       status = wait_for_mysql(handle, status, wait_time);
+                       status = mysql_store_result_cont(&res->result, &handle->con, status);
+
+                       if (!status)
+                               break;
+               }
+       }
+
+       /* At this point, we know we can read a full result without blocking. */
+
+       if (res->result) {
+               *result_out = res;
+
+               res->rows = (int)mysql_num_rows(res->result);
+               handle->affected_rows = res->rows;
+               handle->stored_results++;
+               res->cols = mysql_num_fields(res->result);              
+       } else {
+               if (mysql_field_count(&handle->con) != 0) {
+                       // mysql_store_result_() should have returned data
+
+                       err_str = mariadb_handle_get_error(handle);
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "An error occurred trying to use result for query (%s): %s\n", handle->sql, err_str);
+                       switch_safe_free(err_str);
+               }
+
+               free(res);
+               res = NULL;
+               *result_out = NULL;
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+
+error:
+
+       /* Make sure the failed connection does not have any transactions marked as in progress */
+       mariadb_flush(handle);
+
+       /* Try to reconnect to the DB if we were dropped */
+       db_is_up(handle);
+
+       return SWITCH_STATUS_FALSE;
+}
+
+void mariadb_free_result(mariadb_result_t **result)
+{
+       if (!*result) {
+               return;
+       }
+
+       if ((*result)->result) {
+               mysql_free_result((*result)->result);
+       }
+
+       free(*result);
+       *result = NULL;
+}
+
+switch_status_t mariadb_finish_results_real(const char* file, const char* func, int line, mariadb_handle_t *handle)
+{
+       char *err_str;
+       mariadb_result_t *res = NULL;
+       switch_status_t final_status = SWITCH_STATUS_SUCCESS;
+       int done = 0, status;
+
+       do {
+               mariadb_next_result(handle, &res);
+               if (res && res->err && !switch_stristr("already exists", res->err) && !switch_stristr("duplicate key name", res->err)) {
+                       switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "Error executing query:\n%s\n", res->err);
+                       final_status = SWITCH_STATUS_FALSE;
+               }
+
+               if (!res) {
+                       if (!mysql_more_results(&handle->con)) {
+                               done = 1;
+                       } else {
+                               if ((status = mysql_next_result(&handle->con))) {
+                                       if (status > 0) {
+                                               err_str = mariadb_handle_get_error(handle);
+                                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "An error occurred trying to get next for query (%s): %s\n", handle->sql, err_str);
+                                               switch_safe_free(err_str);
+
+                                               break;
+                                       }
+                               }
+                       }
+               } else if (res->result) {
+                       handle->affected_rows = (int)mysql_affected_rows(&handle->con);
+               }
+
+               mariadb_free_result(&res);
+       } while (!done);
+
+       return final_status;
+}
+
+switch_status_t mariadb_handle_disconnect(mariadb_handle_t *handle)
+{
+       if (!handle) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if (handle->state == MARIADB_STATE_CONNECTED) {
+               mysql_close(&handle->con);
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Disconnected from [%s]\n", handle->dsn);
+       }
+       switch_safe_free(handle->sql);
+       handle->state = MARIADB_STATE_DOWN;
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+static char * mariadb_handle_get_error(mariadb_handle_t *handle)
+{
+       char *err_str = NULL;
+
+       if (!handle) {
+               return NULL;
+       }
+
+       switch_strdup(err_str, mysql_error(&handle->con));
+
+       return err_str;
+}
+
+switch_status_t mariadb_handle_connect(mariadb_handle_t *handle)
+{
+       if (!handle) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if (handle->state == MARIADB_STATE_CONNECTED) {
+               mariadb_handle_disconnect(handle);
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Re-connecting %s\n", handle->dsn);
+       }
+
+       if (handle->state == MARIADB_STATE_CONNECTED) {
+               mariadb_handle_disconnect(handle);
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Re-connecting %s\n", handle->dsn);
+       }
+
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Connecting %s\n", handle->dsn);
+       mysql_init(&handle->con);
+
+       // Enable non-blocking operation
+       // https://mariadb.com/kb/en/library/using-the-non-blocking-library/
+       mysql_options(&handle->con, MYSQL_OPT_NONBLOCK, 0);
+
+       /* set timeouts to 300 microseconds */
+       /*int default_timeout = 3;
+       mysql_options(&handle->con, MYSQL_OPT_READ_TIMEOUT, &default_timeout);
+       mysql_options(&handle->con, MYSQL_OPT_CONNECT_TIMEOUT, &default_timeout);
+       mysql_options(&handle->con, MYSQL_OPT_WRITE_TIMEOUT, &default_timeout);*/
+
+       if (!mysql_dsn_connect(&handle->con, handle->dsn, CLIENT_MULTI_STATEMENTS)) {
+               char *err_str;
+               if ((err_str = mariadb_handle_get_error(handle))) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", err_str);
+                       switch_safe_free(err_str);
+               } else {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to connect to the database [%s]\n", handle->dsn);
+                       mariadb_handle_disconnect(handle);
+               }
+               return SWITCH_STATUS_FALSE;
+       }
+
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Connected to [%s]\n", handle->dsn);
+       handle->state = MARIADB_STATE_CONNECTED;
+       handle->sock = mysql_get_socket(&handle->con);
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t mariadb_handle_new(switch_cache_db_database_interface_options_t database_interface_options, switch_database_interface_handle_t **dih)
+{
+       mariadb_handle_t *new_handle = NULL;
+
+       if (!(*dih = malloc(sizeof(**dih)))) {
+               goto err;
+       }
+
+       if (!(new_handle = malloc(sizeof(*new_handle)))) {
+               goto err;
+       }
+
+       memset(new_handle, 0, sizeof(*new_handle));
+
+       if (!(new_handle->dsn = strdup(database_interface_options.connection_string))) {
+               goto err;
+       }
+
+       new_handle->sock = 0;
+       new_handle->state = MARIADB_STATE_INIT; 
+       new_handle->affected_rows = 0;
+       new_handle->num_retries = DEFAULT_MARIADB_RETRIES;
+       new_handle->auto_commit = SWITCH_TRUE;
+       new_handle->in_txn = SWITCH_FALSE;
+       new_handle->stored_results = 0;
+
+       (*dih)->handle = new_handle;
+
+       if (mariadb_handle_connect(new_handle) != SWITCH_STATUS_SUCCESS) {
+               if (mariadb_handle_destroy(dih) != SWITCH_STATUS_SUCCESS) {
+                       goto err;
+               }
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+
+err:
+       switch_safe_free(*dih);
+
+       if (new_handle) {
+               switch_safe_free(new_handle->dsn);
+               switch_safe_free(new_handle);
+       }
+
+       return SWITCH_STATUS_FALSE;
+}
+
+switch_status_t mariadb_handle_destroy(switch_database_interface_handle_t **dih)
+{
+       mariadb_handle_t *handle = NULL;
+
+       if (!dih) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       handle = (*dih)->handle;
+
+       if (handle) {
+               mariadb_handle_disconnect(handle);
+
+               switch_safe_free(handle->dsn);
+               free(handle);
+       }
+
+       switch_safe_free(*dih);
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t database_flush(switch_database_interface_handle_t *dih)
+{
+       mariadb_handle_t *handle;
+
+       if (!dih) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       handle = dih->handle;
+
+       return mariadb_flush(handle);
+}
+
+switch_status_t mariadb_flush(mariadb_handle_t *handle)
+{
+       MYSQL_RES *tmp = NULL;
+       int x = 0;
+
+       if (!handle) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if (handle->stored_results) {
+               if (mysql_next_result(&handle->con) != 0) {
+                       goto done;
+               }
+       }
+
+       /* Make sure the query is fully cleared */
+       while ((tmp = mysql_store_result(&handle->con)) != NULL) {
+               mysql_free_result(tmp);
+               x++;
+
+               if (mysql_next_result(&handle->con) != 0)
+                       break;
+       }
+
+       if (x) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Flushing %d results\n", x);
+       }
+
+done:
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t mariadb_send_query(mariadb_handle_t *handle, const char* sql)
+{
+       char *err_str;
+       int ret;
+
+       switch_safe_free(handle->sql);
+       handle->sql = strdup(sql);
+       handle->stored_results = 0;
+       ret = mysql_real_query(&handle->con, sql, (unsigned long)strlen(sql));  
+       if (ret) {
+               err_str = mariadb_handle_get_error(handle);
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to send query (%s) to database: %s\n", sql, err_str);
+               switch_safe_free(err_str);
+               mariadb_finish_results(handle);
+               goto error;
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+
+error:
+       return SWITCH_STATUS_FALSE;
+}
+
+switch_status_t mariadb_handle_exec_base_detailed(const char *file, const char *func, int line,
+       mariadb_handle_t *handle, const char *sql, char **err)
+{
+       char *err_str = NULL, *er = NULL;
+
+       mariadb_flush(handle);
+       handle->affected_rows = 0;
+
+       if (!db_is_up(handle)) {
+               er = strdup("Database is not up!");
+               goto error;
+       }
+
+       if (handle->auto_commit == SWITCH_FALSE && handle->in_txn == SWITCH_FALSE) {
+               if (mariadb_send_query(handle, "BEGIN") != SWITCH_STATUS_SUCCESS) {
+                       er = strdup("Error sending BEGIN!");
+                       if (mariadb_finish_results(handle) != SWITCH_STATUS_SUCCESS) {
+                               db_is_up(handle); /* If finish_results failed, maybe the db went dead */
+                       }
+                       goto error;
+               }
+
+               if (mariadb_finish_results(handle) != SWITCH_STATUS_SUCCESS) {
+                       db_is_up(handle);
+                       er = strdup("Error sending BEGIN!");
+                       goto error;
+               }
+               handle->in_txn = SWITCH_TRUE;
+       }
+
+       if (mariadb_send_query(handle, sql) != SWITCH_STATUS_SUCCESS) {
+               er = strdup("Error sending query!");
+               if (mariadb_finish_results(handle) != SWITCH_STATUS_SUCCESS) {
+                       db_is_up(handle);
+               }
+               goto error;
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+
+error:
+       err_str = mariadb_handle_get_error(handle);
+
+       if (zstr(err_str)) {
+               if (zstr(er)) {
+                       err_str = strdup((char *)"SQL ERROR!");
+               } else {
+                       err_str = er;
+               }
+       } else {
+               if (!zstr(er)) {
+                       free(er);
+               }
+       }
+
+       if (err_str) {
+               if (!switch_stristr("already exists", err_str) && !switch_stristr("duplicate key name", err_str)) {
+                       switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str));
+               }
+
+               if (err) {
+                       *err = err_str;
+               } else {
+                       free(err_str);
+               }
+       }
+
+       return SWITCH_STATUS_FALSE;
+}
+
+switch_status_t mariadb_handle_exec_detailed(const char *file, const char *func, int line,
+       mariadb_handle_t *handle, const char *sql, char **err)
+{
+       if (mariadb_handle_exec_base_detailed(file, func, line, handle, sql, err) == SWITCH_STATUS_FALSE) {
+               goto error;
+       }
+
+       return mariadb_finish_results(handle);
+
+error:
+       return SWITCH_STATUS_FALSE;
+}
+
+switch_status_t database_handle_exec_detailed(const char *file, const char *func, int line, 
+       switch_database_interface_handle_t *dih, const char *sql, char **err)
+{
+       mariadb_handle_t *handle;
+
+       if (!dih) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       handle = dih->handle;
+
+       return mariadb_handle_exec_detailed(file, func, line, handle, sql, err);
+}
+
+switch_status_t database_handle_exec_string(switch_database_interface_handle_t *dih, const char *sql, char *resbuf, size_t len, char **err)
+{
+       mariadb_handle_t *handle;
+       switch_status_t sstatus = SWITCH_STATUS_SUCCESS;
+       mariadb_result_t *result = NULL;
+       MYSQL_ROW row;
+
+       if (!dih) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       handle = dih->handle;
+
+       if (!handle)
+               return SWITCH_STATUS_FALSE;
+
+       handle->affected_rows = 0;
+
+       if (mariadb_handle_exec_base(handle, sql, err) == SWITCH_STATUS_FALSE) {
+               goto error;
+       }
+
+       if (mariadb_next_result(handle, &result) == SWITCH_STATUS_FALSE) {
+               goto error;
+       }
+
+       if (!result) {
+               sstatus = SWITCH_STATUS_FALSE;
+               goto done;
+       }
+
+       if (!result->result) {
+               sstatus = SWITCH_STATUS_FALSE;
+               goto done;
+       }
+
+       if (handle->affected_rows <= 0) {
+               goto done;
+       }
+
+       row = mysql_fetch_row(result->result);
+       if (row) {
+               strncpy(resbuf, row[0], len);
+       } else {
+               resbuf[0] = '\0';
+       }
+
+done:
+
+       mariadb_free_result(&result);
+       if (mariadb_finish_results(handle) != SWITCH_STATUS_SUCCESS) {
+               sstatus = SWITCH_STATUS_FALSE;
+       }
+
+       return sstatus;
+
+error:
+       return SWITCH_STATUS_FALSE;
+}
+
+switch_status_t database_SQLSetAutoCommitAttr(switch_database_interface_handle_t *dih, switch_bool_t on)
+{
+       mariadb_handle_t *handle;
+
+       if (!dih) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       handle = dih->handle;
+
+       if (!handle)
+               return SWITCH_STATUS_FALSE;
+
+       if (on) {
+               handle->auto_commit = SWITCH_TRUE;
+       } else {
+               handle->auto_commit = SWITCH_FALSE;
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t mariadb_handle_affected_rows(switch_database_interface_handle_t *dih, int *affected_rows)
+{
+       mariadb_handle_t *handle = NULL;
+
+       if (!dih) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       handle = dih->handle;
+
+       if (!handle)
+               return SWITCH_STATUS_FALSE;
+
+       *affected_rows = handle->affected_rows;
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t database_commit(switch_database_interface_handle_t *dih)
+{
+       switch_status_t result;
+
+       mariadb_handle_t *handle;
+
+       if (!dih) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       handle = dih->handle;
+
+       if (!handle)
+               return SWITCH_STATUS_FALSE;
+
+       result = mariadb_SQLEndTran(handle, SWITCH_TRUE);
+       result = result && database_SQLSetAutoCommitAttr(dih, SWITCH_TRUE);
+       result = result && mariadb_finish_results(handle);
+
+       return result;
+}
+
+switch_status_t database_rollback(switch_database_interface_handle_t *dih)
+{
+       mariadb_handle_t *handle;
+
+       if (!dih) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       handle = dih->handle;
+
+       if (!handle) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       mariadb_SQLEndTran(handle, SWITCH_FALSE);
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t mariadb_handle_callback_exec_detailed(const char *file, const char *func, int line,
+       switch_database_interface_handle_t *dih, const char *sql, switch_core_db_callback_func_t callback, void *pdata, char **err)
+{
+       mariadb_handle_t *handle;
+       char *err_str = NULL;
+       int row = 0, col = 0, err_cnt = 0;
+       mariadb_result_t *result = NULL;
+
+       if (!dih) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       handle = dih->handle;
+
+       if (!handle) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       handle->affected_rows = 0;
+
+       switch_assert(callback != NULL);
+
+       if (mariadb_handle_exec_base(handle, sql, err) == SWITCH_STATUS_FALSE) {
+               goto error;
+       }
+
+       if (mariadb_next_result(handle, &result) == SWITCH_STATUS_FALSE) {
+               err_cnt++;
+               err_str = mariadb_handle_get_error(handle);
+               if (result && !zstr(result->err)) {
+                       switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(result->err));
+               }
+               if (!zstr(err_str)) {
+                       switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str));
+               }
+               switch_safe_free(err_str);
+               err_str = NULL;
+       }
+
+       while (result != NULL) {
+               for (row = 0; row < result->rows; ++row) {
+                       char **names;
+                       char **vals;
+                       MYSQL_ROW data_row;
+
+                       names = calloc(result->cols, sizeof(*names));
+                       vals = calloc(result->cols, sizeof(*vals));
+
+                       switch_assert(names && vals);
+
+                       data_row = mysql_fetch_row(result->result);
+
+                       for (col = 0; col < result->cols; ++col) {
+                               unsigned long *lengths;
+                               MYSQL_FIELD *field = mysql_fetch_field_direct(result->result, col);
+                               if (field) {
+                                       names[col] = malloc(field->name_length +1);
+                                       names[col][field->name_length] = '\0';
+                                       strncpy(names[col], field->name, field->name_length);
+                                                                               
+                                       lengths = mysql_fetch_lengths(result->result);
+                                       vals[col] = malloc(lengths[col] + 1);
+                                       vals[col][lengths[col]] = '\0';
+
+                                       if (data_row) {
+                                               strncpy(vals[col], data_row[col], lengths[col]);
+                                       } else {
+                                               vals[col][0] = '\0';
+                                       }
+                               } else {
+                                       switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: Column number %d out of range\n", col);
+                               }
+                       }
+
+                       if (callback(pdata, result->cols, vals, names)) {
+                               mariadb_finish_results(handle);
+                               row = result->rows;
+                       }
+
+                       for (col = 0; col < result->cols; ++col) {
+                               free(names[col]);
+                               free(vals[col]);
+                       }
+
+                       free(names);
+                       free(vals);
+               }
+
+               mariadb_free_result(&result);
+               if (mariadb_next_result(handle, &result) == SWITCH_STATUS_FALSE) {
+                       err_cnt++;
+                       err_str = mariadb_handle_get_error(handle);
+                       if (result && !zstr(result->err)) {
+                               switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(result->err));
+                       }
+                       if (!zstr(err_str)) {
+                               switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str));
+                       }
+                       switch_safe_free(err_str);
+                       err_str = NULL;
+               }
+       }
+       if (err_cnt) {
+               goto error;
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+
+error:
+       return SWITCH_STATUS_FALSE;
+}
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_mariadb_load)
+{
+       switch_database_interface_t *database_interface;
+
+       supported_prefixes[0] = (char *)"mariadb";
+       supported_prefixes[1] = (char *)"maria";
+       supported_prefixes[2] = (char *)"mysql";
+
+       /* connect my internal structure to the blank pointer passed to me */
+       *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+       MODULE_INTERFACE = *module_interface;
+
+       database_interface = (switch_database_interface_t *)switch_loadable_module_create_interface(*module_interface, SWITCH_DATABASE_INTERFACE);
+       database_interface->interface_name = modname;
+       /*
+               MariaDB and MySQL both have row size limits
+               https://mariadb.com/kb/en/library/innodb-limitations/#limitations-on-size
+               https://dev.mysql.com/doc/refman/8.0/en/column-count-limit.html
+
+               Setting database flag to SWITCH_DATABASE_FLAG_ROW_SIZE_LIMIT 
+               will allow FreeSWITCH Core to properly create wide tables such as the channel table 
+               which size exeeds the limit in the case of a multi-byte charset like utf8 (1-4 bytes per character).
+       */
+       database_interface->flags = SWITCH_DATABASE_FLAG_ROW_SIZE_LIMIT;
+       database_interface->prefixes = supported_prefixes;
+       database_interface->handle_new = mariadb_handle_new;
+       database_interface->handle_destroy = mariadb_handle_destroy;
+       database_interface->flush = database_flush;
+       database_interface->exec_detailed = database_handle_exec_detailed;
+       database_interface->exec_string = database_handle_exec_string;
+       database_interface->affected_rows = mariadb_handle_affected_rows;
+       database_interface->sql_set_auto_commit_attr = database_SQLSetAutoCommitAttr;
+       database_interface->commit = database_commit;
+       database_interface->rollback = database_rollback;
+       database_interface->callback_exec_detailed = mariadb_handle_callback_exec_detailed;
+       
+       /* indicate that the module should continue to be loaded */
+       return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_mariadb_shutdown)
+{
+       return SWITCH_STATUS_UNLOAD;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
index 71127a15c00197274efbba9df5df6897857e9e66..c642ab3aa26bfd93d467e470380ab8b451dec05b 100644 (file)
@@ -2929,7 +2929,7 @@ static char create_row_size_limited_channels_sql[] =
        "   ip_addr  VARCHAR(256),\n"
        "   dest  VARCHAR(1024),\n"
        "   application  VARCHAR(128),\n"
-       "   application_data  VARCHAR(4096),\n"
+       "   application_data TEXT,\n"
        "   dialplan VARCHAR(128),\n"
        "   context VARCHAR(128),\n"
        "   read_codec  VARCHAR(128),\n"
index 170a47cd8ca615b5842b9834087dd7206ab1f314..5f77b94298e2064bee12050a5e1bd45db9e8f905 100644 (file)
       <RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>\r
       <RefTargetDir>INSTALLFOLDER</RefTargetDir>\r
     </ProjectReference>\r
+    <ProjectReference Include="..\..\src\mod\databases\mod_mariadb\mod_mariadb.2017.vcxproj">\r
+      <Name>mod_mariadb</Name>\r
+      <Project>{0b612f84-7533-4dec-aedd-5c9cbcf15eac}</Project>\r
+      <Private>True</Private>\r
+      <DoNotHarvest>True</DoNotHarvest>\r
+      <RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>\r
+      <RefTargetDir>INSTALLFOLDER</RefTargetDir>\r
+    </ProjectReference>\r
     <ProjectReference Include="..\..\src\mod\databases\mod_pgsql\mod_pgsql.2017.vcxproj">\r
       <Name>mod_pgsql</Name>\r
       <Project>{1ba65811-5453-46f6-8190-9eceefeb7df2}</Project>\r
diff --git a/w32/mariadb-connector-c-version.props b/w32/mariadb-connector-c-version.props
new file mode 100644 (file)
index 0000000..e2cd36f
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ImportGroup Label="PropertySheets">
+    <Import Project="basedir.props" Condition=" '$(BaseDirImported)' == ''"/>
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros">
+    <mariadb-connector-cVersion>3.0.9</mariadb-connector-cVersion>
+  </PropertyGroup>
+  <PropertyGroup>
+    <mariadb-connector-cVersionImported>true</mariadb-connector-cVersionImported>
+  </PropertyGroup>
+  <PropertyGroup />
+  <ItemDefinitionGroup />
+  <ItemGroup>
+    <BuildMacro Include="mariadb-connector-cVersion">
+      <Value>$(mariadb-connector-cVersion)</Value>
+    </BuildMacro>
+  </ItemGroup>
+</Project>
diff --git a/w32/mariadb-connector-c.props b/w32/mariadb-connector-c.props
new file mode 100644 (file)
index 0000000..e9da703
--- /dev/null
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ImportGroup Label="PropertySheets">
+    <Import Project="mariadb-connector-c-version.props" Condition=" '$(mariadb-connector-cVersionImported)' == '' "/>
+    <Import Project="downloadpackage.task" Condition=" '$(downloadpackagetask_Imported)' == '' " />
+  </ImportGroup>
+
+  <PropertyGroup>
+    <mariadb-connector-cPropsImported>true</mariadb-connector-cPropsImported>
+  </PropertyGroup>
+
+  <PropertyGroup Label="UserMacros">
+    <mariadb-connector-clibDir>$(BaseDir)libs\mariadb-connector-c-$(mariadb-connector-cVersion)</mariadb-connector-clibDir>
+  </PropertyGroup>
+
+  <!-- 
+       Download Target.
+       Name must be unique. 
+       By design, targets are executed only once per project.
+       
+       Usage:
+       
+       package: URI
+
+       expectfileordirectory: Skips the download and extraction if exists
+
+       outputfolder: Folder to store a downloaded file. 
+                     By default "$(BaseDir)libs", if empty
+
+       outputfilename: If not empty, overrides filename from URI.
+                       .exe files don't get extracted
+
+       extractto: Folder to extract an archive to
+   -->
+
+  <Target Name="mariadb-connector-cBinariesDownloadTarget" BeforeTargets="CustomBuild" DependsOnTargets="7za">  
+      <DownloadPackageTask 
+           package="http://files.freeswitch.org/windows/packages/mariadb-connector-c/$(mariadb-connector-cVersion)/mariadb-connector-c-$(mariadb-connector-cVersion)-binaries-$(Platform.ToLower())-$(Configuration.ToLower()).zip"
+           expectfileordirectory="$(mariadb-connector-clibDir)\binaries\$(Platform)\$(Configuration)\libmariadb.dll" 
+           outputfolder=""
+           outputfilename="" 
+           extractto="$(BaseDir)libs\"
+      />
+  </Target> 
+  <Target Name="mariadb-connector-cHeadersDownloadTarget" BeforeTargets="CustomBuild" DependsOnTargets="7za">  
+      <DownloadPackageTask 
+           package="http://files.freeswitch.org/windows/packages/mariadb-connector-c/$(mariadb-connector-cVersion)/mariadb-connector-c-$(mariadb-connector-cVersion)-headers.zip"
+           expectfileordirectory="$(mariadb-connector-clibDir)\include\mysql.h" 
+           outputfolder=""
+           outputfilename="" 
+           extractto="$(BaseDir)libs\"
+      />
+  </Target> 
+
+  <Target Name="mariadb-connector-ccopyTarget" AfterTargets="Build" DependsOnTargets="Build">  
+      <ItemGroup>  
+          <mariadb-connector-cFiles Include="$(mariadb-connector-clibDir)\binaries\$(Platform)\$(Configuration)\*.dll"/>  
+          <libmariadb-plugins Include="$(mariadb-connector-clibDir)\binaries\$(Platform)\$(Configuration)\plugin\*.*" />
+      </ItemGroup>  
+      <Copy Condition="!exists('$(BaseDir)\$(Platform)\$(Configuration)\libmariadb.dll')"
+          SourceFiles="@(mariadb-connector-cFiles)"  
+          DestinationFiles="@(mariadb-connector-cFiles->'$(BaseDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension)')"  
+      />  
+      <Copy Condition="!exists('$(BaseDir)\$(Platform)\$(Configuration)\plugin\caching_sha2_password.dll')"
+          SourceFiles="@(libmariadb-plugins)"
+          DestinationFolder="$(BaseDir)\$(Platform)\$(Configuration)\libmariadb_plugin\"
+      />
+  </Target>   
+
+
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <AdditionalIncludeDirectories>$(mariadb-connector-clibDir)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <AdditionalLibraryDirectories>$(mariadb-connector-clibDir)\binaries\$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalDependencies>libmariadb.lib;Secur32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+</Project>