/*
This file is part of GNUnet.
- Copyright (C) 2009-2016 GNUnet e.V.
+ Copyright (C) 2009-2018 GNUnet e.V.
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
+ SPDX-License-Identifier: AGPL3.0-or-later
*/
/**
*/
static struct GNUNET_RESOLVER_RequestHandle *req_tail;
+/**
+ * ID of the last request we sent to the service
+ */
+static uint32_t last_request_id;
+
/**
* How long should we wait to reconnect?
*/
*/
int af;
+ /**
+ * Identifies the request. The response will contain this id.
+ */
+ uint32_t id;
+
/**
* Has this request been transmitted to the service?
* #GNUNET_YES if transmitted
struct sockaddr_in v4;
struct sockaddr_in6 v6;
+ if (GNUNET_OK ==
+ GNUNET_CONFIGURATION_have_value (resolver_cfg,
+ "resolver",
+ "UNIXPATH"))
+ return GNUNET_OK;
memset (&v4, 0, sizeof (v4));
v4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
v4.sin_family = AF_INET;
for (unsigned int i = 0;
NULL != loopback[i];
i++)
- if (0 == strcasecmp (loopback[i], hostname))
+ if (0 == strcasecmp (loopback[i],
+ hostname))
{
GNUNET_free (hostname);
return GNUNET_OK;
static void
shutdown_task (void *cls)
{
+ (void) cls;
s_task = NULL;
GNUNET_RESOLVER_disconnect ();
backoff = GNUNET_TIME_UNIT_MILLISECONDS;
mq_error_handler (void *cls,
enum GNUNET_MQ_Error error)
{
+ (void) cls;
GNUNET_MQ_destroy (mq);
mq = NULL;
LOG (GNUNET_ERROR_TYPE_DEBUG,
- "MQ error, reconnecting\n");
+ "MQ error %d, reconnecting\n",
+ error);
reconnect ();
}
{
/* nothing to do, release socket really soon if there is nothing
* else happening... */
- s_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
- &shutdown_task,
- NULL);
+ if (NULL == s_task)
+ s_task =
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
+ &shutdown_task,
+ NULL);
return;
}
if (GNUNET_NO != rh->was_transmitted)
GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST);
msg->direction = htonl (rh->direction);
msg->af = htonl (rh->af);
+ msg->client_id = rh->id;
GNUNET_memcpy (&msg[1],
&rh[1],
rh->data_len);
LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Transmitting DNS resolution request to DNS service\n");
+ "Transmitting DNS resolution request (ID %u) to DNS service\n",
+ rh->id);
GNUNET_MQ_send (mq,
env);
rh->was_transmitted = GNUNET_YES;
*/
static int
check_response (void *cls,
- const struct GNUNET_MessageHeader *msg)
+ const struct GNUNET_RESOLVER_ResponseMessage *msg)
{
+ (void) cls;
+ (void) msg;
+
/* implemented in #handle_response() for now */
return GNUNET_OK;
}
*/
static void
handle_response (void *cls,
- const struct GNUNET_MessageHeader *msg)
+ const struct GNUNET_RESOLVER_ResponseMessage *msg)
{
struct GNUNET_RESOLVER_RequestHandle *rh = req_head;
uint16_t size;
char *nret;
+ uint32_t client_request_id = msg->client_id;
+
+ for (; rh != NULL; rh = rh->next)
+ {
+ if (rh->id == client_request_id)
+ break;
+ }
- size = ntohs (msg->size);
- if (size == sizeof (struct GNUNET_MessageHeader))
+ (void) cls;
+ if (NULL == rh)
+ {
+ /* Resolver service sent extra replies to query (after terminator)? Bad! */
+ GNUNET_break (0);
+ GNUNET_MQ_destroy (mq);
+ mq = NULL;
+ reconnect ();
+ return;
+ }
+ size = ntohs (msg->header.size);
+ if (size == sizeof (struct GNUNET_RESOLVER_ResponseMessage))
{
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Received empty response from DNS service\n");
GNUNET_free (nret);
}
/* finally, make termination call */
- rh->name_callback (rh->cls,
- NULL);
+ if (GNUNET_SYSERR != rh->was_transmitted)
+ rh->name_callback (rh->cls,
+ NULL);
}
- if (NULL != rh->addr_callback)
- rh->addr_callback (rh->cls,
- NULL,
- 0);
+ if ( (NULL != rh->addr_callback) &&
+ (GNUNET_SYSERR != rh->was_transmitted) )
+ rh->addr_callback (rh->cls,
+ NULL,
+ 0);
}
rh->was_transmitted = GNUNET_NO;
GNUNET_RESOLVER_request_cancel (rh);
const char *hostname;
hostname = (const char *) &msg[1];
- if (hostname[size - sizeof (struct GNUNET_MessageHeader) - 1] != '\0')
+ if (hostname[size - sizeof (struct GNUNET_RESOLVER_ResponseMessage) - 1] != '\0')
{
GNUNET_break (0);
if (GNUNET_SYSERR != rh->was_transmitted)
size_t ip_len;
ip = &msg[1];
- ip_len = size - sizeof (struct GNUNET_MessageHeader);
+ ip_len = size - sizeof (struct GNUNET_RESOLVER_ResponseMessage);
if (ip_len == sizeof (struct in_addr))
{
memset (&v4, 0, sizeof (v4));
(const struct sockaddr *) &v4,
sizeof (v4));
if ( (rh->af == AF_UNSPEC) &&
+ (GNUNET_SYSERR != rh->was_transmitted) &&
(1 == inet_pton (AF_INET6,
hostname,
&v6.sin6_addr)) )
(const struct sockaddr *) &v6,
sizeof (v6));
}
- rh->addr_callback (rh->cls,
- NULL,
- 0);
+ if (GNUNET_SYSERR != rh->was_transmitted)
+ rh->addr_callback (rh->cls,
+ NULL,
+ 0);
GNUNET_free (rh);
return;
}
rh->addr_callback (rh->cls,
(const struct sockaddr *) &v6,
sizeof (v6));
- rh->addr_callback (rh->cls,
- NULL,
- 0);
+ if (GNUNET_SYSERR != rh->was_transmitted)
+ rh->addr_callback (rh->cls,
+ NULL,
+ 0);
GNUNET_free (rh);
return;
}
GNUNET_break (0);
break;
}
- rh->addr_callback (rh->cls,
- NULL,
- 0);
+ if (GNUNET_SYSERR != rh->was_transmitted)
+ rh->addr_callback (rh->cls,
+ NULL,
+ 0);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Finished resolving hostname `%s'.\n",
(const char *) &rh[1]);
struct GNUNET_MQ_MessageHandler handlers[] = {
GNUNET_MQ_hd_var_size (response,
GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE,
- struct GNUNET_MessageHeader,
+ struct GNUNET_RESOLVER_ResponseMessage,
NULL),
GNUNET_MQ_handler_end ()
};
+ (void) cls;
r_task = NULL;
if (NULL == req_head)
return; /* no work pending */
hostname);
rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + slen);
rh->af = af;
+ rh->id = ++last_request_id;
rh->addr_callback = callback;
rh->cls = callback_cls;
GNUNET_memcpy (&rh[1],
rh->name_callback = callback;
rh->cls = cls;
rh->af = sa->sa_family;
+ rh->id = ++last_request_id;
rh->timeout = GNUNET_TIME_relative_to_absolute (timeout);
GNUNET_memcpy (&rh[1],
ip,