mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-25 04:34:15 +00:00
Merge branch 'master' into modzmq
This commit is contained in:
commit
2b1793ed56
329 files changed
+119236
-8526
No files matched your search
@@ -0,0 +1,20 @@
|
||||
BASE=../../../..
|
||||
|
||||
LDNS=ldns
|
||||
|
||||
LDNS_DIR=$(switch_srcdir)/libs/$(LDNS)
|
||||
LDNS_BUILDDIR=$(switch_builddir)/libs/$(LDNS)
|
||||
LOCAL_CFLAGS=-I$(LDNS_DIR) -I$(LDNS_DIR)/include
|
||||
LDNS_LA=$(LDNS_BUILDDIR)/libldns.la
|
||||
LOCAL_LIBADD=$(LDNS_LA)
|
||||
include $(BASE)/build/modmake.rules
|
||||
|
||||
$(LDNS_BUILDDIR)/Makefile: $(LDNS_DIR)/Makefile.in
|
||||
mkdir -p $(LDNS_BUILDDIR)
|
||||
cd $(LDNS_BUILDDIR) && $(DEFAULT_VARS) $(LDNS_DIR)/configure $(DEFAULT_ARGS) --srcdir=$(LDNS_DIR) --disable-gost --without-ssl --disable-sha2
|
||||
$(TOUCH_TARGET)
|
||||
|
||||
$(LDNS_LA): $(LDNS_BUILDDIR)/Makefile
|
||||
cd $(LDNS_BUILDDIR) && $(MAKE)
|
||||
$(TOUCH_TARGET)
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
include $(top_srcdir)/build/modmake.rulesam
|
||||
MODNAME=mod_enum
|
||||
|
||||
UDNS_DIR=$(switch_srcdir)/libs/udns
|
||||
mod_enum_la_CFLAGS = -I$(UDNS_DIR) -DHAVE_POLL $(AM_CFLAGS)
|
||||
|
||||
mod_LTLIBRARIES = mod_enum.la
|
||||
mod_enum_la_SOURCES = mod_enum.c
|
||||
mod_enum_la_SOURCES += $(UDNS_DIR)/udns_dn.c $(UDNS_DIR)/udns_dntosp.c $(UDNS_DIR)/udns_parse.c $(UDNS_DIR)/udns_misc.c
|
||||
mod_enum_la_SOURCES += $(UDNS_DIR)/udns_rr_a.c $(UDNS_DIR)/udns_rr_ptr.c $(UDNS_DIR)/udns_rr_mx.c $(UDNS_DIR)/udns_rr_txt.c $(UDNS_DIR)/udns_bl.c
|
||||
mod_enum_la_SOURCES += $(UDNS_DIR)/udns_rr_srv.c $(UDNS_DIR)/udns_rr_naptr.c $(UDNS_DIR)/udns_codes.c $(UDNS_DIR)/udns_resolver.c
|
||||
mod_enum_la_LIBADD = $(switch_builddir)/libfreeswitch.la
|
||||
mod_enum_la_LDFLAGS = -avoid-version -module -no-undefined -shared
|
||||
@@ -0,0 +1,323 @@
|
||||
diff -ru b/ldns/ldns.h a/ldns/ldns.h
|
||||
--- b/ldns/ldns.h 2011-03-24 20:32:30.000000000 -0500
|
||||
+++ a/ldns/ldns.h 2011-03-24 20:29:03.000000000 -0500
|
||||
@@ -148,6 +148,16 @@
|
||||
/** EDNS flags */
|
||||
extern ldns_lookup_table ldns_edns_flags[];
|
||||
|
||||
+
|
||||
+#ifdef USE_WINSOCK
|
||||
+#define SOCK_INVALID INVALID_SOCKET
|
||||
+#define close_socket(_s) if (_s > SOCK_INVALID) {closesocket(_s); _s = SOCK_INVALID;}
|
||||
+#else
|
||||
+#define SOCK_INVALID -1
|
||||
+#define close_socket(_s) if (_s > SOCK_INVALID) {close(_s); _s = SOCK_INVALID;}
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
diff -ru b/net.c a/net.c
|
||||
--- b/net.c 2011-02-11 10:50:46.000000000 -0600
|
||||
+++ a/net.c 2011-03-24 20:28:15.000000000 -0500
|
||||
@@ -261,12 +261,18 @@
|
||||
#endif
|
||||
}
|
||||
|
||||
+#ifndef WIN32
|
||||
+#include <poll.h>
|
||||
+#endif
|
||||
+
|
||||
/** wait for a socket to become ready */
|
||||
static int
|
||||
ldns_sock_wait(int sockfd, struct timeval timeout, int write)
|
||||
{
|
||||
- fd_set fds;
|
||||
int ret;
|
||||
+
|
||||
+#ifdef WIN32
|
||||
+ fd_set fds;
|
||||
#ifndef S_SPLINT_S
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(FD_SET_T sockfd, &fds);
|
||||
@@ -275,6 +281,26 @@
|
||||
ret = select(sockfd+1, NULL, &fds, NULL, &timeout);
|
||||
else
|
||||
ret = select(sockfd+1, &fds, NULL, NULL, &timeout);
|
||||
+#else
|
||||
+
|
||||
+ struct pollfd pfds[2];
|
||||
+ int x = 0;
|
||||
+
|
||||
+ memset(&pfds[0], 0, sizeof(pfds[0]) * 2);
|
||||
+
|
||||
+ pfds[0].fd = sockfd;
|
||||
+ pfds[0].events = POLLIN|POLLERR;
|
||||
+
|
||||
+ if (write) {
|
||||
+ pfds[0].events |= POLLOUT;
|
||||
+ }
|
||||
+
|
||||
+ ret = poll(pfds, 1, timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
+
|
||||
if(ret == 0)
|
||||
/* timeout expired */
|
||||
return 0;
|
||||
@@ -299,11 +325,7 @@
|
||||
|
||||
/* wait for an response*/
|
||||
if(!ldns_sock_wait(sockfd, timeout, 0)) {
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(sockfd);
|
||||
-#else
|
||||
- closesocket(sockfd);
|
||||
-#endif
|
||||
+ close_socket(sockfd);
|
||||
return LDNS_STATUS_NETWORK_ERR;
|
||||
}
|
||||
|
||||
@@ -313,11 +335,7 @@
|
||||
ldns_sock_nonblock(sockfd);
|
||||
|
||||
answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL);
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(sockfd);
|
||||
-#else
|
||||
- closesocket(sockfd);
|
||||
-#endif
|
||||
+ close_socket(sockfd);
|
||||
|
||||
if (*answer_size == 0) {
|
||||
/* oops */
|
||||
@@ -353,9 +371,10 @@
|
||||
|
||||
if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_DGRAM,
|
||||
IPPROTO_UDP))
|
||||
- == -1) {
|
||||
+ == SOCK_INVALID) {
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
@@ -366,20 +385,20 @@
|
||||
int sockfd;
|
||||
|
||||
if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_STREAM,
|
||||
- IPPROTO_TCP)) == -1) {
|
||||
+ IPPROTO_TCP)) == SOCK_INVALID) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* perform nonblocking connect, to be able to wait with select() */
|
||||
ldns_sock_nonblock(sockfd);
|
||||
- if (connect(sockfd, (struct sockaddr*)to, tolen) == -1) {
|
||||
+ if (connect(sockfd, (struct sockaddr*)to, tolen) == SOCK_INVALID) {
|
||||
#ifndef USE_WINSOCK
|
||||
#ifdef EINPROGRESS
|
||||
if(errno != EINPROGRESS) {
|
||||
#else
|
||||
if(1) {
|
||||
#endif
|
||||
- close(sockfd);
|
||||
+ close_socket(sockfd);
|
||||
return 0;
|
||||
}
|
||||
#else /* USE_WINSOCK */
|
||||
@@ -398,11 +417,7 @@
|
||||
socklen_t len = (socklen_t)sizeof(error);
|
||||
|
||||
if(!ldns_sock_wait(sockfd, timeout, 1)) {
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(sockfd);
|
||||
-#else
|
||||
- closesocket(sockfd);
|
||||
-#endif
|
||||
+ close_socket(sockfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -421,7 +436,7 @@
|
||||
continue; /* try again */
|
||||
#endif
|
||||
else if(error != 0) {
|
||||
- close(sockfd);
|
||||
+ close_socket(sockfd);
|
||||
/* error in errno for our user */
|
||||
errno = error;
|
||||
return 0;
|
||||
@@ -645,11 +660,7 @@
|
||||
}
|
||||
|
||||
answer = ldns_tcp_read_wire_timeout(sockfd, answer_size, timeout);
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(sockfd);
|
||||
-#else
|
||||
- closesocket(sockfd);
|
||||
-#endif
|
||||
+ close_socket(sockfd);
|
||||
|
||||
if (*answer_size == 0) {
|
||||
/* oops */
|
||||
@@ -782,7 +793,7 @@
|
||||
* @hostname is used */
|
||||
for (ns_i = 0;
|
||||
ns_i < ldns_resolver_nameserver_count(resolver) &&
|
||||
- resolver->_socket == 0;
|
||||
+ resolver->_socket == SOCK_INVALID;
|
||||
ns_i++) {
|
||||
ns = ldns_rdf2native_sockaddr_storage(
|
||||
resolver->_nameservers[ns_i],
|
||||
@@ -792,7 +803,7 @@
|
||||
ldns_resolver_timeout(resolver));
|
||||
}
|
||||
|
||||
- if (resolver->_socket == 0) {
|
||||
+ if (resolver->_socket == SOCK_INVALID) {
|
||||
ldns_pkt_free(query);
|
||||
LDNS_FREE(ns);
|
||||
return LDNS_STATUS_NETWORK_ERR;
|
||||
@@ -807,13 +818,7 @@
|
||||
if (status != LDNS_STATUS_OK) {
|
||||
/* RoRi: to prevent problems on subsequent calls to ldns_axfr_start
|
||||
we have to close the socket here! */
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(resolver->_socket);
|
||||
-#else
|
||||
- closesocket(resolver->_socket);
|
||||
-#endif
|
||||
- resolver->_socket = 0;
|
||||
-
|
||||
+ close_socket(resolver->_socket);
|
||||
return LDNS_STATUS_CRYPTO_TSIG_ERR;
|
||||
}
|
||||
}
|
||||
@@ -826,12 +831,8 @@
|
||||
if(!query_wire) {
|
||||
ldns_pkt_free(query);
|
||||
LDNS_FREE(ns);
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(resolver->_socket);
|
||||
-#else
|
||||
- closesocket(resolver->_socket);
|
||||
-#endif
|
||||
- resolver->_socket = 0;
|
||||
+
|
||||
+ close_socket(resolver->_socket);
|
||||
|
||||
return LDNS_STATUS_MEM_ERR;
|
||||
}
|
||||
@@ -843,12 +844,8 @@
|
||||
|
||||
/* RoRi: to prevent problems on subsequent calls to ldns_axfr_start
|
||||
we have to close the socket here! */
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(resolver->_socket);
|
||||
-#else
|
||||
- closesocket(resolver->_socket);
|
||||
-#endif
|
||||
- resolver->_socket = 0;
|
||||
+
|
||||
+ close_socket(resolver->_socket);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -862,12 +859,8 @@
|
||||
/* RoRi: to prevent problems on subsequent calls to ldns_axfr_start
|
||||
we have to close the socket here! */
|
||||
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(resolver->_socket);
|
||||
-#else
|
||||
- closesocket(resolver->_socket);
|
||||
-#endif
|
||||
- resolver->_socket = 0;
|
||||
+
|
||||
+ close_socket(resolver->_socket);
|
||||
|
||||
return LDNS_STATUS_NETWORK_ERR;
|
||||
}
|
||||
diff -ru b/resolver.c a/resolver.c
|
||||
--- b/resolver.c 2010-12-14 08:41:38.000000000 -0600
|
||||
+++ a/resolver.c 2011-03-24 20:07:17.000000000 -0500
|
||||
@@ -627,9 +627,7 @@
|
||||
r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
|
||||
r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
|
||||
|
||||
- /* TODO: fd=0 is actually a valid socket (stdin),
|
||||
- replace with -1 */
|
||||
- r->_socket = 0;
|
||||
+ r->_socket = -1;
|
||||
r->_axfr_soa_count = 0;
|
||||
r->_axfr_i = 0;
|
||||
r->_cur_axfr_pkt = NULL;
|
||||
@@ -903,6 +901,8 @@
|
||||
size_t i;
|
||||
|
||||
if (res) {
|
||||
+ close_socket(res->_socket);
|
||||
+
|
||||
if (res->_searchlist) {
|
||||
for (i = 0; i < ldns_resolver_searchlist_count(res); i++) {
|
||||
ldns_rdf_deep_free(res->_searchlist[i]);
|
||||
@@ -1198,7 +1198,7 @@
|
||||
ldns_status status;
|
||||
|
||||
/* check if start() has been called */
|
||||
- if (!resolver || resolver->_socket == 0) {
|
||||
+ if (!resolver || resolver->_socket == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1215,12 +1215,9 @@
|
||||
if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
|
||||
resolver->_axfr_soa_count++;
|
||||
if (resolver->_axfr_soa_count >= 2) {
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(resolver->_socket);
|
||||
-#else
|
||||
- closesocket(resolver->_socket);
|
||||
-#endif
|
||||
- resolver->_socket = 0;
|
||||
+
|
||||
+ close_socket(resolver->_socket);
|
||||
+
|
||||
ldns_pkt_free(resolver->_cur_axfr_pkt);
|
||||
resolver->_cur_axfr_pkt = NULL;
|
||||
}
|
||||
@@ -1243,12 +1240,8 @@
|
||||
/* RoRi: we must now also close the socket, otherwise subsequent uses of the
|
||||
same resolver structure will fail because the link is still open or
|
||||
in an undefined state */
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(resolver->_socket);
|
||||
-#else
|
||||
- closesocket(resolver->_socket);
|
||||
-#endif
|
||||
- resolver->_socket = 0;
|
||||
+
|
||||
+ close_socket(resolver->_socket);
|
||||
|
||||
return NULL;
|
||||
} else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) {
|
||||
@@ -1258,12 +1251,8 @@
|
||||
/* RoRi: we must now also close the socket, otherwise subsequent uses of the
|
||||
same resolver structure will fail because the link is still open or
|
||||
in an undefined state */
|
||||
-#ifndef USE_WINSOCK
|
||||
- close(resolver->_socket);
|
||||
-#else
|
||||
- closesocket(resolver->_socket);
|
||||
-#endif
|
||||
- resolver->_socket = 0;
|
||||
+
|
||||
+ close_socket(resolver->_socket);
|
||||
|
||||
return NULL;
|
||||
} else {
|
||||
@@ -42,7 +42,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""$(InputDir)..\..\..\..\libs\udns""
|
||||
AdditionalIncludeDirectories=""$(InputDir)..\..\..\..\libs\ldns""
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
<Tool
|
||||
@@ -106,7 +106,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""$(InputDir)..\..\..\..\libs\udns""
|
||||
AdditionalIncludeDirectories=""$(InputDir)..\..\..\..\libs\ldns""
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
<Tool
|
||||
@@ -171,7 +171,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""$(InputDir)..\..\..\..\libs\udns""
|
||||
AdditionalIncludeDirectories=""$(InputDir)..\..\..\..\libs\ldns""
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
<Tool
|
||||
@@ -235,7 +235,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""$(InputDir)..\..\..\..\libs\udns""
|
||||
AdditionalIncludeDirectories=""$(InputDir)..\..\..\..\libs\ldns""
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
<Tool
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\udns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\ldns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
@@ -82,7 +82,7 @@
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\udns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\ldns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
@@ -96,7 +96,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\udns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\ldns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
@@ -112,7 +112,7 @@
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\udns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\ldns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
@@ -128,9 +128,8 @@
|
||||
<ClCompile Include="mod_enum.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\libs\win32\udns\libudns.2010.vcxproj">
|
||||
<Project>{4043fc6a-9a30-4577-8ad5-9b233c9575d8}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
<ProjectReference Include="..\..\..\..\libs\win32\ldns\ldns-lib\ldns-lib.2010.vcxproj">
|
||||
<Project>{23b4d303-79fc-49e0-89e2-2280e7e28940}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2010.vcxproj">
|
||||
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
|
||||
|
||||
@@ -30,11 +30,10 @@
|
||||
*/
|
||||
|
||||
#include <switch.h>
|
||||
#include <udns.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#define closesocket close
|
||||
#ifdef _MSC_VER
|
||||
#define ssize_t int
|
||||
#endif
|
||||
#include <ldns/ldns.h>
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_enum_load);
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_enum_shutdown);
|
||||
@@ -49,19 +48,10 @@ struct enum_record {
|
||||
char *route;
|
||||
int supported;
|
||||
struct enum_record *next;
|
||||
struct enum_record *tail;
|
||||
};
|
||||
typedef struct enum_record enum_record_t;
|
||||
|
||||
struct query {
|
||||
const char *name; /* original query string */
|
||||
char *number;
|
||||
unsigned char dn[DNS_MAXDN];
|
||||
enum dns_type qtyp; /* type of the query */
|
||||
enum_record_t *results;
|
||||
int errs;
|
||||
};
|
||||
typedef struct query enum_query_t;
|
||||
|
||||
struct route {
|
||||
char *service;
|
||||
char *regex;
|
||||
@@ -70,12 +60,11 @@ struct route {
|
||||
};
|
||||
typedef struct route enum_route_t;
|
||||
|
||||
static enum dns_class qcls = DNS_C_IN;
|
||||
|
||||
static switch_event_node_t *NODE = NULL;
|
||||
|
||||
static struct {
|
||||
char *root;
|
||||
char *server;
|
||||
char *isn_root;
|
||||
enum_route_t *route_order;
|
||||
switch_memory_pool_t *pool;
|
||||
@@ -84,6 +73,7 @@ static struct {
|
||||
} globals;
|
||||
|
||||
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_root, globals.root);
|
||||
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_server, globals.server);
|
||||
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_isn_root, globals.isn_root);
|
||||
|
||||
static void add_route(char *service, char *regex, char *replace)
|
||||
@@ -125,6 +115,8 @@ static switch_status_t load_config(void)
|
||||
const char *val = switch_xml_attr_soft(param, "value");
|
||||
if (!strcasecmp(var, "default-root")) {
|
||||
set_global_root(val);
|
||||
} else if (!strcasecmp(var, "use-server")) {
|
||||
set_global_server(val);
|
||||
} else if (!strcasecmp(var, "auto-reload")) {
|
||||
globals.auto_reload = switch_true(val);
|
||||
} else if (!strcasecmp(var, "query-timeout")) {
|
||||
@@ -152,6 +144,32 @@ static switch_status_t load_config(void)
|
||||
}
|
||||
|
||||
done:
|
||||
#ifdef _MSC_VER
|
||||
if (!globals.server) {
|
||||
HKEY hKey;
|
||||
DWORD data_sz;
|
||||
char* buf;
|
||||
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
|
||||
0, KEY_QUERY_VALUE, &hKey);
|
||||
|
||||
RegQueryValueEx(hKey, "DhcpNameServer", NULL, NULL, NULL, &data_sz);
|
||||
if (globals.server) {
|
||||
free(globals.server);
|
||||
}
|
||||
buf = (char*)malloc(data_sz + 1);
|
||||
|
||||
RegQueryValueEx(hKey, "DhcpNameServer", NULL, NULL, (LPBYTE)buf, &data_sz);
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
||||
if(buf[data_sz - 1] != 0) {
|
||||
buf[data_sz] = 0;
|
||||
}
|
||||
globals.server = buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (xml) {
|
||||
switch_xml_free(xml);
|
||||
@@ -168,11 +186,12 @@ static switch_status_t load_config(void)
|
||||
return status;
|
||||
}
|
||||
|
||||
static char *reverse_number(char *in, char *root)
|
||||
static char *reverse_number(const char *in, const char *root)
|
||||
{
|
||||
switch_size_t len;
|
||||
char *out = NULL;
|
||||
char *y, *z;
|
||||
const char *y;
|
||||
char *z;
|
||||
|
||||
if (!(in && root)) {
|
||||
return NULL;
|
||||
@@ -198,59 +217,33 @@ static char *reverse_number(char *in, char *root)
|
||||
return out;
|
||||
}
|
||||
|
||||
static void dnserror(enum_query_t *q, int errnum)
|
||||
{
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unable to lookup %s record for %s: %s\n",
|
||||
dns_typename(q->qtyp), dns_dntosp(q->dn), dns_strerror(errnum));
|
||||
q->errs++;
|
||||
}
|
||||
|
||||
static void add_result(enum_query_t *q, int order, int preference, char *service, char *route, int supported)
|
||||
static void add_result(enum_record_t **results, int order, int preference, char *service, char *route, int supported)
|
||||
{
|
||||
enum_record_t *new_result, *rp, *prev = NULL;
|
||||
enum_record_t *new_result;
|
||||
|
||||
new_result = malloc(sizeof(*new_result));
|
||||
switch_assert(new_result);
|
||||
memset(new_result, 0, sizeof(*new_result));
|
||||
|
||||
memset(new_result, 0, sizeof(*new_result));
|
||||
new_result->order = order;
|
||||
new_result->preference = preference;
|
||||
new_result->service = strdup(service);
|
||||
new_result->route = strdup(route);
|
||||
new_result->supported = supported;
|
||||
|
||||
|
||||
if (!q->results) {
|
||||
q->results = new_result;
|
||||
return;
|
||||
}
|
||||
|
||||
rp = q->results;
|
||||
|
||||
while (rp && strcasecmp(rp->service, new_result->service)) {
|
||||
prev = rp;
|
||||
rp = rp->next;
|
||||
}
|
||||
|
||||
while (rp && !strcasecmp(rp->service, new_result->service) && new_result->order > rp->order) {
|
||||
prev = rp;
|
||||
rp = rp->next;
|
||||
}
|
||||
|
||||
while (rp && !strcasecmp(rp->service, new_result->service) && new_result->preference > rp->preference) {
|
||||
prev = rp;
|
||||
rp = rp->next;
|
||||
}
|
||||
|
||||
if (prev) {
|
||||
new_result->next = rp;
|
||||
prev->next = new_result;
|
||||
if (!*results) {
|
||||
*results = new_result;
|
||||
(*results)->tail = new_result;
|
||||
} else {
|
||||
new_result->next = rp;
|
||||
q->results = new_result;
|
||||
(*results)->tail->next = new_result;
|
||||
(*results)->tail = new_result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void free_results(enum_record_t ** results)
|
||||
{
|
||||
enum_record_t *fp, *rp;
|
||||
@@ -265,201 +258,226 @@ static void free_results(enum_record_t ** results)
|
||||
*results = NULL;
|
||||
}
|
||||
|
||||
static void parse_rr(const struct dns_parse *p, enum_query_t *q, struct dns_rr *rr)
|
||||
|
||||
static ldns_rdf *ldns_rdf_new_addr_frm_str(const char *str)
|
||||
{
|
||||
const unsigned char *pkt = p->dnsp_pkt;
|
||||
const unsigned char *end = p->dnsp_end;
|
||||
const unsigned char *dptr = rr->dnsrr_dptr;
|
||||
const unsigned char *dend = rr->dnsrr_dend;
|
||||
unsigned char *dn = rr->dnsrr_dn;
|
||||
const unsigned char *c;
|
||||
char flags;
|
||||
int order;
|
||||
int preference;
|
||||
ldns_rdf *a;
|
||||
|
||||
ldns_str2rdf_a(&a, str);
|
||||
|
||||
if (!a) {
|
||||
/* maybe ip6 */
|
||||
ldns_str2rdf_aaaa(&a, str);
|
||||
if (!a) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
#define strip_quotes(_s) if (*_s == '"') _s++; if (end_of(_s) == '"') end_of(_s) = '\0'
|
||||
|
||||
static void parse_naptr(const ldns_rr *naptr, const char *number, enum_record_t **results)
|
||||
{
|
||||
char *str = ldns_rr2str(naptr);
|
||||
char *argv[11] = { 0 };
|
||||
int i, argc;
|
||||
char *pack[4] = { 0 };
|
||||
int packc;
|
||||
|
||||
char *p;
|
||||
int order = 10;
|
||||
int preference = 100;
|
||||
char *service = NULL;
|
||||
char *regex = NULL;
|
||||
char *replace = NULL;
|
||||
char *ptr;
|
||||
int argc = 0;
|
||||
char *argv[4] = { 0 };
|
||||
int n;
|
||||
char string_arg[3][256] = { {0} };
|
||||
char *packstr;
|
||||
|
||||
switch (rr->dnsrr_typ) {
|
||||
case DNS_T_NAPTR: /* prio weight port targetDN */
|
||||
c = dptr;
|
||||
c += 4; /* order, pref */
|
||||
|
||||
for (n = 0; n < 3; ++n) {
|
||||
if (c >= dend) {
|
||||
goto xperr;
|
||||
} else {
|
||||
c += *c + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 || c != dend) {
|
||||
goto xperr;
|
||||
}
|
||||
|
||||
c = dptr;
|
||||
order = dns_get16(c + 0);
|
||||
preference = dns_get16(c + 2);
|
||||
flags = (char) dns_get16(c + 4);
|
||||
c += 4;
|
||||
|
||||
for (n = 0; n < 3; n++) {
|
||||
uint32_t len = *c++, cpylen = len;
|
||||
switch_assert(string_arg[n]);
|
||||
if (len > sizeof(string_arg[n]) - 1) {
|
||||
cpylen = sizeof(string_arg[n]) - 1;
|
||||
}
|
||||
strncpy(string_arg[n], (char *) c, cpylen);
|
||||
*(string_arg[n] + len) = '\0';
|
||||
c += len;
|
||||
}
|
||||
|
||||
service = string_arg[1];
|
||||
|
||||
if ((argc = switch_separate_string(string_arg[2], '!', argv, (sizeof(argv) / sizeof(argv[0]))))) {
|
||||
regex = argv[1];
|
||||
replace = argv[2];
|
||||
} else {
|
||||
goto xperr;
|
||||
}
|
||||
|
||||
for (ptr = replace; ptr && *ptr; ptr++) {
|
||||
if (*ptr == '\\') {
|
||||
*ptr = '$';
|
||||
}
|
||||
}
|
||||
|
||||
if (flags && service && regex && replace) {
|
||||
switch_regex_t *re = NULL;
|
||||
int proceed = 0, ovector[30];
|
||||
char substituted[1024] = "";
|
||||
char rbuf[1024] = "";
|
||||
char *uri;
|
||||
enum_route_t *route;
|
||||
int supported = 0;
|
||||
switch_regex_safe_free(re);
|
||||
|
||||
if ((proceed = switch_regex_perform(q->number, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
|
||||
if (strchr(regex, '(')) {
|
||||
switch_perform_substitution(re, proceed, replace, q->number, substituted, sizeof(substituted), ovector);
|
||||
uri = substituted;
|
||||
} else {
|
||||
uri = replace;
|
||||
}
|
||||
|
||||
switch_mutex_lock(MUTEX);
|
||||
for (route = globals.route_order; route; route = route->next) {
|
||||
if (strcasecmp(service, route->service)) {
|
||||
continue;
|
||||
}
|
||||
switch_regex_safe_free(re);
|
||||
if ((proceed = switch_regex_perform(uri, route->regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
|
||||
if (strchr(route->regex, '(')) {
|
||||
switch_perform_substitution(re, proceed, route->replace, uri, rbuf, sizeof(rbuf), ovector);
|
||||
uri = rbuf;
|
||||
} else {
|
||||
uri = route->replace;
|
||||
}
|
||||
supported++;
|
||||
add_result(q, order, preference, service, uri, supported);
|
||||
}
|
||||
}
|
||||
|
||||
if (!supported) {
|
||||
add_result(q, order, preference, service, uri, 0);
|
||||
}
|
||||
}
|
||||
switch_mutex_unlock(MUTEX);
|
||||
|
||||
|
||||
switch_regex_safe_free(re);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
char *regex, *replace;
|
||||
|
||||
if (zstr(str)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
for (p = str; p && *p; p++) {
|
||||
if (*p == '\t') *p = ' ';
|
||||
if (*p == ' ' && *(p+1) == '.') *p = '\0';
|
||||
}
|
||||
|
||||
xperr:
|
||||
|
||||
argc = switch_split(str, ' ', argv);
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (i > 0) {
|
||||
strip_quotes(argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
service = argv[7];
|
||||
packstr = argv[8];
|
||||
|
||||
if (zstr(service) || zstr(packstr)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!zstr(argv[4])) {
|
||||
order = atoi(argv[4]);
|
||||
}
|
||||
|
||||
if (!zstr(argv[5])) {
|
||||
preference = atoi(argv[5]);
|
||||
}
|
||||
|
||||
|
||||
if ((packc = switch_split(packstr, '!', pack))) {
|
||||
regex = pack[1];
|
||||
replace = pack[2];
|
||||
} else {
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (p = replace; p && *p; p++) {
|
||||
if (*p == '\\') {
|
||||
*p = '$';
|
||||
}
|
||||
}
|
||||
|
||||
if (service && regex && replace) {
|
||||
switch_regex_t *re = NULL, *re2 = NULL;
|
||||
int proceed = 0, ovector[30];
|
||||
char substituted[1024] = "";
|
||||
char rbuf[1024] = "";
|
||||
char *uri;
|
||||
enum_route_t *route;
|
||||
int supported = 0;
|
||||
|
||||
if ((proceed = switch_regex_perform(number, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
|
||||
if (strchr(regex, '(')) {
|
||||
switch_perform_substitution(re, proceed, replace, number, substituted, sizeof(substituted), ovector);
|
||||
uri = substituted;
|
||||
} else {
|
||||
uri = replace;
|
||||
}
|
||||
|
||||
switch_mutex_lock(MUTEX);
|
||||
for (route = globals.route_order; route; route = route->next) {
|
||||
if (strcasecmp(service, route->service)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((proceed = switch_regex_perform(uri, route->regex, &re2, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
|
||||
if (strchr(route->regex, '(')) {
|
||||
switch_perform_substitution(re2, proceed, route->replace, uri, rbuf, sizeof(rbuf), ovector);
|
||||
uri = rbuf;
|
||||
} else {
|
||||
uri = route->replace;
|
||||
}
|
||||
supported++;
|
||||
add_result(results, order, preference, service, uri, supported);
|
||||
}
|
||||
switch_regex_safe_free(re2);
|
||||
}
|
||||
switch_mutex_unlock(MUTEX);
|
||||
|
||||
if (!supported) {
|
||||
add_result(results, order, preference, service, uri, 0);
|
||||
}
|
||||
|
||||
switch_regex_safe_free(re);
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
switch_safe_free(str);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void dnscb(struct dns_ctx *ctx, void *result, void *data)
|
||||
|
||||
switch_status_t ldns_lookup(const char *number, const char *root, const char *server_name, enum_record_t **results)
|
||||
{
|
||||
int r = dns_status(ctx);
|
||||
enum_query_t *q = data;
|
||||
struct dns_parse p;
|
||||
struct dns_rr rr;
|
||||
unsigned nrr;
|
||||
unsigned char dn[DNS_MAXDN];
|
||||
const unsigned char *pkt, *cur, *end, *qdn;
|
||||
if (!result) {
|
||||
dnserror(q, r);
|
||||
return;
|
||||
ldns_resolver *res = NULL;
|
||||
ldns_rdf *domain = NULL;
|
||||
ldns_pkt *p = NULL;
|
||||
ldns_rr_list *naptr = NULL;
|
||||
ldns_status s = LDNS_STATUS_ERR;
|
||||
ldns_rdf *serv_rdf;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
char *name = NULL;
|
||||
|
||||
if (!(name = reverse_number(number, root))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Parse Error!\n");
|
||||
goto end;
|
||||
}
|
||||
pkt = result;
|
||||
end = pkt + r;
|
||||
cur = dns_payload(pkt);
|
||||
dns_getdn(pkt, &cur, end, dn, sizeof(dn));
|
||||
dns_initparse(&p, NULL, pkt, cur, end);
|
||||
p.dnsp_qcls = 0;
|
||||
p.dnsp_qtyp = 0;
|
||||
qdn = dn;
|
||||
nrr = 0;
|
||||
while ((r = dns_nextrr(&p, &rr)) > 0) {
|
||||
if (!dns_dnequal(qdn, rr.dnsrr_dn))
|
||||
continue;
|
||||
if ((qcls == DNS_C_ANY || qcls == rr.dnsrr_cls) && (q->qtyp == DNS_T_ANY || q->qtyp == rr.dnsrr_typ))
|
||||
++nrr;
|
||||
else if (rr.dnsrr_typ == DNS_T_CNAME && !nrr) {
|
||||
if (dns_getdn(pkt, &rr.dnsrr_dptr, end, p.dnsp_dnbuf, sizeof(p.dnsp_dnbuf)) <= 0 || rr.dnsrr_dptr != rr.dnsrr_dend) {
|
||||
r = DNS_E_PROTOCOL;
|
||||
break;
|
||||
} else {
|
||||
qdn = p.dnsp_dnbuf;
|
||||
|
||||
if (!(domain = ldns_dname_new_frm_str(name))) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!zstr(server_name)) {
|
||||
res = ldns_resolver_new();
|
||||
switch_assert(res);
|
||||
|
||||
if ((serv_rdf = ldns_rdf_new_addr_frm_str(server_name))) {
|
||||
s = ldns_resolver_push_nameserver(res, serv_rdf);
|
||||
ldns_rdf_deep_free(serv_rdf);
|
||||
}
|
||||
} else {
|
||||
/* create a new resolver from /etc/resolv.conf */
|
||||
s = ldns_resolver_new_frm_file(&res, NULL);
|
||||
}
|
||||
|
||||
if (s != LDNS_STATUS_OK) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((p = ldns_resolver_query(res,
|
||||
domain,
|
||||
LDNS_RR_TYPE_NAPTR,
|
||||
LDNS_RR_CLASS_IN,
|
||||
LDNS_RD))) {
|
||||
/* retrieve the NAPTR records from the answer section of that
|
||||
* packet
|
||||
*/
|
||||
|
||||
if ((naptr = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NAPTR, LDNS_SECTION_ANSWER))) {
|
||||
size_t i;
|
||||
|
||||
ldns_rr_list_sort(naptr);
|
||||
|
||||
for (i = 0; i < ldns_rr_list_rr_count(naptr); i++) {
|
||||
parse_naptr(ldns_rr_list_rr(naptr, i), number, results);
|
||||
}
|
||||
|
||||
//ldns_rr_list_print(stdout, naptr);
|
||||
ldns_rr_list_deep_free(naptr);
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
if (!r && !nrr)
|
||||
r = DNS_E_NODATA;
|
||||
if (r < 0) {
|
||||
dnserror(q, r);
|
||||
free(result);
|
||||
return;
|
||||
|
||||
end:
|
||||
|
||||
switch_safe_free(name);
|
||||
|
||||
if (domain) {
|
||||
ldns_rdf_deep_free(domain);
|
||||
}
|
||||
|
||||
dns_rewind(&p, NULL);
|
||||
p.dnsp_qtyp = q->qtyp;
|
||||
p.dnsp_qcls = qcls;
|
||||
while (dns_nextrr(&p, &rr)) {
|
||||
parse_rr(&p, q, &rr);
|
||||
if (p) {
|
||||
ldns_pkt_free(p);
|
||||
}
|
||||
|
||||
free(result);
|
||||
if (res) {
|
||||
ldns_resolver_deep_free(res);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t enum_lookup(char *root, char *in, enum_record_t ** results)
|
||||
static switch_status_t enum_lookup(char *root, char *in, enum_record_t **results)
|
||||
{
|
||||
switch_status_t sstatus = SWITCH_STATUS_SUCCESS;
|
||||
char *name = NULL;
|
||||
enum_query_t query = { 0 };
|
||||
enum dns_type l_qtyp = DNS_T_NAPTR;
|
||||
int i = 0, abs = 0, j = 0;
|
||||
dns_socket fd = (dns_socket) - 1;
|
||||
fd_set fds;
|
||||
struct timeval tv = { 0 };
|
||||
time_t now = 0;
|
||||
struct dns_ctx *nctx = NULL;
|
||||
char *num, *mnum = NULL, *mroot = NULL, *p;
|
||||
char *mnum = NULL, *mroot = NULL, *p;
|
||||
char *server = NULL;
|
||||
|
||||
*results = NULL;
|
||||
|
||||
@@ -475,87 +493,13 @@ static switch_status_t enum_lookup(char *root, char *in, enum_record_t ** result
|
||||
root = globals.root;
|
||||
}
|
||||
|
||||
num = mnum;
|
||||
if (!(name = reverse_number(num, root))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Parse Error!\n");
|
||||
sstatus = SWITCH_STATUS_FALSE;
|
||||
goto done;
|
||||
|
||||
if (!(server = switch_core_get_variable("enum-server"))) {
|
||||
server = globals.server;
|
||||
}
|
||||
|
||||
if (!(nctx = dns_new(NULL))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Memory Error!\n");
|
||||
sstatus = SWITCH_STATUS_MEMERR;
|
||||
goto done;
|
||||
}
|
||||
ldns_lookup(mnum, root, server, results);
|
||||
|
||||
fd = dns_open(nctx);
|
||||
|
||||
if (fd < 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FD Error!\n");
|
||||
sstatus = SWITCH_STATUS_FALSE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
dns_ptodn(name, (unsigned int) strlen(name), query.dn, sizeof(query.dn), &abs);
|
||||
query.name = name;
|
||||
query.number = num;
|
||||
query.qtyp = l_qtyp;
|
||||
|
||||
if (abs) {
|
||||
abs = DNS_NOSRCH;
|
||||
}
|
||||
|
||||
if (!dns_submit_dn(nctx, query.dn, qcls, l_qtyp, abs, 0, dnscb, &query)) {
|
||||
dnserror(&query, dns_status(nctx));
|
||||
}
|
||||
|
||||
FD_ZERO(&fds);
|
||||
now = 0;
|
||||
|
||||
while ((i = dns_timeouts(nctx, 1, now)) > 0) {
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4389 4127)
|
||||
#endif
|
||||
FD_SET(fd, &fds);
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
j += i;
|
||||
|
||||
if (j > globals.timeout || query.results || query.errs) {
|
||||
break;
|
||||
}
|
||||
|
||||
tv.tv_sec = i;
|
||||
tv.tv_usec = 0;
|
||||
i = select((int) (fd + 1), &fds, 0, 0, &tv);
|
||||
now = switch_epoch_time_now(NULL);
|
||||
if (i > 0) {
|
||||
dns_ioevent(nctx, now);
|
||||
}
|
||||
}
|
||||
|
||||
if (!query.results) {
|
||||
sstatus = SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
*results = query.results;
|
||||
query.results = NULL;
|
||||
|
||||
done:
|
||||
|
||||
if (fd > -1) {
|
||||
closesocket(fd);
|
||||
fd = (dns_socket) - 1;
|
||||
}
|
||||
|
||||
if (nctx) {
|
||||
dns_free(nctx);
|
||||
}
|
||||
|
||||
switch_safe_free(name);
|
||||
switch_safe_free(mnum);
|
||||
switch_safe_free(mroot);
|
||||
|
||||
@@ -623,15 +567,17 @@ SWITCH_STANDARD_APP(enum_app_function)
|
||||
dest = argv[0];
|
||||
root = argv[1];
|
||||
if (enum_lookup(root, dest, &results) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_event_header_t *hi;
|
||||
if ((hi = switch_channel_variable_first(channel))) {
|
||||
for (; hi; hi = hi->next) {
|
||||
switch_event_t *vars;
|
||||
|
||||
if (switch_channel_get_variables(channel, &vars) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_event_header_t *hi;
|
||||
for (hi = vars->headers; hi; hi = hi->next) {
|
||||
char *vvar = hi->name;
|
||||
if (vvar && !strncmp(vvar, "enum_", 5)) {
|
||||
switch_channel_set_variable(channel, (char *) vvar, NULL);
|
||||
}
|
||||
}
|
||||
switch_channel_variable_last(channel);
|
||||
switch_event_destroy(&vars);
|
||||
}
|
||||
|
||||
for (rp = results; rp; rp = rp->next) {
|
||||
@@ -823,9 +769,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_enum_load)
|
||||
return SWITCH_STATUS_TERM;
|
||||
}
|
||||
|
||||
if (dns_init(0) < 0) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
memset(&globals, 0, sizeof(globals));
|
||||
do_load();
|
||||
|
||||
@@ -10,8 +10,10 @@ DING_DIR=$(BASE)/libs/libdingaling
|
||||
LOCAL_CFLAGS += -I$(DING_DIR)/src -I$(BASE)/libs/iksemel/include
|
||||
LOCAL_OBJS=$(DING_DIR)/src/libdingaling.o $(DING_DIR)/src/sha1.o $(IKS_LA)
|
||||
LOCAL_SOURCES=$(DING_DIR)/src/libdingaling.c $(DING_DIR)/src/sha1.c
|
||||
LOCAL_LDFLAGS=$(LIBGNUTLS_LIBS)
|
||||
include $(BASE)/build/modmake.rules
|
||||
|
||||
|
||||
$(IKS_LA): $(IKS_DIR) $(IKS_DIR)/.update
|
||||
@cd $(IKS_DIR) && $(MAKE)
|
||||
@$(TOUCH_TARGET)
|
||||
|
||||
@@ -3480,6 +3480,96 @@ SWITCH_STANDARD_API(sofia_count_reg_function)
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_API(sofia_username_of_function)
|
||||
{
|
||||
char *data;
|
||||
char *user = NULL;
|
||||
char *domain = NULL;
|
||||
char *profile_name = NULL;
|
||||
char *p;
|
||||
char *reply = "";
|
||||
sofia_profile_t *profile = NULL;
|
||||
|
||||
if (!cmd) {
|
||||
stream->write_function(stream, "%s", "");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
data = strdup(cmd);
|
||||
switch_assert(data);
|
||||
|
||||
if ((p = strchr(data, '/'))) {
|
||||
profile_name = data;
|
||||
*p++ = '\0';
|
||||
user = p;
|
||||
} else {
|
||||
user = data;
|
||||
}
|
||||
|
||||
if ((domain = strchr(user, '@'))) {
|
||||
*domain++ = '\0';
|
||||
}
|
||||
|
||||
if (!profile_name && domain) {
|
||||
profile_name = domain;
|
||||
}
|
||||
|
||||
if (user && profile_name) {
|
||||
char *sql;
|
||||
|
||||
if (!(profile = sofia_glue_find_profile(profile_name))) {
|
||||
profile_name = domain;
|
||||
domain = NULL;
|
||||
}
|
||||
|
||||
if (!profile && profile_name) {
|
||||
profile = sofia_glue_find_profile(profile_name);
|
||||
}
|
||||
|
||||
if (profile) {
|
||||
struct cb_helper_sql2str cb;
|
||||
char username[256] = "";
|
||||
|
||||
cb.buf = username;
|
||||
cb.len = sizeof(username);
|
||||
|
||||
if (!domain || !strchr(domain, '.')) {
|
||||
domain = profile->name;
|
||||
}
|
||||
|
||||
switch_assert(!zstr(user));
|
||||
|
||||
sql = switch_mprintf("select sip_username "
|
||||
"from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
|
||||
user, domain, domain);
|
||||
|
||||
switch_assert(sql);
|
||||
|
||||
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sql2str_callback, &cb);
|
||||
switch_safe_free(sql);
|
||||
if (!zstr(username)) {
|
||||
stream->write_function(stream, "%s", username);
|
||||
} else {
|
||||
stream->write_function(stream, "");
|
||||
}
|
||||
reply = NULL;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (reply) {
|
||||
stream->write_function(stream, "%s", reply);
|
||||
}
|
||||
|
||||
switch_safe_free(data);
|
||||
|
||||
if (profile) {
|
||||
sofia_glue_release_profile(profile);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void select_from_profile(sofia_profile_t *profile,
|
||||
const char *user,
|
||||
const char *domain,
|
||||
@@ -4993,6 +5083,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
|
||||
switch_console_add_complete_func("::sofia::list_profile_gateway", list_profile_gateway);
|
||||
|
||||
|
||||
SWITCH_ADD_API(api_interface, "sofia_username_of", "Sofia Username Lookup", sofia_username_of_function, "[profile/]<user>@<domain>");
|
||||
SWITCH_ADD_API(api_interface, "sofia_contact", "Sofia Contacts", sofia_contact_function, "[profile/]<user>@<domain>");
|
||||
SWITCH_ADD_API(api_interface, "sofia_count_reg", "Count Sofia registration", sofia_count_reg_function, "[profile/]<user>@<domain>");
|
||||
SWITCH_ADD_API(api_interface, "sofia_dig", "SIP DIG", sip_dig_function, "<url>");
|
||||
|
||||
@@ -5210,12 +5210,14 @@ void sofia_glue_del_profile(sofia_profile_t *profile)
|
||||
}
|
||||
|
||||
for (gp = profile->gateways; gp; gp = gp->next) {
|
||||
char *pkey = switch_mprintf("%s::%s", profile->name, gp->name);
|
||||
|
||||
switch_core_hash_delete(mod_sofia_globals.gateway_hash, gp->name);
|
||||
switch_core_hash_delete(mod_sofia_globals.gateway_hash, gp->register_from);
|
||||
switch_core_hash_delete(mod_sofia_globals.gateway_hash, gp->register_contact);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "deleted gateway %s\n", gp->name);
|
||||
profile->gateways = NULL;
|
||||
switch_core_hash_delete(mod_sofia_globals.gateway_hash, pkey);
|
||||
switch_safe_free(pkey);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "deleted gateway %s from profile %s\n", gp->name, profile->name);
|
||||
}
|
||||
profile->gateways = NULL;
|
||||
}
|
||||
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
|
||||
}
|
||||
|
||||
@@ -9315,6 +9315,16 @@ SWIGEXPORT int SWIGSTDCALL CSharp_set_high_priority() {
|
||||
}
|
||||
|
||||
|
||||
SWIGEXPORT int SWIGSTDCALL CSharp_set_normal_priority() {
|
||||
int jresult ;
|
||||
int32_t result;
|
||||
|
||||
result = (int32_t)set_normal_priority();
|
||||
jresult = result;
|
||||
return jresult;
|
||||
}
|
||||
|
||||
|
||||
SWIGEXPORT int SWIGSTDCALL CSharp_change_user_group(char * jarg1, char * jarg2) {
|
||||
int jresult ;
|
||||
char *arg1 = (char *) 0 ;
|
||||
@@ -9638,6 +9648,14 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_time_set_monotonic(int jarg1) {
|
||||
}
|
||||
|
||||
|
||||
SWIGEXPORT void SWIGSTDCALL CSharp_switch_time_set_timerfd(int jarg1) {
|
||||
switch_bool_t arg1 ;
|
||||
|
||||
arg1 = (switch_bool_t)jarg1;
|
||||
switch_time_set_timerfd(arg1);
|
||||
}
|
||||
|
||||
|
||||
SWIGEXPORT void SWIGSTDCALL CSharp_switch_time_set_nanosleep(int jarg1) {
|
||||
switch_bool_t arg1 ;
|
||||
|
||||
@@ -23128,6 +23146,14 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_set_caller_extension(void * ja
|
||||
}
|
||||
|
||||
|
||||
SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_flip_cid(void * jarg1) {
|
||||
switch_channel_t *arg1 = (switch_channel_t *) 0 ;
|
||||
|
||||
arg1 = (switch_channel_t *)jarg1;
|
||||
switch_channel_flip_cid(arg1);
|
||||
}
|
||||
|
||||
|
||||
SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_sort_cid(void * jarg1, int jarg2) {
|
||||
switch_channel_t *arg1 = (switch_channel_t *) 0 ;
|
||||
switch_bool_t arg2 ;
|
||||
|
||||
@@ -9606,6 +9606,16 @@ SWIGEXPORT int SWIGSTDCALL CSharp_set_high_priority() {
|
||||
}
|
||||
|
||||
|
||||
SWIGEXPORT int SWIGSTDCALL CSharp_set_normal_priority() {
|
||||
int jresult ;
|
||||
int32_t result;
|
||||
|
||||
result = (int32_t)set_normal_priority();
|
||||
jresult = result;
|
||||
return jresult;
|
||||
}
|
||||
|
||||
|
||||
SWIGEXPORT int SWIGSTDCALL CSharp_change_user_group(char * jarg1, char * jarg2) {
|
||||
int jresult ;
|
||||
char *arg1 = (char *) 0 ;
|
||||
@@ -9929,6 +9939,14 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_time_set_monotonic(int jarg1) {
|
||||
}
|
||||
|
||||
|
||||
SWIGEXPORT void SWIGSTDCALL CSharp_switch_time_set_timerfd(int jarg1) {
|
||||
switch_bool_t arg1 ;
|
||||
|
||||
arg1 = (switch_bool_t)jarg1;
|
||||
switch_time_set_timerfd(arg1);
|
||||
}
|
||||
|
||||
|
||||
SWIGEXPORT void SWIGSTDCALL CSharp_switch_time_set_nanosleep(int jarg1) {
|
||||
switch_bool_t arg1 ;
|
||||
|
||||
|
||||
@@ -2134,6 +2134,11 @@ public class freeswitch {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static int set_normal_priority() {
|
||||
int ret = freeswitchPINVOKE.set_normal_priority();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static int change_user_group(string user, string group) {
|
||||
int ret = freeswitchPINVOKE.change_user_group(user, group);
|
||||
return ret;
|
||||
@@ -2275,6 +2280,10 @@ public class freeswitch {
|
||||
freeswitchPINVOKE.switch_time_set_monotonic((int)enable);
|
||||
}
|
||||
|
||||
public static void switch_time_set_timerfd(switch_bool_t enable) {
|
||||
freeswitchPINVOKE.switch_time_set_timerfd((int)enable);
|
||||
}
|
||||
|
||||
public static void switch_time_set_nanosleep(switch_bool_t enable) {
|
||||
freeswitchPINVOKE.switch_time_set_nanosleep((int)enable);
|
||||
}
|
||||
@@ -3415,6 +3424,10 @@ public class freeswitch {
|
||||
freeswitchPINVOKE.switch_channel_set_caller_extension(SWIGTYPE_p_switch_channel.getCPtr(channel), switch_caller_extension.getCPtr(caller_extension));
|
||||
}
|
||||
|
||||
public static void switch_channel_flip_cid(SWIGTYPE_p_switch_channel channel) {
|
||||
freeswitchPINVOKE.switch_channel_flip_cid(SWIGTYPE_p_switch_channel.getCPtr(channel));
|
||||
}
|
||||
|
||||
public static void switch_channel_sort_cid(SWIGTYPE_p_switch_channel channel, switch_bool_t arg1) {
|
||||
freeswitchPINVOKE.switch_channel_sort_cid(SWIGTYPE_p_switch_channel.getCPtr(channel), (int)arg1);
|
||||
}
|
||||
@@ -8068,6 +8081,9 @@ class freeswitchPINVOKE {
|
||||
[DllImport("mod_managed", EntryPoint="CSharp_set_high_priority")]
|
||||
public static extern int set_high_priority();
|
||||
|
||||
[DllImport("mod_managed", EntryPoint="CSharp_set_normal_priority")]
|
||||
public static extern int set_normal_priority();
|
||||
|
||||
[DllImport("mod_managed", EntryPoint="CSharp_change_user_group")]
|
||||
public static extern int change_user_group(string jarg1, string jarg2);
|
||||
|
||||
@@ -8155,6 +8171,9 @@ class freeswitchPINVOKE {
|
||||
[DllImport("mod_managed", EntryPoint="CSharp_switch_time_set_monotonic")]
|
||||
public static extern void switch_time_set_monotonic(int jarg1);
|
||||
|
||||
[DllImport("mod_managed", EntryPoint="CSharp_switch_time_set_timerfd")]
|
||||
public static extern void switch_time_set_timerfd(int jarg1);
|
||||
|
||||
[DllImport("mod_managed", EntryPoint="CSharp_switch_time_set_nanosleep")]
|
||||
public static extern void switch_time_set_nanosleep(int jarg1);
|
||||
|
||||
@@ -11500,6 +11519,9 @@ class freeswitchPINVOKE {
|
||||
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_set_caller_extension")]
|
||||
public static extern void switch_channel_set_caller_extension(HandleRef jarg1, HandleRef jarg2);
|
||||
|
||||
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_flip_cid")]
|
||||
public static extern void switch_channel_flip_cid(HandleRef jarg1);
|
||||
|
||||
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_sort_cid")]
|
||||
public static extern void switch_channel_sort_cid(HandleRef jarg1, int jarg2);
|
||||
|
||||
@@ -21716,6 +21738,8 @@ public enum switch_channel_flag_t {
|
||||
CF_DIALPLAN,
|
||||
CF_BLOCK_BROADCAST_UNTIL_MEDIA,
|
||||
CF_CNG_PLC,
|
||||
CF_ATTENDED_TRANSFER,
|
||||
CF_LAZY_ATTENDED_TRANSFER,
|
||||
CF_FLAG_MAX
|
||||
}
|
||||
|
||||
@@ -28777,7 +28801,7 @@ namespace FreeSWITCH.Native {
|
||||
SWITCH_RTP_FLAG_BREAK = (1 << 10),
|
||||
SWITCH_RTP_FLAG_UDPTL = (1 << 11),
|
||||
SWITCH_RTP_FLAG_DATAWAIT = (1 << 12),
|
||||
SWITCH_RTP_FLAG_BUGGY_2833 = (1 << 13),
|
||||
SWITCH_RTP_FLAG_BYTESWAP = (1 << 13),
|
||||
SWITCH_RTP_FLAG_PASS_RFC2833 = (1 << 14),
|
||||
SWITCH_RTP_FLAG_AUTO_CNG = (1 << 15),
|
||||
SWITCH_RTP_FLAG_SECURE_SEND_RESET = (1 << 16),
|
||||
|
||||
@@ -2124,6 +2124,11 @@ public class freeswitch {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static int set_normal_priority() {
|
||||
int ret = freeswitchPINVOKE.set_normal_priority();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static int change_user_group(string user, string group) {
|
||||
int ret = freeswitchPINVOKE.change_user_group(user, group);
|
||||
return ret;
|
||||
@@ -2265,6 +2270,10 @@ public class freeswitch {
|
||||
freeswitchPINVOKE.switch_time_set_monotonic((int)enable);
|
||||
}
|
||||
|
||||
public static void switch_time_set_timerfd(switch_bool_t enable) {
|
||||
freeswitchPINVOKE.switch_time_set_timerfd((int)enable);
|
||||
}
|
||||
|
||||
public static void switch_time_set_nanosleep(switch_bool_t enable) {
|
||||
freeswitchPINVOKE.switch_time_set_nanosleep((int)enable);
|
||||
}
|
||||
@@ -8058,6 +8067,9 @@ class freeswitchPINVOKE {
|
||||
[DllImport("mod_managed", EntryPoint="CSharp_set_high_priority")]
|
||||
public static extern int set_high_priority();
|
||||
|
||||
[DllImport("mod_managed", EntryPoint="CSharp_set_normal_priority")]
|
||||
public static extern int set_normal_priority();
|
||||
|
||||
[DllImport("mod_managed", EntryPoint="CSharp_change_user_group")]
|
||||
public static extern int change_user_group(string jarg1, string jarg2);
|
||||
|
||||
@@ -8145,6 +8157,9 @@ class freeswitchPINVOKE {
|
||||
[DllImport("mod_managed", EntryPoint="CSharp_switch_time_set_monotonic")]
|
||||
public static extern void switch_time_set_monotonic(int jarg1);
|
||||
|
||||
[DllImport("mod_managed", EntryPoint="CSharp_switch_time_set_timerfd")]
|
||||
public static extern void switch_time_set_timerfd(int jarg1);
|
||||
|
||||
[DllImport("mod_managed", EntryPoint="CSharp_switch_time_set_nanosleep")]
|
||||
public static extern void switch_time_set_nanosleep(int jarg1);
|
||||
|
||||
|
||||
@@ -9899,17 +9899,17 @@ XS(SWIG_init) {
|
||||
SWIG_TypeClientData(SWIGTYPE_p_IVRMenu, (void*) "freeswitch::IVRMenu");
|
||||
SWIG_TypeClientData(SWIGTYPE_p_API, (void*) "freeswitch::API");
|
||||
SWIG_TypeClientData(SWIGTYPE_p_input_callback_state, (void*) "freeswitch::input_callback_state_t");
|
||||
/*@SWIG:/usr/local/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do {
|
||||
/*@SWIG:/usr/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do {
|
||||
SV *sv = get_sv((char*) SWIG_prefix "S_HUP", TRUE | 0x2 | GV_ADDMULTI);
|
||||
sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(S_HUP)));
|
||||
SvREADONLY_on(sv);
|
||||
} while(0) /*@SWIG@*/;
|
||||
/*@SWIG:/usr/local/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do {
|
||||
/*@SWIG:/usr/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do {
|
||||
SV *sv = get_sv((char*) SWIG_prefix "S_FREE", TRUE | 0x2 | GV_ADDMULTI);
|
||||
sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(S_FREE)));
|
||||
SvREADONLY_on(sv);
|
||||
} while(0) /*@SWIG@*/;
|
||||
/*@SWIG:/usr/local/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do {
|
||||
/*@SWIG:/usr/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do {
|
||||
SV *sv = get_sv((char*) SWIG_prefix "S_RDLOCK", TRUE | 0x2 | GV_ADDMULTI);
|
||||
sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(S_RDLOCK)));
|
||||
SvREADONLY_on(sv);
|
||||
|
||||
@@ -240,7 +240,6 @@ void Session::unsetInputCallback(void)
|
||||
cb_arg = NULL;
|
||||
}
|
||||
|
||||
switch_channel_set_private(channel, "CoreSession", NULL);
|
||||
args.input_callback = NULL;
|
||||
ap = NULL;
|
||||
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
*
|
||||
* 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 FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
*
|
||||
* The Original Code is 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):
|
||||
* Timo Teräs <timo.teras@iki.fi>
|
||||
*
|
||||
*
|
||||
* mod_timerfd.c -- Timer implementation using Linux timerfd
|
||||
*
|
||||
*/
|
||||
|
||||
#include <switch.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_timerfd_load);
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_timerfd_shutdown);
|
||||
SWITCH_MODULE_RUNTIME_FUNCTION(mod_timerfd_runtime);
|
||||
SWITCH_MODULE_DEFINITION(mod_timerfd, mod_timerfd_load, mod_timerfd_shutdown, mod_timerfd_runtime);
|
||||
|
||||
#define MAX_INTERVAL 2000 /* ms */
|
||||
|
||||
struct interval_timer {
|
||||
int fd;
|
||||
int users;
|
||||
switch_size_t tick;
|
||||
switch_mutex_t *mutex;
|
||||
switch_thread_cond_t *cond;
|
||||
};
|
||||
typedef struct interval_timer interval_timer_t;
|
||||
|
||||
static switch_memory_pool_t *module_pool = NULL;
|
||||
static switch_mutex_t *interval_timers_mutex;
|
||||
static interval_timer_t interval_timers[MAX_INTERVAL + 1];
|
||||
static int interval_poll_fd;
|
||||
|
||||
static switch_status_t timerfd_start_interval(interval_timer_t *it, int interval)
|
||||
{
|
||||
struct itimerspec val;
|
||||
struct epoll_event e;
|
||||
int fd;
|
||||
|
||||
it->users++;
|
||||
if (it->users > 1)
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
it->tick = 0;
|
||||
switch_mutex_init(&it->mutex, SWITCH_MUTEX_NESTED, module_pool);
|
||||
switch_thread_cond_create(&it->cond, module_pool);
|
||||
|
||||
fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
|
||||
if (fd < 0)
|
||||
return SWITCH_STATUS_GENERR;
|
||||
|
||||
val.it_interval.tv_sec = interval / 1000;
|
||||
val.it_interval.tv_nsec = (interval % 1000) * 1000000;
|
||||
val.it_value.tv_sec = 0;
|
||||
val.it_value.tv_nsec = 100000;
|
||||
|
||||
if (timerfd_settime(fd, 0, &val, NULL) < 0) {
|
||||
close(fd);
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
e.events = EPOLLIN | EPOLLERR;
|
||||
e.data.ptr = it;
|
||||
if (epoll_ctl(interval_poll_fd, EPOLL_CTL_ADD, fd, &e) < 0) {
|
||||
close(fd);
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
it->fd = fd;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t timerfd_stop_interval(interval_timer_t *it)
|
||||
{
|
||||
it->users--;
|
||||
if (it->users > 0)
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
close(it->fd);
|
||||
it->fd = -1;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t timerfd_init(switch_timer_t *timer)
|
||||
{
|
||||
interval_timer_t *it;
|
||||
int rc;
|
||||
|
||||
if (timer->interval < 1 || timer->interval > MAX_INTERVAL)
|
||||
return SWITCH_STATUS_GENERR;
|
||||
|
||||
it = &interval_timers[timer->interval];
|
||||
switch_mutex_lock(interval_timers_mutex);
|
||||
rc = timerfd_start_interval(it, timer->interval);
|
||||
timer->private_info = it;
|
||||
switch_mutex_unlock(interval_timers_mutex);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static switch_status_t timerfd_step(switch_timer_t *timer)
|
||||
{
|
||||
timer->tick++;
|
||||
timer->samplecount += timer->samples;
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t timerfd_next(switch_timer_t *timer)
|
||||
{
|
||||
interval_timer_t *it = timer->private_info;
|
||||
|
||||
if ((int)(timer->tick - it->tick) < -1)
|
||||
timer->tick = it->tick;
|
||||
timerfd_step(timer);
|
||||
|
||||
switch_mutex_lock(it->mutex);
|
||||
while ((int)(timer->tick - it->tick) > 0)
|
||||
switch_thread_cond_wait(it->cond, it->mutex);
|
||||
switch_mutex_unlock(it->mutex);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t timerfd_sync(switch_timer_t *timer)
|
||||
{
|
||||
interval_timer_t *it = timer->private_info;
|
||||
|
||||
timer->tick = it->tick;
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t timerfd_check(switch_timer_t *timer, switch_bool_t step)
|
||||
{
|
||||
interval_timer_t *it = timer->private_info;
|
||||
int diff = (int)(timer->tick - it->tick);
|
||||
|
||||
if (diff > 0) {
|
||||
/* still pending */
|
||||
timer->diff = diff;
|
||||
return SWITCH_STATUS_FALSE;
|
||||
} else {
|
||||
/* timer pending */
|
||||
timer->diff = 0;
|
||||
if (step)
|
||||
timerfd_step(timer);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
static switch_status_t timerfd_destroy(switch_timer_t *timer)
|
||||
{
|
||||
interval_timer_t *it = timer->private_info;
|
||||
int rc;
|
||||
|
||||
switch_mutex_lock(interval_timers_mutex);
|
||||
rc = timerfd_stop_interval(it);
|
||||
switch_mutex_unlock(interval_timers_mutex);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_timerfd_load)
|
||||
{
|
||||
switch_timer_interface_t *timer_interface;
|
||||
|
||||
module_pool = pool;
|
||||
|
||||
interval_poll_fd = epoll_create(16);
|
||||
if (interval_poll_fd < 0)
|
||||
return SWITCH_STATUS_GENERR;
|
||||
|
||||
switch_mutex_init(&interval_timers_mutex, SWITCH_MUTEX_NESTED, module_pool);
|
||||
memset(interval_timers, 0, sizeof(interval_timers));
|
||||
|
||||
/* connect my internal structure to the blank pointer passed to me */
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
timer_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_TIMER_INTERFACE);
|
||||
timer_interface->interface_name = "timerfd";
|
||||
timer_interface->timer_init = timerfd_init;
|
||||
timer_interface->timer_next = timerfd_next;
|
||||
timer_interface->timer_step = timerfd_step;
|
||||
timer_interface->timer_sync = timerfd_sync;
|
||||
timer_interface->timer_check = timerfd_check;
|
||||
timer_interface->timer_destroy = timerfd_destroy;
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_timerfd_shutdown)
|
||||
{
|
||||
close(interval_poll_fd);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_MODULE_RUNTIME_FUNCTION(mod_timerfd_runtime)
|
||||
{
|
||||
struct epoll_event e[16];
|
||||
interval_timer_t *it;
|
||||
uint64_t u64;
|
||||
int i, r;
|
||||
|
||||
do {
|
||||
r = epoll_wait(interval_poll_fd, e, sizeof(e) / sizeof(e[0]), 1000);
|
||||
if (r < 0)
|
||||
break;
|
||||
for (i = 0; i < r; i++) {
|
||||
it = e[i].data.ptr;
|
||||
if ((e[i].events & EPOLLIN) &&
|
||||
read(it->fd, &u64, sizeof(u64)) == sizeof(u64)) {
|
||||
switch_mutex_lock(it->mutex);
|
||||
it->tick += u64;
|
||||
switch_thread_cond_broadcast(it->cond);
|
||||
switch_mutex_unlock(it->mutex);
|
||||
}
|
||||
}
|
||||
} while (1);
|
||||
|
||||
return SWITCH_STATUS_TERM;
|
||||
}
|
||||
|
||||
/* 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:
|
||||
*/
|
||||
Reference in new issue
Block a user