mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
dirmngr: Refactor variable-sized array code.
* dirmngr/ks-engine-hkp.c (struct hostinfo_s): Add explicit length and size fields. (MAX_POOL_SIZE): New macro. (create_new_hostinfo): Initialize new fields. (host_in_pool_p): Adapt. (select_random_host): Likewise. (add_host): Likewise. Move the resizing logic here. (hostinfo_sort_pool): New function. (map_host): Simplify. Move the resizing logic away from here. (ks_hkp_mark_host): Adapt. (ks_hkp_print_hosttable): Likewise. -- The current code assumes that the pool array is only filled when the hostinfo object is created. This patch removes that limitation. GnuPG-bug-id: 3033 Signed-off-by: Justus Winter <justus@g10code.com>
This commit is contained in:
parent
794261c4bd
commit
fc4834d213
@ -74,9 +74,11 @@ struct hostinfo_s
|
|||||||
{
|
{
|
||||||
time_t lastfail; /* Time we tried to connect and failed. */
|
time_t lastfail; /* Time we tried to connect and failed. */
|
||||||
time_t lastused; /* Time of last use. */
|
time_t lastused; /* Time of last use. */
|
||||||
int *pool; /* A -1 terminated array with indices into
|
int *pool; /* An array with indices into HOSTTABLE or NULL
|
||||||
HOSTTABLE or NULL if NAME is not a pool
|
if NAME is not a pool name. */
|
||||||
name. */
|
size_t pool_len; /* Length of POOL. */
|
||||||
|
size_t pool_size; /* Allocated size of POOL. */
|
||||||
|
#define MAX_POOL_SIZE 128
|
||||||
int poolidx; /* Index into POOL with the used host. -1 if not set. */
|
int poolidx; /* Index into POOL with the used host. -1 if not set. */
|
||||||
unsigned int v4:1; /* Host supports AF_INET. */
|
unsigned int v4:1; /* Host supports AF_INET. */
|
||||||
unsigned int v6:1; /* Host supports AF_INET6. */
|
unsigned int v6:1; /* Host supports AF_INET6. */
|
||||||
@ -118,6 +120,8 @@ create_new_hostinfo (const char *name)
|
|||||||
return -1;
|
return -1;
|
||||||
strcpy (hi->name, name);
|
strcpy (hi->name, name);
|
||||||
hi->pool = NULL;
|
hi->pool = NULL;
|
||||||
|
hi->pool_len = 0;
|
||||||
|
hi->pool_size = 0;
|
||||||
hi->poolidx = -1;
|
hi->poolidx = -1;
|
||||||
hi->lastused = (time_t)(-1);
|
hi->lastused = (time_t)(-1);
|
||||||
hi->lastfail = (time_t)(-1);
|
hi->lastfail = (time_t)(-1);
|
||||||
@ -187,24 +191,24 @@ sort_hostpool (const void *xa, const void *xb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Return true if the host with the hosttable index TBLIDX is in POOL. */
|
/* Return true if the host with the hosttable index TBLIDX is in HI->pool. */
|
||||||
static int
|
static int
|
||||||
host_in_pool_p (int *pool, int tblidx)
|
host_in_pool_p (hostinfo_t hi, int tblidx)
|
||||||
{
|
{
|
||||||
int i, pidx;
|
int i, pidx;
|
||||||
|
|
||||||
for (i=0; (pidx = pool[i]) != -1; i++)
|
for (i = 0; i < hi->pool_len && (pidx = hi->pool[i]) != -1; i++)
|
||||||
if (pidx == tblidx && hosttable[pidx])
|
if (pidx == tblidx && hosttable[pidx])
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Select a random host. Consult TABLE which indices into the global
|
/* Select a random host. Consult HI->pool which indices into the global
|
||||||
hosttable. Returns index into TABLE or -1 if no host could be
|
hosttable. Returns index into HI->pool or -1 if no host could be
|
||||||
selected. */
|
selected. */
|
||||||
static int
|
static int
|
||||||
select_random_host (int *table)
|
select_random_host (hostinfo_t hi)
|
||||||
{
|
{
|
||||||
int *tbl;
|
int *tbl;
|
||||||
size_t tblsize;
|
size_t tblsize;
|
||||||
@ -212,7 +216,9 @@ select_random_host (int *table)
|
|||||||
|
|
||||||
/* We create a new table so that we randomly select only from
|
/* We create a new table so that we randomly select only from
|
||||||
currently alive hosts. */
|
currently alive hosts. */
|
||||||
for (idx=0, tblsize=0; (pidx = table[idx]) != -1; idx++)
|
for (idx = 0, tblsize = 0;
|
||||||
|
idx < hi->pool_len && (pidx = hi->pool[idx]) != -1;
|
||||||
|
idx++)
|
||||||
if (hosttable[pidx] && !hosttable[pidx]->dead)
|
if (hosttable[pidx] && !hosttable[pidx]->dead)
|
||||||
tblsize++;
|
tblsize++;
|
||||||
if (!tblsize)
|
if (!tblsize)
|
||||||
@ -221,7 +227,9 @@ select_random_host (int *table)
|
|||||||
tbl = xtrymalloc (tblsize * sizeof *tbl);
|
tbl = xtrymalloc (tblsize * sizeof *tbl);
|
||||||
if (!tbl)
|
if (!tbl)
|
||||||
return -1;
|
return -1;
|
||||||
for (idx=0, tblsize=0; (pidx = table[idx]) != -1; idx++)
|
for (idx = 0, tblsize = 0;
|
||||||
|
idx < hi->pool_len && (pidx = hi->pool[idx]) != -1;
|
||||||
|
idx++)
|
||||||
if (hosttable[pidx] && !hosttable[pidx]->dead)
|
if (hosttable[pidx] && !hosttable[pidx]->dead)
|
||||||
tbl[tblsize++] = pidx;
|
tbl[tblsize++] = pidx;
|
||||||
|
|
||||||
@ -286,15 +294,16 @@ tor_not_running_p (ctrl_t ctrl)
|
|||||||
reference table accordingly. */
|
reference table accordingly. */
|
||||||
static void
|
static void
|
||||||
add_host (const char *name, int is_pool,
|
add_host (const char *name, int is_pool,
|
||||||
const dns_addrinfo_t ai, unsigned short port,
|
const dns_addrinfo_t ai, unsigned short port)
|
||||||
int *reftbl, size_t reftblsize, int *refidx)
|
|
||||||
{
|
{
|
||||||
gpg_error_t tmperr;
|
gpg_error_t tmperr;
|
||||||
char *tmphost;
|
char *tmphost;
|
||||||
int idx, tmpidx;
|
int idx, tmpidx;
|
||||||
|
hostinfo_t host;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
idx = find_hostinfo (name);
|
idx = find_hostinfo (name);
|
||||||
|
host = hosttable[idx];
|
||||||
|
|
||||||
if (is_pool)
|
if (is_pool)
|
||||||
{
|
{
|
||||||
@ -325,7 +334,7 @@ add_host (const char *name, int is_pool,
|
|||||||
log_info ("resolve_dns_addr failed while checking '%s': %s\n",
|
log_info ("resolve_dns_addr failed while checking '%s': %s\n",
|
||||||
name, gpg_strerror (tmperr));
|
name, gpg_strerror (tmperr));
|
||||||
}
|
}
|
||||||
else if ((*refidx) + 1 >= reftblsize)
|
else if (host->pool_len + 1 >= MAX_POOL_SIZE)
|
||||||
{
|
{
|
||||||
log_error ("resolve_dns_addr for '%s': '%s'"
|
log_error ("resolve_dns_addr for '%s': '%s'"
|
||||||
" [index table full - ignored]\n", name, tmphost);
|
" [index table full - ignored]\n", name, tmphost);
|
||||||
@ -365,17 +374,54 @@ add_host (const char *name, int is_pool,
|
|||||||
else
|
else
|
||||||
BUG ();
|
BUG ();
|
||||||
|
|
||||||
for (i=0; i < *refidx; i++)
|
/* If we updated the main entry, we're done. */
|
||||||
if (reftbl[i] == tmpidx)
|
if (idx == tmpidx)
|
||||||
break;
|
goto leave;
|
||||||
if (!(i < *refidx) && tmpidx != idx)
|
|
||||||
reftbl[(*refidx)++] = tmpidx;
|
/* If we updated an existing entry, we're done. */
|
||||||
|
for (i = 0; i < host->pool_len; i++)
|
||||||
|
if (host->pool[i] == tmpidx)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
/* Otherwise, we need to add it to the pool. Check if there
|
||||||
|
is space. */
|
||||||
|
if (host->pool_len + 1 > host->pool_size)
|
||||||
|
{
|
||||||
|
int *new_pool;
|
||||||
|
size_t new_size;
|
||||||
|
|
||||||
|
if (host->pool_size == 0)
|
||||||
|
new_size = 4;
|
||||||
|
else
|
||||||
|
new_size = host->pool_size * 2;
|
||||||
|
|
||||||
|
new_pool = xtryrealloc (host->pool,
|
||||||
|
new_size * sizeof *new_pool);
|
||||||
|
|
||||||
|
if (new_pool == NULL)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
host->pool = new_pool;
|
||||||
|
host->pool_size = new_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finally, add it. */
|
||||||
|
log_assert (host->pool_len < host->pool_size);
|
||||||
|
host->pool[host->pool_len++] = tmpidx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
leave:
|
||||||
xfree (tmphost);
|
xfree (tmphost);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Sort the pool of the given hostinfo HI. */
|
||||||
|
static void
|
||||||
|
hostinfo_sort_pool (hostinfo_t hi)
|
||||||
|
{
|
||||||
|
qsort (hi->pool, hi->pool_len, sizeof *hi->pool, sort_hostpool);
|
||||||
|
}
|
||||||
|
|
||||||
/* Map the host name NAME to the actual to be used host name. This
|
/* Map the host name NAME to the actual to be used host name. This
|
||||||
* allows us to manage round robin DNS names. We use our own strategy
|
* allows us to manage round robin DNS names. We use our own strategy
|
||||||
* to choose one of the hosts. For example we skip those hosts which
|
* to choose one of the hosts. For example we skip those hosts which
|
||||||
@ -427,25 +473,15 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
|
|||||||
{
|
{
|
||||||
/* We never saw this host. Allocate a new entry. */
|
/* We never saw this host. Allocate a new entry. */
|
||||||
dns_addrinfo_t aibuf, ai;
|
dns_addrinfo_t aibuf, ai;
|
||||||
int *reftbl;
|
|
||||||
size_t reftblsize;
|
|
||||||
int refidx;
|
|
||||||
int is_pool = 0;
|
int is_pool = 0;
|
||||||
char *cname;
|
char *cname;
|
||||||
struct srventry *srvs;
|
struct srventry *srvs;
|
||||||
unsigned int srvscount;
|
unsigned int srvscount;
|
||||||
|
|
||||||
reftblsize = 100;
|
|
||||||
reftbl = xtrymalloc (reftblsize * sizeof *reftbl);
|
|
||||||
if (!reftbl)
|
|
||||||
return gpg_error_from_syserror ();
|
|
||||||
refidx = 0;
|
|
||||||
|
|
||||||
idx = create_new_hostinfo (name);
|
idx = create_new_hostinfo (name);
|
||||||
if (idx == -1)
|
if (idx == -1)
|
||||||
{
|
{
|
||||||
err = gpg_error_from_syserror ();
|
err = gpg_error_from_syserror ();
|
||||||
xfree (reftbl);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
hi = hosttable[idx];
|
hi = hosttable[idx];
|
||||||
@ -456,7 +492,6 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
|
|||||||
err = get_dns_srv (name, srvtag, NULL, &srvs, &srvscount);
|
err = get_dns_srv (name, srvtag, NULL, &srvs, &srvscount);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
xfree (reftbl);
|
|
||||||
if (gpg_err_code (err) == GPG_ERR_ECONNREFUSED)
|
if (gpg_err_code (err) == GPG_ERR_ECONNREFUSED)
|
||||||
tor_not_running_p (ctrl);
|
tor_not_running_p (ctrl);
|
||||||
return err;
|
return err;
|
||||||
@ -475,8 +510,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
|
|||||||
if (err)
|
if (err)
|
||||||
continue;
|
continue;
|
||||||
dirmngr_tick (ctrl);
|
dirmngr_tick (ctrl);
|
||||||
add_host (name, is_pool, ai, srvs[i].port,
|
add_host (name, is_pool, ai, srvs[i].port);
|
||||||
reftbl, reftblsize, &refidx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
xfree (srvs);
|
xfree (srvs);
|
||||||
@ -516,29 +550,12 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
|
|||||||
continue;
|
continue;
|
||||||
dirmngr_tick (ctrl);
|
dirmngr_tick (ctrl);
|
||||||
|
|
||||||
add_host (name, is_pool, ai, 0, reftbl, reftblsize, &refidx);
|
add_host (name, is_pool, ai, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reftbl[refidx] = -1;
|
|
||||||
xfree (cname);
|
xfree (cname);
|
||||||
free_dns_addrinfo (aibuf);
|
free_dns_addrinfo (aibuf);
|
||||||
|
hostinfo_sort_pool (hi);
|
||||||
if (refidx && is_pool)
|
|
||||||
{
|
|
||||||
assert (!hi->pool);
|
|
||||||
hi->pool = xtryrealloc (reftbl, (refidx+1) * sizeof *reftbl);
|
|
||||||
if (!hi->pool)
|
|
||||||
{
|
|
||||||
err = gpg_error_from_syserror ();
|
|
||||||
log_error ("shrinking index table in map_host failed: %s\n",
|
|
||||||
gpg_strerror (err));
|
|
||||||
xfree (reftbl);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
qsort (hi->pool, refidx, sizeof *reftbl, sort_hostpool);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
xfree (reftbl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hi = hosttable[idx];
|
hi = hosttable[idx];
|
||||||
@ -563,7 +580,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
|
|||||||
/* Select a host if needed. */
|
/* Select a host if needed. */
|
||||||
if (hi->poolidx == -1)
|
if (hi->poolidx == -1)
|
||||||
{
|
{
|
||||||
hi->poolidx = select_random_host (hi->pool);
|
hi->poolidx = select_random_host (hi);
|
||||||
if (hi->poolidx == -1)
|
if (hi->poolidx == -1)
|
||||||
{
|
{
|
||||||
log_error ("no alive host found in pool '%s'\n", name);
|
log_error ("no alive host found in pool '%s'\n", name);
|
||||||
@ -740,7 +757,9 @@ ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
|
|||||||
/* If the host is a pool mark all member hosts. */
|
/* If the host is a pool mark all member hosts. */
|
||||||
if (!err && hi->pool)
|
if (!err && hi->pool)
|
||||||
{
|
{
|
||||||
for (idx2=0; !err && (n=hi->pool[idx2]) != -1; idx2++)
|
for (idx2 = 0;
|
||||||
|
!err && idx2 < hi->pool_len && (n = hi->pool[idx2]) != -1;
|
||||||
|
idx2++)
|
||||||
{
|
{
|
||||||
assert (n >= 0 && n < hosttable_size);
|
assert (n >= 0 && n < hosttable_size);
|
||||||
|
|
||||||
@ -753,7 +772,7 @@ ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
|
|||||||
if (hosttable[idx3]
|
if (hosttable[idx3]
|
||||||
&& hosttable[idx3]->pool
|
&& hosttable[idx3]->pool
|
||||||
&& idx3 != idx
|
&& idx3 != idx
|
||||||
&& host_in_pool_p (hosttable[idx3]->pool, n))
|
&& host_in_pool_p (hosttable[idx3], n))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (idx3 < hosttable_size)
|
if (idx3 < hosttable_size)
|
||||||
@ -903,7 +922,7 @@ ks_hkp_print_hosttable (ctrl_t ctrl)
|
|||||||
{
|
{
|
||||||
init_membuf (&mb, 256);
|
init_membuf (&mb, 256);
|
||||||
put_membuf_printf (&mb, " . -->");
|
put_membuf_printf (&mb, " . -->");
|
||||||
for (idx2=0; hi->pool[idx2] != -1; idx2++)
|
for (idx2 = 0; idx2 < hi->pool_len && hi->pool[idx2] != -1; idx2++)
|
||||||
{
|
{
|
||||||
put_membuf_printf (&mb, " %d", hi->pool[idx2]);
|
put_membuf_printf (&mb, " %d", hi->pool[idx2]);
|
||||||
if (hi->poolidx == hi->pool[idx2])
|
if (hi->poolidx == hi->pool[idx2])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user