}
+static int
+host_is_alive (hostinfo_t hi, time_t curtime)
+{
+ if (!hi)
+ return 0;
+ if (!hi->dead)
+ return 1;
+ if (!hi->died_at)
+ return 0; /* manually marked dead */
+ if (hi->died_at + RESURRECT_INTERVAL <= curtime
+ || hi->died_at > curtime)
+ {
+ hi->dead = 0;
+ log_info ("resurrected host '%s'", hi->name);
+ return 1;
+ }
+ return 0;
+}
+
/* Select a random host. Consult TABLE which indices into the global
hosttable. Returns index into TABLE or -1 if no host could be
selected. */
static int
select_random_host (int *table)
{
- int *tbl;
- size_t tblsize;
+ int *tbl = NULL;
+ size_t tblsize = 0;
int pidx, idx;
+ time_t curtime;
+ curtime = gnupg_get_time ();
/* We create a new table so that we randomly select only from
currently alive hosts. */
- for (idx=0, tblsize=0; (pidx = table[idx]) != -1; idx++)
- if (hosttable[pidx] && !hosttable[pidx]->dead)
- tblsize++;
+ for (idx=0; (pidx = table[idx]) != -1; idx++)
+ if (hosttable[pidx] && host_is_alive (hosttable[pidx], curtime))
+ {
+ tblsize++;
+ tbl = xtryrealloc(tbl, tblsize * sizeof *tbl);
+ if (!tbl)
+ return -1; /* memory allocation failed! */
+ tbl[tblsize-1] = pidx;
+ }
if (!tblsize)
return -1; /* No hosts. */
- tbl = xtrymalloc (tblsize * sizeof *tbl);
- if (!tbl)
- return -1;
- for (idx=0, tblsize=0; (pidx = table[idx]) != -1; idx++)
- if (hosttable[pidx] && !hosttable[pidx]->dead)
- tbl[tblsize++] = pidx;
-
if (tblsize == 1) /* Save a get_uint_nonce. */
pidx = tbl[0];
else
}
+/* Print a warninng iff Tor is not running but Tor has been requested.
+ * Also return true if it is not running. */
+static int
+tor_not_running_p (ctrl_t ctrl)
+{
+ assuan_fd_t sock;
+
+ if (!dirmngr_use_tor ())
+ return 0;
+
+ sock = assuan_sock_connect_byname (NULL, 0, 0, NULL, ASSUAN_SOCK_TOR);
+ if (sock != ASSUAN_INVALID_FD)
+ {
+ assuan_sock_close (sock);
+ return 0;
+ }
+
+ log_info ("(it seems Tor is not running)\n");
+ dirmngr_status (ctrl, "WARNING", "tor_not_running 0",
+ "Tor is enabled but the local Tor daemon"
+ " seems to be down", NULL);
+ return 1;
+}
+
+
/* Add the host AI under the NAME into the HOSTTABLE. If PORT is not
zero, it specifies which port to use to talk to the host. If NAME
specifies a pool (as indicated by IS_POOL), update the given
gpg_error_t err = 0;
hostinfo_t hi;
int idx;
+ time_t curtime;
*r_host = NULL;
if (r_httpflags)
if (err)
{
xfree (reftbl);
+ if (gpg_err_code (err) == GPG_ERR_ECONNREFUSED)
+ tor_not_running_p (ctrl);
return err;
}
{
if (ai->family != AF_INET && ai->family != AF_INET6)
continue;
+ if (opt.disable_ipv4 && ai->family == AF_INET)
+ continue;
dirmngr_tick (ctrl);
add_host (name, is_pool, ai, 0, reftbl, reftblsize, &refidx);
xfree (reftbl);
}
+ curtime = gnupg_get_time ();
hi = hosttable[idx];
if (hi->pool)
{
if (force_reselect)
hi->poolidx = -1;
else if (hi->poolidx >= 0 && hi->poolidx < hosttable_size
- && hosttable[hi->poolidx] && hosttable[hi->poolidx]->dead)
+ && hosttable[hi->poolidx] && !host_is_alive (hosttable[hi->poolidx], curtime))
hi->poolidx = -1;
/* Select a host if needed. */
{
for (ai = aibuf; ai; ai = ai->next)
{
- if (ai->family == AF_INET6 || ai->family == AF_INET)
+ if (ai->family == AF_INET6
+ || (!opt.disable_ipv4 && ai->family == AF_INET))
{
err = resolve_dns_addr (ai->addr, ai->addrlen, 0, &host);
if (!err)
free_dns_addrinfo (aibuf);
}
- if (hi->dead)
+ if (!host_is_alive (hi, curtime))
{
log_error ("host '%s' marked as dead\n", hi->name);
if (r_httphost)
{
gpg_error_t err = 0;
hostinfo_t hi, hi2;
- int idx, idx2, idx3, n;
+ int idx, idx2, idx3, n, is_alive;
+ time_t curtime;
if (!name || !*name || !strcmp (name, "localhost"))
return 0;
if (idx == -1)
return gpg_error (GPG_ERR_NOT_FOUND);
+ curtime = gnupg_get_time ();
hi = hosttable[idx];
- if (alive && hi->dead)
+ is_alive = host_is_alive (hi, curtime);
+ if (alive && !is_alive)
{
hi->dead = 0;
err = ks_printf_help (ctrl, "marking '%s' as alive", name);
}
- else if (!alive && !hi->dead)
+ else if (!alive && is_alive)
{
hi->dead = 1;
hi->died_at = 0; /* Manually set dead. */
hi2 = hosttable[n];
if (!hi2)
- ;
- else if (alive && hi2->dead)
+ continue;
+ is_alive = host_is_alive (hi2, curtime);
+ if (alive && !is_alive)
{
hi2->dead = 0;
err = ks_printf_help (ctrl, "marking '%s' as alive",
hi2->name);
}
- else if (!alive && !hi2->dead)
+ else if (!alive && is_alive)
{
hi2->dead = 1;
hi2->died_at = 0; /* Manually set dead. */
}
-/* Housekeeping function called from the housekeeping thread. It is
- used to mark dead hosts alive so that they may be tried again after
- some time. */
-void
-ks_hkp_housekeeping (time_t curtime)
-{
- int idx;
- hostinfo_t hi;
-
- for (idx=0; idx < hosttable_size; idx++)
- {
- hi = hosttable[idx];
- if (!hi)
- continue;
- if (!hi->dead)
- continue;
- if (!hi->died_at)
- continue; /* Do not resurrect manually shot hosts. */
- if (hi->died_at + RESURRECT_INTERVAL <= curtime
- || hi->died_at > curtime)
- {
- hi->dead = 0;
- log_info ("resurrected host '%s'", hi->name);
- }
- }
-}
-
-
/* Reload (SIGHUP) action for this module. We mark all host alive
* even those which have been manually shot. */
void
/* fixme: AUTH */ NULL,
(httpflags
|(opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
- |(opt.use_tor? HTTP_FLAG_FORCE_TOR:0)),
+ |(dirmngr_use_tor ()? HTTP_FLAG_FORCE_TOR:0)
+ |(opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)),
ctrl->http_proxy,
session,
NULL,
}
-/* Helper to evaluate the error code ERR form a send_request() call
+/* Helper to evaluate the error code ERR from a send_request() call
with REQUEST. The function returns true if the caller shall try
again. TRIES_LEFT points to a variable to track the number of
retries; this function decrements it and won't return true if it is
down to zero. */
static int
-handle_send_request_error (gpg_error_t err, const char *request,
+handle_send_request_error (ctrl_t ctrl, gpg_error_t err, const char *request,
unsigned int *tries_left)
{
int retry = 0;
switch (gpg_err_code (err))
{
case GPG_ERR_ECONNREFUSED:
- if (opt.use_tor)
- {
- assuan_fd_t sock;
-
- sock = assuan_sock_connect_byname (NULL, 0, 0, NULL, ASSUAN_SOCK_TOR);
- if (sock == ASSUAN_INVALID_FD)
- log_info ("(it seems Tor is not running)\n");
- else
- assuan_sock_close (sock);
- }
+ if (tor_not_running_p (ctrl))
+ break; /* A retry does not make sense. */
+ /* Okay: Tor is up or --use-tor is not used. */
/*FALLTHRU*/
case GPG_ERR_ENETUNREACH:
case GPG_ERR_ENETDOWN:
}
break;
+ case GPG_ERR_EACCES:
+ if (dirmngr_use_tor ())
+ {
+ log_info ("(Tor configuration problem)\n");
+ dirmngr_status (ctrl, "WARNING", "tor_config_problem 0",
+ "Please check that the \"SocksPort\" flag "
+ "\"IPv6Traffic\" is set in torrc", NULL);
+ }
+ break;
+
default:
break;
}
/* Send the request. */
err = send_request (ctrl, request, hostport, httphost, httpflags,
NULL, NULL, &fp, r_http_status);
- if (handle_send_request_error (err, request, &tries))
+ if (handle_send_request_error (ctrl, err, request, &tries))
{
reselect = 1;
goto again;
/* Send the request. */
err = send_request (ctrl, request, hostport, httphost, httpflags,
NULL, NULL, &fp, NULL);
- if (handle_send_request_error (err, request, &tries))
+ if (handle_send_request_error (ctrl, err, request, &tries))
{
reselect = 1;
goto again;
/* Send the request. */
err = send_request (ctrl, request, hostport, httphost, 0,
put_post_cb, &parm, &fp, NULL);
- if (handle_send_request_error (err, request, &tries))
+ if (handle_send_request_error (ctrl, err, request, &tries))
{
reselect = 1;
goto again;