This file is part of GNUnet.
Copyright (C) 2010-2013, 2016 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.
-
- 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.
+ 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/>.
*/
/**
#define LOG(kind,...) GNUNET_log_from (kind, "namestore-api",__VA_ARGS__)
+/**
+ * We grant the namestore up to 1 minute of latency, if it is slower than
+ * that, store queries will fail.
+ */
+#define NAMESTORE_DELAY_TOLERANCE GNUNET_TIME_UNIT_MINUTES
/**
* An QueueEntry used to store information for a pending
*/
struct GNUNET_MQ_Envelope *env;
+ /**
+ * Task scheduled to warn us if the namestore is way too slow.
+ */
+ struct GNUNET_SCHEDULER_Task *timeout_task;
+
/**
* The operation id this zone iteration operation has
*/
qe);
if (NULL != qe->env)
GNUNET_MQ_discard (qe->env);
+ if (NULL != qe->timeout_task)
+ GNUNET_SCHEDULER_cancel (qe->timeout_task);
GNUNET_free (qe);
}
size_t name_len;
size_t rd_len;
+ (void) cls;
rd_len = ntohs (msg->rd_len);
msg_len = ntohs (msg->gns_header.header.size);
name_len = ntohs (msg->name_len);
size_t name_len;
size_t rd_len;
+ (void) cls;
rd_len = ntohs (msg->rd_len);
msg_len = ntohs (msg->gns_header.header.size);
name_len = ntohs (msg->name_len);
size_t rd_ser_len;
const char *name_tmp;
+ (void) cls;
if (GNUNET_OK != ntohs (msg->res))
return GNUNET_OK;
name_len = ntohs (msg->name_len);
{
struct GNUNET_NAMESTORE_Handle *h = cls;
+ (void) error;
force_reconnect (h);
}
struct GNUNET_NAMESTORE_QueueEntry *qe;
GNUNET_assert (NULL == h->mq);
- h->mq = GNUNET_CLIENT_connecT (h->cfg,
+ h->mq = GNUNET_CLIENT_connect (h->cfg,
"namestore",
handlers,
&mq_error_handler,
}
+/**
+ * Task launched to warn the user that the namestore is
+ * excessively slow and that a query was thus dropped.
+ *
+ * @param cls a `struct GNUNET_NAMESTORE_QueueEntry *`
+ */
+static void
+warn_delay (void *cls)
+{
+ struct GNUNET_NAMESTORE_QueueEntry *qe = cls;
+
+ qe->timeout_task = NULL;
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ "Did not receive response from namestore after %s!\n",
+ GNUNET_STRINGS_relative_time_to_string (NAMESTORE_DELAY_TOLERANCE,
+ GNUNET_YES));
+ if (NULL != qe->cont)
+ {
+ qe->cont (qe->cont_cls,
+ GNUNET_SYSERR,
+ "timeout");
+ qe->cont = NULL;
+ }
+ GNUNET_NAMESTORE_cancel (qe);
+}
+
+
/**
* Store an item in the namestore. If the item is already present,
* it is replaced with the new record. Use an empty array to
struct GNUNET_MQ_Envelope *env;
char *name_tmp;
char *rd_ser;
- size_t rd_ser_len;
+ ssize_t rd_ser_len;
size_t name_len;
uint32_t rid;
struct RecordStoreMessage *msg;
+ ssize_t sret;
name_len = strlen (label) + 1;
if (name_len > MAX_NAME_LEN)
GNUNET_break (0);
return NULL;
}
+ rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count,
+ rd);
+ if (rd_ser_len < 0)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ if (rd_ser_len > UINT16_MAX)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
rid = get_op_id (h);
qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
qe->h = h;
qe);
/* setup msg */
- rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count,
- rd);
env = GNUNET_MQ_msg_extra (msg,
name_len + rd_ser_len,
GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE);
name_tmp = (char *) &msg[1];
GNUNET_memcpy (name_tmp,
- label,
- name_len);
+ label,
+ name_len);
rd_ser = &name_tmp[name_len];
- GNUNET_assert (rd_ser_len ==
- GNUNET_GNSRECORD_records_serialize (rd_count,
- rd,
- rd_ser_len,
- rd_ser));
+ sret = GNUNET_GNSRECORD_records_serialize (rd_count,
+ rd,
+ rd_ser_len,
+ rd_ser);
+ if ( (0 > sret) ||
+ (sret != rd_ser_len) )
+ {
+ GNUNET_break (0);
+ GNUNET_free (env);
+ return NULL;
+ }
+ GNUNET_assert (rd_ser_len == (size_t) sret);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Sending NAMESTORE_RECORD_STORE message for name `%s' with %u records\n",
label,
rd_count);
-
+ qe->timeout_task = GNUNET_SCHEDULER_add_delayed (NAMESTORE_DELAY_TOLERANCE,
+ &warn_delay,
+ qe);
if (NULL == h->mq)
+ {
qe->env = env;
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ "Delaying NAMESTORE_RECORD_STORE message as namestore is not ready!\n");
+ }
else
+ {
GNUNET_MQ_send (h->mq,
env);
+ }
return qe;
}
rd.flags |= GNUNET_GNSRECORD_RF_PRIVATE;
return GNUNET_NAMESTORE_records_store (h,
pkey,
- GNUNET_GNS_MASTERZONE_STR,
+ GNUNET_GNS_EMPTY_LABEL_AT,
1,
&rd,
cont,
* for the next record.
*
* @param it the iterator
+ * @param limit number of records to return to the iterator in one shot
+ * (before #GNUNET_NAMESTORE_zone_iterator_next is to be called again)
*/
void
-GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it)
+GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it,
+ uint64_t limit)
{
struct GNUNET_NAMESTORE_Handle *h = it->h;
struct ZoneIterationNextMessage *msg;
struct GNUNET_MQ_Envelope *env;
LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Sending ZONE_ITERATION_NEXT message\n");
+ "Sending ZONE_ITERATION_NEXT message with limit %llu\n",
+ (unsigned long long) limit);
env = GNUNET_MQ_msg (msg,
GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
msg->gns_header.r_id = htonl (it->op_id);
+ msg->limit = GNUNET_htonll (limit);
GNUNET_MQ_send (h->mq,
env);
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Sending ZONE_ITERATION_STOP message\n");
- env = GNUNET_MQ_msg (msg,
- GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
- msg->gns_header.r_id = htonl (it->op_id);
- GNUNET_MQ_send (h->mq,
- env);
+ if (NULL != h->mq)
+ {
+ env = GNUNET_MQ_msg (msg,
+ GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
+ msg->gns_header.r_id = htonl (it->op_id);
+ GNUNET_MQ_send (h->mq,
+ env);
+ }
free_ze (it);
}