aboutsummaryrefslogtreecommitdiff
path: root/Src/replicant/jnetlib/asyncdns.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/replicant/jnetlib/asyncdns.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/replicant/jnetlib/asyncdns.cpp')
-rw-r--r--Src/replicant/jnetlib/asyncdns.cpp314
1 files changed, 314 insertions, 0 deletions
diff --git a/Src/replicant/jnetlib/asyncdns.cpp b/Src/replicant/jnetlib/asyncdns.cpp
new file mode 100644
index 00000000..2a680216
--- /dev/null
+++ b/Src/replicant/jnetlib/asyncdns.cpp
@@ -0,0 +1,314 @@
+/*
+** JNetLib
+** Copyright (C) 2000-2007 Nullsoft, Inc.
+** Author: Justin Frankel
+** File: asyncdns.cpp - JNL portable asynchronous DNS implementation
+** License: see jnetlib.h
+*/
+
+#include "netinc.h"
+#include "util.h"
+#include "asyncdns.h"
+#include <time.h>
+#ifdef _WIN32
+#include <strsafe.h>
+#endif
+
+enum
+{
+ MODE_RESOLVE=0,
+ MODE_REVERSE=1,
+};
+
+
+struct cache_entry
+{
+ time_t last_used; // timestamp.
+ bool resolved;
+ int mode; // 1=reverse
+ unsigned short port;
+ char hostname[256];
+ addrinfo *addr;
+ int sockettype;
+};
+
+JNL_AsyncDNS::JNL_AsyncDNS(int max_cache_entries)
+{
+ m_thread_kill=1;
+ m_thread=0;
+ m_cache_size=max_cache_entries;
+ m_cache=(cache_entry *)malloc(sizeof(cache_entry)*m_cache_size);
+ memset(m_cache, 0, sizeof(cache_entry)*m_cache_size);
+}
+
+JNL_AsyncDNS::~JNL_AsyncDNS()
+{
+ m_thread_kill=1;
+
+#ifdef _WIN32
+ if (m_thread)
+ {
+ WaitForSingleObject(m_thread,INFINITE);
+ CloseHandle(m_thread);
+ }
+#else
+ if (m_thread)
+ {
+ void *p;
+ pthread_join(m_thread,&p);
+ }
+#endif//!_WIN32
+ // free all the addrinfo stuff
+ for (int x = 0; x < m_cache_size; x ++)
+ {
+ if (m_cache[x].addr)
+ freeaddrinfo(m_cache[x].addr);
+ }
+
+ free(m_cache);
+}
+
+int JNL_AsyncDNS::resolvenow(const char *hostname, unsigned short port, addrinfo **addr, int sockettype)
+{
+ addrinfo hints;
+ memset(&hints,0,sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ if (hostname)
+ hints.ai_flags = AI_NUMERICHOST;
+ else
+ hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
+ hints.ai_socktype = sockettype;
+
+ char portString[32] = {0};
+ sprintf(portString, "%u", (unsigned int)port);
+
+ if (getaddrinfo(hostname, portString, &hints, addr) == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ hints.ai_flags = 0;
+ if (getaddrinfo(hostname, portString, &hints, addr) == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+}
+
+#ifdef _WIN32
+unsigned long WINAPI JNL_AsyncDNS::_threadfunc(LPVOID _d)
+#else
+unsigned int JNL_AsyncDNS::_threadfunc(void *_d)
+#endif
+{
+ int nowinsock=JNL::open_socketlib();
+ JNL_AsyncDNS *_this=(JNL_AsyncDNS*)_d;
+ int x;
+ for (x = 0; x < _this->m_cache_size && !_this->m_thread_kill; x ++)
+ {
+ if (_this->m_cache[x].last_used && !_this->m_cache[x].resolved)
+ {
+ if (!nowinsock)
+ {
+ if (_this->m_cache[x].mode==0)
+ {
+ addrinfo *res=0;
+ if (resolvenow(_this->m_cache[x].hostname, _this->m_cache[x].port, &res, _this->m_cache[x].sockettype) == 0)
+ {
+ _this->m_cache[x].addr=res;
+ }
+ else
+ {
+ _this->m_cache[x].addr=0;//INADDR_NONE;
+ }
+ }
+ else if (_this->m_cache[x].mode==1)
+ {
+ /*
+ hostent *ent;
+ // TODO: replace with getnameinfo for IPv6
+ ent=gethostbyaddr((const char *)&_this->m_cache[x].addr,4,AF_INET);
+ if (ent)
+ lstrcpyn(_this->m_cache[x].hostname, ent->h_name, 256);
+ else
+ _this->m_cache[x].hostname[0]=0;
+ */
+ }
+ _this->m_cache[x].resolved=true;
+ }
+ else
+ {
+ if (_this->m_cache[x].mode==0)
+ {
+ _this->m_cache[x].addr=0;//INADDR_NONE;
+ _this->m_cache[x].resolved=true;
+ }
+ else if (_this->m_cache[x].mode==1)
+ {
+ _this->m_cache[x].hostname[0]=0;
+ _this->m_cache[x].resolved=true;
+ }
+ }
+ }
+ }
+ if (!nowinsock) JNL::close_socketlib();
+ _this->m_thread_kill=1;
+
+ return 0;
+}
+
+int JNL_AsyncDNS::resolve(const char *hostname, unsigned short port, addrinfo **addr, int sockettype)
+{
+ // return 0 on success, 1 on wait, -1 on unresolvable
+ int x;
+
+ for (x = 0; x < m_cache_size; x ++)
+ {
+ if (!strcasecmp(m_cache[x].hostname,hostname) && port == m_cache[x].port && m_cache[x].mode==0 && m_cache[x].sockettype==sockettype)
+ {
+ m_cache[x].last_used=time(0);
+ if (m_cache[x].resolved)
+ {
+ if (m_cache[x].addr == 0)//INADDR_NONE)
+ {
+ return DNS_RESOLVE_UNRESOLVABLE;
+ }
+ *addr =m_cache[x].addr;
+ return DNS_RESOLVE_SUCCESS;
+ }
+ makesurethreadisrunning();
+ return DNS_RESOLVE_WAIT;
+ }
+ }
+ // add to resolve list
+ int oi=-1;
+ for (x = 0; x < m_cache_size; x ++)
+ {
+ if (!m_cache[x].last_used)
+ {
+ oi=x;
+ break;
+ }
+ if ((oi==-1 || m_cache[x].last_used < m_cache[oi].last_used) && m_cache[x].resolved)
+ {
+ oi=x;
+ }
+ }
+ if (oi == -1)
+ {
+ return DNS_RESOLVE_UNRESOLVABLE;
+ }
+#ifdef _WIN32
+ StringCchCopyA(m_cache[oi].hostname, 256, hostname);
+#elif defined(__APPLE__)
+ strlcpy(m_cache[oi].hostname, hostname, 255);
+#else
+ strncpy(m_cache[oi].hostname, hostname, 255);
+ m_cache[oi].hostname[255]=0;
+#endif
+ m_cache[oi].port=port;
+ m_cache[oi].mode=0;
+ m_cache[oi].addr=0;//INADDR_NONE;
+ m_cache[oi].resolved=false;
+ m_cache[oi].last_used=time(0);
+ m_cache[oi].sockettype=sockettype;
+
+ makesurethreadisrunning();
+ return DNS_RESOLVE_WAIT;
+}
+
+/*
+int JNL_AsyncDNS::reverse(unsigned long addr, char *hostname, size_t hostnameSize)
+{
+// return 0 on success, 1 on wait, -1 on unresolvable
+int x;
+if (addr == INADDR_NONE)
+{
+return DNS_REVERSE_UNRESOLVABLE;
+}
+#ifndef NO_DNS_SUPPORT
+for (x = 0; x < m_cache_size; x ++)
+{
+if (m_cache[x].addr==addr && m_cache[x].mode==1)
+{
+m_cache[x].last_used=time(0);
+if (m_cache[x].resolved)
+{
+if (!m_cache[x].hostname[0])
+{
+return DNS_REVERSE_UNRESOLVABLE;
+}
+lstrcpyn(hostname,m_cache[x].hostname, hostnameSize);
+return DNS_REVERSE_SUCCESS;
+}
+makesurethreadisrunning();
+return DNS_REVERSE_WAIT;
+}
+}
+// add to resolve list
+int oi=-1;
+for (x = 0; x < m_cache_size; x ++)
+{
+if (!m_cache[x].last_used)
+{
+oi=x;
+break;
+}
+if ((oi==-1 || m_cache[x].last_used < m_cache[oi].last_used) && m_cache[x].resolved)
+{
+oi=x;
+}
+}
+if (oi == -1)
+{
+return DNS_REVERSE_UNRESOLVABLE;
+}
+m_cache[oi].addr=addr;
+m_cache[oi].hostname[0]=0;
+m_cache[oi].resolved=false;
+m_cache[oi].mode=1;
+m_cache[oi].last_used=time(0);
+
+makesurethreadisrunning();
+return DNS_REVERSE_WAIT;
+#else
+return DNS_REVERSE_UNRESOLVABLE;
+#endif
+}
+*/
+
+void JNL_AsyncDNS::makesurethreadisrunning(void)
+{
+ if (m_thread_kill)
+ {
+#ifdef _WIN32
+ if (m_thread)
+ {
+ WaitForSingleObject(m_thread,INFINITE);
+ CloseHandle(m_thread);
+ }
+ DWORD id;
+ m_thread_kill=0;
+ m_thread=CreateThread(NULL,0,_threadfunc,(LPVOID)this,0,&id);
+ if (!m_thread)
+ {
+#else
+ if (m_thread)
+ {
+ void *p;
+ pthread_join(m_thread,&p);
+ }
+ m_thread_kill=0;
+ if (pthread_create(&m_thread,NULL,(void *(*) (void *))_threadfunc,(void*)this) != 0)
+ {
+#endif
+ m_thread_kill=1;
+ }
+ }
+}
+