From 9412da8e850b4fd41c15156a2494380a0a02440e434db1dd6fa374debca40a2a Mon Sep 17 00:00:00 2001 From: ADAM David Alan Martin Date: Mon, 12 May 2025 23:43:14 -0400 Subject: [PATCH] DNS changes, mostly work? --- src/IO/http.cc | 29 +++++++--- src/dns.cc | 140 ++++++++++++++++++++++--------------------------- src/dns.hh | 15 ++++-- 3 files changed, 95 insertions(+), 89 deletions(-) diff --git a/src/IO/http.cc b/src/IO/http.cc index 159b394..ab60334 100644 --- a/src/IO/http.cc +++ b/src/IO/http.cc @@ -42,6 +42,9 @@ #include "../uicmd.hh" +#include +#include + /* Used to send a message to the bw's status bar */ #define MSG_BW(web, root, ...) \ D_STMT_START { \ @@ -58,18 +61,18 @@ static const int HTTP_SOCKET_TLS = 0x8; static const int HTTP_SOCKET_IOWATCH_ACTIVE = 0x10; /* 'web' is just a reference (no need to deallocate it here). */ -typedef struct { +struct SocketData_t { int SockFD; uint_t flags; DilloWeb *web; /* reference to client's web structure */ DilloUrl *url; - Dlist *addr_list; /* Holds the DNS answer */ + std::vector< std::shared_ptr< DilloHost > > addr_list; /* Holds the DNS answer */ int addr_list_idx; ChainLink *Info; /* Used for CCC asynchronous operations */ char *connected_to; /* Used for per-server connection limit */ uint_t connect_port; Dstr *https_proxy_reply; -} SocketData_t; +}; /* Data structures and functions to queue sockets that need to be * delayed due to the per host connection limit. @@ -569,7 +572,9 @@ static void Http_connect_socket(ChainLink *Info) DilloHost *dh; SocketData_t *S = reinterpret_cast< SocketData_t * >( a_Klist_get_data(ValidSocks, VOIDP2INT(Info->LocalKey)) ); - for (; (dh = reinterpret_cast< DilloHost * >( dList_nth_data(S->addr_list, S->addr_list_idx) )); + std::cerr << "I see " << S->addr_list.size() << " addresses to try." << std::endl; + std::cerr << "I see " << S->addr_list_idx << " as the starting index." << std::endl; + for (; (S->addr_list_idx < S->addr_list.size() and ( dh = S->addr_list.at( S->addr_list_idx ).get() ) ); S->addr_list_idx++) { #ifdef ENABLE_IPV6 struct sockaddr_in6 name; @@ -578,6 +583,14 @@ static void Http_connect_socket(ChainLink *Info) #endif socklen_t socket_len = 0; + std::cerr << "Going to try "; + for( int ii= 0; ii < dh->alen; ++ii ) + { + std::cerr << std::hex << std::setw( 2 ) << std::setfill( '0' ) << (int) ( dh->data[ ii ] & 0xFF ); + if( ii % 2 and ii != ( dh->alen - 1 ) ) std::cerr << ":"; + } + std::cerr << std::endl; + if (S->addr_list_idx > 0 && S->SockFD >= 0) { /* clean up the previous one that failed */ Http_fd_map_remove_entry(S->SockFD); @@ -654,7 +667,7 @@ static void Http_connect_socket(ChainLink *Info) } } /* for */ - if (S->addr_list_idx >= dList_length(S->addr_list) ) { + if (S->addr_list_idx >= S->addr_list.size() ) { MSG("Http_connect_socket ran out of IP addrs to try.\n"); a_Http_connect_done(S->SockFD, FALSE); } @@ -737,7 +750,7 @@ static char *Http_get_connect_str(const DilloUrl *url) * Continue connecting the socket, or abort upon error condition. * S->web is checked to assert the operation wasn't aborted while waiting. */ -static void Http_dns_cb(int Status, Dlist *addr_list, void *data) +static void Http_dns_cb(int Status, std::optional< std::vector< std::shared_ptr< DilloHost > > > &addr_list, void *data) { int SKey = VOIDP2INT(data); bool_t clean_up = TRUE; @@ -749,10 +762,10 @@ static void Http_dns_cb(int Status, Dlist *addr_list, void *data) const char *host = URL_HOST((S->flags & HTTP_SOCKET_USE_PROXY) ? HTTP_Proxy : S->url); if (a_Web_valid(S->web)) { - if (Status == 0 && addr_list) { + if (Status == 0 && addr_list.has_value()) { /* Successful DNS answer; save the IP */ - S->addr_list = addr_list; + S->addr_list = addr_list.value(); S->addr_list_idx = 0; clean_up = FALSE; srv = Http_server_get(host, S->connect_port, diff --git a/src/dns.cc b/src/dns.cc index c73d882..10d2123 100644 --- a/src/dns.cc +++ b/src/dns.cc @@ -42,6 +42,10 @@ #include "list.h" #include "IO/iowatch.hh" +#include +#include +#include + /* Maximum dns resolving threads */ #ifdef D_DNS_THREADED @@ -56,28 +60,28 @@ typedef enum { DNS_SERVER_RESOLVED, } DnsServerState_t; -typedef struct { +struct DnsServer { int channel; /**< Index of this channel [0 based] */ DnsServerState_t state; - Dlist *addr_list; /**< IP address */ + HostList addr_list; /**< IP address */ char *hostname; /**< Address to resolve */ int status; /**< errno code for resolving function */ #ifdef D_DNS_THREADED pthread_t th1; /**< Thread id */ #endif -} DnsServer; +}; -typedef struct { - char *hostname; /**< host name for cache */ - Dlist *addr_list; /**< addresses of host */ -} GDnsCache; +struct GDnsCache { + std::string hostname; /**< host name for cache */ + HostList addr_list; /**< addresses of host */ +}; -typedef struct { +struct GDnsQueue { int channel; /**< -2 if waiting, otherwise index to dns_server[] */ - char *hostname; /**< The one we're resolving */ + std::string hostname; /**< The one we're resolving */ DnsCallback_t cb_func; /**< callback function */ void *cb_data; /**< extra data for the callback function */ -} GDnsQueue; +}; /* @@ -90,10 +94,8 @@ static void Dns_timeout_client(int fd, void *data); */ static DnsServer dns_server[D_DNS_MAX_SERVERS]; static int num_servers; -static GDnsCache *dns_cache; -static int dns_cache_size, dns_cache_size_max; -static GDnsQueue *dns_queue; -static int dns_queue_size, dns_queue_size_max; +static std::vector< GDnsCache > dns_cache; +static std::vector< GDnsQueue > dns_queue; static int dns_notify_pipe[2]; @@ -103,12 +105,12 @@ static int dns_notify_pipe[2]; static void Dns_queue_add(int channel, const char *hostname, DnsCallback_t cb_func, void *cb_data) { - a_List_add(dns_queue, dns_queue_size, dns_queue_size_max, GDnsQueue); - dns_queue[dns_queue_size].channel = channel; - dns_queue[dns_queue_size].hostname = dStrdup(hostname); - dns_queue[dns_queue_size].cb_func = cb_func; - dns_queue[dns_queue_size].cb_data = cb_data; - dns_queue_size++; + GDnsQueue entry; + entry.channel = channel; + entry.hostname = hostname; + entry.cb_func = cb_func; + entry.cb_data = cb_data; + dns_queue.push_back( entry ); } /** @@ -119,8 +121,8 @@ static int Dns_queue_find(const char *hostname) { int i; - for (i = 0; i < dns_queue_size; i++) - if (!dStrAsciiCasecmp(hostname, dns_queue[i].hostname)) + for (i = 0; i < dns_queue.size(); i++) + if (!dStrAsciiCasecmp(hostname, dns_queue[i].hostname.c_str())) return i; return -1; @@ -131,17 +133,10 @@ static int Dns_queue_find(const char *hostname) */ static void Dns_queue_remove(int index) { - int i; - _MSG("Dns_queue_remove: deleting client [%d] [queue_size=%d]\n", - index, dns_queue_size); + index, dns_queue.size()); - if (index < dns_queue_size) { - dFree(dns_queue[index].hostname); - --dns_queue_size; /* you'll find out why ;-) */ - for (i = index; i < dns_queue_size; i++) - dns_queue[i] = dns_queue[i + 1]; - } + if (index < dns_queue.size()) dns_queue.erase( begin( dns_queue ) + index ); } /* @@ -161,13 +156,13 @@ void Dns_queue_print() /** * Add an IP/hostname pair to Dns-cache */ -static void Dns_cache_add(char *hostname, Dlist *addr_list) +static void Dns_cache_add(char *hostname, std::optional< std::vector< std::shared_ptr< DilloHost > > > addr_list) { - a_List_add(dns_cache, dns_cache_size, dns_cache_size_max, GDnsCache); - dns_cache[dns_cache_size].hostname = dStrdup(hostname); - dns_cache[dns_cache_size].addr_list = addr_list; - ++dns_cache_size; - _MSG("Cache objects: %d\n", dns_cache_size); + GDnsCache entry; + entry.hostname = hostname; + entry.addr_list = std::move( addr_list ); + dns_cache.push_back( entry ); + _MSG("Cache objects: %d\n", dns_cache.size()); } @@ -184,13 +179,13 @@ void a_Dns_init(void) MSG("dillo_dns_init: Here we go! (not threaded)\n"); #endif - dns_queue_size = 0; - dns_queue_size_max = 16; - dns_queue = dNew(GDnsQueue, dns_queue_size_max); + //dns_queue_size = 0; + //dns_queue_size_max = 16; + //dns_queue = dNew(GDnsQueue, dns_queue_size_max); - dns_cache_size = 0; - dns_cache_size_max = 16; - dns_cache = dNew(GDnsCache, dns_cache_size_max); + //dns_cache_size = 0; + //dns_cache_size_max = 16; + //dns_cache = dNew(GDnsCache, dns_cache_size_max); num_servers = D_DNS_MAX_SERVERS; @@ -203,7 +198,7 @@ void a_Dns_init(void) for (i = 0; i < num_servers; ++i) { dns_server[i].channel = i; dns_server[i].state = DNS_SERVER_IDLE; - dns_server[i].addr_list = NULL; + //dns_server[i].addr_list = NULL; dns_server[i].hostname = NULL; dns_server[i].status = 0; #ifdef D_DNS_THREADED @@ -216,10 +211,10 @@ void a_Dns_init(void) * Allocate a host structure and add it to the list */ -static void Dns_note_hosts(Dlist *list, struct addrinfo *res0) +static void Dns_note_hosts(std::vector< std::shared_ptr< DilloHost > > &list, struct addrinfo *res0) { struct addrinfo *res; - DilloHost *dh; + std::unique_ptr< DilloHost > dh; for (res = res0; res; res = res->ai_next) { @@ -230,14 +225,14 @@ static void Dns_note_hosts(Dlist *list, struct addrinfo *res0) continue; } - dh = dNew0(DilloHost, 1); + dh = std::make_unique< DilloHost >(); dh->af = AF_INET; in_addr = (struct sockaddr_in*) res->ai_addr; dh->alen = sizeof (struct in_addr); memcpy(&dh->data[0], &in_addr->sin_addr.s_addr, dh->alen); - dList_append(list, dh); + list.push_back( std::move( dh ) ); #ifdef ENABLE_IPV6 } else if (res->ai_family == AF_INET6) { struct sockaddr_in6 *in6_addr; @@ -246,14 +241,14 @@ static void Dns_note_hosts(Dlist *list, struct addrinfo *res0) continue; } - dh = dNew0(DilloHost, 1); + dh = std::make_unique< DilloHost >(); dh->af = AF_INET6; in6_addr = (struct sockaddr_in6*) res->ai_addr; dh->alen = sizeof (struct in6_addr); memcpy(&dh->data[0], &in6_addr->sin6_addr.s6_addr, dh->alen); - dList_append(list, dh); + list.push_back( std::move( dh ) ); #endif } } @@ -267,7 +262,7 @@ static void *Dns_server(void *data) int channel = VOIDP2INT(data); struct addrinfo hints, *res0; int error; - Dlist *hosts; + std::vector< std::shared_ptr< DilloHost > > hosts; size_t length, i; char addr_string[40]; @@ -279,8 +274,6 @@ static void *Dns_server(void *data) #endif hints.ai_socktype = SOCK_STREAM; - hosts = dList_new(2); - _MSG("Dns_server: starting...\n ch: %d host: %s\n", channel, dns_server[channel].hostname); @@ -295,19 +288,18 @@ static void *Dns_server(void *data) freeaddrinfo(res0); } - if (dList_length(hosts) > 0) { + if (hosts.size() > 0) { dns_server[channel].status = 0; } else { - dList_free(hosts); - hosts = NULL; + hosts.clear(); // Superfluous? -- ADAM } /* tell our findings */ MSG("Dns_server [%d]: %s is", channel, dns_server[channel].hostname); - if ((length = dList_length(hosts))) { + if ((length = hosts.size())) { for (i = 0; i < length; i++) { - a_Dns_dillohost_to_string(reinterpret_cast< DilloHost * >( dList_nth_data(hosts, i) ), + a_Dns_dillohost_to_string(hosts.at( i ).get(), addr_string, sizeof(addr_string)); MSG(" %s", addr_string); } @@ -366,11 +358,11 @@ void a_Dns_resolve(const char *hostname, DnsCallback_t cb_func, void *cb_data) return; /* check for cache hit. */ - for (i = 0; i < dns_cache_size; i++) - if (!dStrAsciiCasecmp(hostname, dns_cache[i].hostname)) + for (i = 0; i < dns_cache.size(); i++) + if (!dStrAsciiCasecmp(hostname, dns_cache[i].hostname.c_str())) break; - if (i < dns_cache_size) { + if (i < dns_cache.size()) { /* already resolved, call the Callback immediately. */ cb_func(0, dns_cache[i].addr_list, cb_data); @@ -404,7 +396,7 @@ static void Dns_serve_channel(int channel) int i; DnsServer *srv = &dns_server[channel]; - for (i = 0; i < dns_queue_size; i++) { + for (i = 0; i < dns_queue.size(); i++) { if (dns_queue[i].channel == channel) { dns_queue[i].cb_func(srv->status, srv->addr_list, dns_queue[i].cb_data); @@ -424,20 +416,20 @@ static void Dns_assign_channels(void) for (ch = 0; ch < num_servers; ++ch) { if (dns_server[ch].state == DNS_SERVER_IDLE) { /* Find the next query in the queue (we're a FIFO) */ - for (i = 0; i < dns_queue_size; i++) + for (i = 0; i < dns_queue.size(); i++) if (dns_queue[i].channel == -2) break; - if (i < dns_queue_size) { + if (i < dns_queue.size()) { /* assign this channel to every queued request * with the same hostname*/ - for (j = i; j < dns_queue_size; j++) + for (j = i; j < dns_queue.size(); j++) if (dns_queue[j].channel == -2 && - !dStrAsciiCasecmp(dns_queue[j].hostname, - dns_queue[i].hostname)) { + !dStrAsciiCasecmp(dns_queue[j].hostname.c_str(), + dns_queue[i].hostname.c_str())) { dns_queue[j].channel = ch; } - Dns_server_req(ch, dns_queue[i].hostname); + Dns_server_req(ch, dns_queue[i].hostname.c_str()); } else return; } @@ -459,7 +451,7 @@ static void Dns_timeout_client(int fd, void *data) DnsServer *srv = &dns_server[i]; if (srv->state == DNS_SERVER_RESOLVED) { - if (srv->addr_list != NULL) { + if (srv->addr_list.has_value()) { /* DNS succeeded, let's cache it */ Dns_cache_add(srv->hostname, srv->addr_list); } @@ -479,18 +471,10 @@ static void Dns_timeout_client(int fd, void *data) */ void a_Dns_freeall(void) { - int i, j; - - for ( i = 0; i < dns_cache_size; ++i ){ - dFree(dns_cache[i].hostname); - for ( j = 0; j < dList_length(dns_cache[i].addr_list); ++j) - dFree(dList_nth_data(dns_cache[i].addr_list, j)); - dList_free(dns_cache[i].addr_list); - } a_IOwatch_remove_fd(dns_notify_pipe[0], DIO_READ); dClose(dns_notify_pipe[0]); dClose(dns_notify_pipe[1]); - dFree(dns_cache); + dns_cache.clear(); } /** diff --git a/src/dns.hh b/src/dns.hh index 73dc151..d82085e 100644 --- a/src/dns.hh +++ b/src/dns.hh @@ -3,12 +3,21 @@ #include +#include +#include +#include + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -typedef void (*DnsCallback_t)(int status, Dlist *addr_list, void *data); +struct DilloHost; + +using HostList= std::optional< std::vector< std::shared_ptr< DilloHost > > >; + + +typedef void (*DnsCallback_t)(int status, HostList &addr_list, void *data); void a_Dns_init (void); void a_Dns_freeall(void); @@ -20,11 +29,11 @@ void a_Dns_resolve(const char *hostname, DnsCallback_t cb_func, void *cb_data); # define DILLO_ADDR_MAX sizeof(struct in_addr) #endif -typedef struct { +struct DilloHost { int af; int alen; char data[DILLO_ADDR_MAX]; -} DilloHost; +}; void a_Dns_dillohost_to_string(DilloHost *host, char *dst, size_t size);