Merge branch 'dns-changes' into master

* dns-changes:
  DNS changes, mostly work?
This commit is contained in:
2025-05-24 08:55:15 -04:00
3 changed files with 95 additions and 89 deletions

View File

@ -42,6 +42,9 @@
#include "../uicmd.hh"
#include <iostream>
#include <iomanip>
/* 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,

View File

@ -42,6 +42,10 @@
#include "list.h"
#include "IO/iowatch.hh"
#include <vector>
#include <string>
#include <memory>
/* 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();
}
/**

View File

@ -3,12 +3,21 @@
#include <netinet/in.h>
#include <vector>
#include <memory>
#include <optional>
#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);