/**
 * Iterate over all entries in a directory.  Note that directories
 * are structured such that it is possible to iterate over the
 * individual blocks as well as over the entire directory.  Thus
 * a client can call this function on the buffer in the
 * GNUNET_FS_ProgressCallback.  Also, directories can optionally
 * include the contents of (small) files embedded in the directory
 * itself; for those files, the processor may be given the
 * contents of the file directly by this function.
 * <p>
 *
 * Note that this function maybe called on parts of directories.  Thus
 * parser errors should not be reported _at all_ (with GNUNET_break).
 * Still, if some entries can be recovered despite these parsing
 * errors, the function should try to do this.
 *
 * @param size number of bytes in data
 * @param data pointer to the beginning of the directory
 * @param offset offset of data in the directory
 * @param dep function to call on each entry
 * @param dep_cls closure for dep
 * @return GNUNET_OK if this could be a block in a directory,
 *         GNUNET_NO if this could be part of a directory (but not 100% OK)
 *         GNUNET_SYSERR if 'data' does not represent a directory
 */
int
GNUNET_FS_directory_list_contents (size_t size, const void *data,
                                   uint64_t offset,
                                   GNUNET_FS_DirectoryEntryProcessor dep,
                                   void *dep_cls)
{
    struct GetFullDataClosure full_data;
    const char *cdata = data;
    char *emsg;
    uint64_t pos;
    uint64_t align;
    uint32_t mdSize;
    uint64_t epos;
    struct GNUNET_FS_Uri *uri;
    struct GNUNET_CONTAINER_MetaData *md;
    char *filename;

    if ((offset == 0) &&
            ((size < 8 + sizeof (uint32_t)) ||
             (0 != memcmp (cdata, GNUNET_FS_DIRECTORY_MAGIC, 8))))
        return GNUNET_SYSERR;
    pos = offset;
    if (offset == 0)
    {
        memcpy (&mdSize, &cdata[8], sizeof (uint32_t));
        mdSize = ntohl (mdSize);
        if (mdSize > size - 8 - sizeof (uint32_t))
        {
            /* invalid size */
            GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                        _("MAGIC mismatch.  This is not a GNUnet directory.\n"));
            return GNUNET_SYSERR;
        }
        md = GNUNET_CONTAINER_meta_data_deserialize (&cdata[8 + sizeof (uint32_t)],
                mdSize);
        if (md == NULL)
        {
            GNUNET_break (0);
            return GNUNET_SYSERR;     /* malformed ! */
        }
        dep (dep_cls, NULL, NULL, md, 0, NULL);
        GNUNET_CONTAINER_meta_data_destroy (md);
        pos = 8 + sizeof (uint32_t) + mdSize;
    }
    while (pos < size)
    {
        /* find end of URI */
        if (cdata[pos] == '\0')
        {
            /* URI is never empty, must be end of block,
             * skip to next alignment */
            align = ((pos / DBLOCK_SIZE) + 1) * DBLOCK_SIZE;
            if (align == pos)
            {
                /* if we were already aligned, still skip a block! */
                align += DBLOCK_SIZE;
            }
            pos = align;
            if (pos >= size)
            {
                /* malformed - or partial download... */
                break;
            }
        }
        epos = pos;
        while ((epos < size) && (cdata[epos] != '\0'))
            epos++;
        if (epos >= size)
            return GNUNET_NO;         /* malformed - or partial download */

        uri = GNUNET_FS_uri_parse (&cdata[pos], &emsg);
        pos = epos + 1;
        if (uri == NULL)
        {
            GNUNET_free (emsg);
            pos--;                    /* go back to '\0' to force going to next alignment */
            continue;
        }
        if (GNUNET_FS_uri_test_ksk (uri))
        {
            GNUNET_FS_uri_destroy (uri);
            GNUNET_break (0);
            return GNUNET_NO;         /* illegal in directory! */
        }

        memcpy (&mdSize, &cdata[pos], sizeof (uint32_t));
        mdSize = ntohl (mdSize);
        pos += sizeof (uint32_t);
        if (pos + mdSize > size)
        {
            GNUNET_FS_uri_destroy (uri);
            return GNUNET_NO;         /* malformed - or partial download */
        }

        md = GNUNET_CONTAINER_meta_data_deserialize (&cdata[pos], mdSize);
        if (md == NULL)
        {
            GNUNET_FS_uri_destroy (uri);
            GNUNET_break (0);
            return GNUNET_NO;         /* malformed ! */
        }
        pos += mdSize;
        filename =
            GNUNET_CONTAINER_meta_data_get_by_type (md,
                    EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME);
        full_data.size = 0;
        full_data.data = NULL;
        GNUNET_CONTAINER_meta_data_iterate (md, &find_full_data, &full_data);
        if (dep != NULL)
        {
            dep (dep_cls, filename, uri, md, full_data.size, full_data.data);
        }
        GNUNET_free_non_null (full_data.data);
        GNUNET_free_non_null (filename);
        GNUNET_CONTAINER_meta_data_destroy (md);
        GNUNET_FS_uri_destroy (uri);
    }
    return GNUNET_OK;
}
Exemple #2
0
/**
 * Type of a function to call when we receive a message
 * from the service.
 *
 * @param cls closure
 * @param msg message received, NULL on timeout or fatal error
 */
static void
message_handler (void *cls,
		 const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_IDENTITY_Handle *h = cls;
  struct GNUNET_IDENTITY_Operation *op;
  struct GNUNET_IDENTITY_Ego *ego;
  const struct GNUNET_IDENTITY_ResultCodeMessage *rcm;
  const struct GNUNET_IDENTITY_UpdateMessage *um;
  const struct GNUNET_IDENTITY_SetDefaultMessage *sdm;
  struct GNUNET_CRYPTO_EcdsaPublicKey pub;
  struct GNUNET_HashCode id;
  const char *str;
  uint16_t size;
  uint16_t name_len;

  if (NULL == msg)
  {
    reschedule_connect (h);
    return;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Received message of type %d from identity service\n",
       ntohs (msg->type));
  size = ntohs (msg->size);
  switch (ntohs (msg->type))
  {
  case GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE:
    if (size < sizeof (struct GNUNET_IDENTITY_ResultCodeMessage))
    {
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }
    rcm = (const struct GNUNET_IDENTITY_ResultCodeMessage *) msg;
    str = (const char *) &rcm[1];
    if ( (size > sizeof (struct GNUNET_IDENTITY_ResultCodeMessage)) &&
	 ('\0' != str[size - sizeof (struct GNUNET_IDENTITY_ResultCodeMessage) - 1]) )
    {
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }
    if (size == sizeof (struct GNUNET_IDENTITY_ResultCodeMessage))
      str = NULL;

    op = h->op_head;
    GNUNET_CONTAINER_DLL_remove (h->op_head,
				 h->op_tail,
				 op);
    GNUNET_CLIENT_receive (h->client, &message_handler, h,
			   GNUNET_TIME_UNIT_FOREVER_REL);
    if (NULL != op->cont)
      op->cont (op->cls,
		str);
    else if (NULL != op->cb)
      op->cb (op->cls, NULL, NULL, NULL);
    GNUNET_free (op);
    break;
  case GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE:
    if (size < sizeof (struct GNUNET_IDENTITY_UpdateMessage))
    {
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }
    um = (const struct GNUNET_IDENTITY_UpdateMessage *) msg;
    name_len = ntohs (um->name_len);

    str = (const char *) &um[1];
    if ( (size != name_len + sizeof (struct GNUNET_IDENTITY_UpdateMessage)) ||
	 ( (0 != name_len) &&
	   ('\0' != str[name_len - 1])) )
    {
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }
    if (GNUNET_YES == ntohs (um->end_of_list))
    {
      /* end of initial list of data */
      GNUNET_CLIENT_receive (h->client, &message_handler, h,
			     GNUNET_TIME_UNIT_FOREVER_REL);
      if (NULL != h->cb)
	h->cb (h->cb_cls, NULL, NULL, NULL);
      break;
    }
    GNUNET_CRYPTO_ecdsa_key_get_public (&um->private_key,
				      &pub);
    GNUNET_CRYPTO_hash (&pub, sizeof (pub), &id);
    if (0 == name_len)
      str = NULL;
    else
      str = (const char *) &um[1];
    ego = GNUNET_CONTAINER_multihashmap_get (h->egos,
					     &id);
    if (NULL == ego)
    {
      /* ego was created */
      if (NULL == str)
      {
	/* deletion of unknown ego? not allowed */
	GNUNET_break (0);
	reschedule_connect (h);
	return;
      }
      ego = GNUNET_new (struct GNUNET_IDENTITY_Ego);
      ego->pk = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
      *ego->pk = um->private_key;
      ego->name = GNUNET_strdup (str);
      ego->id = id;
      GNUNET_assert (GNUNET_YES ==
		     GNUNET_CONTAINER_multihashmap_put (h->egos,
							&ego->id,
							ego,
							GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
    }
    if (NULL == str)
    {
      /* ego was deleted */
      GNUNET_assert (GNUNET_YES ==
		     GNUNET_CONTAINER_multihashmap_remove (h->egos,
							   &ego->id,
							   ego));
    }
    else
    {
      /* ego changed name */
      GNUNET_free (ego->name);
      ego->name = GNUNET_strdup (str);
    }
    GNUNET_CLIENT_receive (h->client, &message_handler, h,
			   GNUNET_TIME_UNIT_FOREVER_REL);
    /* inform application about change */
    if (NULL != h->cb)
      h->cb (h->cb_cls,
	     ego,
	     &ego->ctx,
	     str);
    if (NULL == str)
    {
      GNUNET_free (ego->pk);
      GNUNET_free (ego->name);
      GNUNET_free (ego);
    }
    break;
  case GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT:
    if (size < sizeof (struct GNUNET_IDENTITY_SetDefaultMessage))
    {
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }
    sdm = (const struct GNUNET_IDENTITY_SetDefaultMessage *) msg;
    GNUNET_break (0 == ntohs (sdm->reserved));
    name_len = ntohs (sdm->name_len);
    str = (const char *) &sdm[1];
    if ( (size != name_len + sizeof (struct GNUNET_IDENTITY_SetDefaultMessage)) ||
	 ( (0 != name_len) &&
	   ('\0' != str[name_len - 1]) ) )
    {
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }
    /* Note: we know which service this should be for, so we're not
       really using 'str' henceforth */
    GNUNET_CRYPTO_ecdsa_key_get_public (&sdm->private_key,
				      &pub);
    GNUNET_CRYPTO_hash (&pub, sizeof (pub), &id);
    ego = GNUNET_CONTAINER_multihashmap_get (h->egos,
					     &id);
    if (NULL == ego)
    {
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }
    op = h->op_head;
    if (NULL == op)
    {
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Received SET_DEFAULT message from identity service\n");
    GNUNET_CONTAINER_DLL_remove (h->op_head,
				 h->op_tail,
				 op);
    GNUNET_CLIENT_receive (h->client, &message_handler, h,
			   GNUNET_TIME_UNIT_FOREVER_REL);
    if (NULL != op->cb)
      op->cb (op->cls,
	      ego,
	      &ego->ctx,
	      ego->name);
    GNUNET_free (op);
    break;
  default:
    GNUNET_break (0);
    reschedule_connect (h);
    return;
  }
}
static void
shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Ending test.\n");
  GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
}
static void
run (void *cls,
     const struct GNUNET_CONFIGURATION_Handle *cfg,
     struct GNUNET_TESTING_Peer *peer)
{
  char *quota_str;

  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_OUT", &quota_str))
  {
      fprintf (stderr, "Cannot load WAN outbound quota from configuration, exit!\n");
      ret = 1;
      return;
  }
  if  (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_str, &wan_quota_out))
  {
      fprintf (stderr, "Cannot load WAN outbound quota from configuration, exit!\n");
      ret = 1;
      GNUNET_free (quota_str);
      return;
  }
  GNUNET_free (quota_str);
  quota_str = NULL;

  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "ats", "WAN_QUOTA_IN", &quota_str))
  {
      fprintf (stderr, "Cannot load WAN inbound quota from configuration, exit!\n");
      ret = 1;
      return;
  }
  if  (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_str, &wan_quota_in))
  {
      fprintf (stderr, "Cannot load WAN inbound quota from configuration, exit!\n");
      GNUNET_free (quota_str);
      ret = 1;
      return;
  }
  GNUNET_free (quota_str);
  quota_str = NULL;
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Configured WAN inbound quota: %llu\n", wan_quota_in);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Configured WAN outbound quota: %llu\n", wan_quota_out);


  die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);

  /* Connect to ATS scheduling */
  sched_ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL);
  if (sched_ats == NULL)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n");
    ret = 1;
    end ();
    return;
  }

  perf_ats = GNUNET_ATS_performance_init (cfg, NULL, NULL);
  if (perf_ats == NULL)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS performance!\n");
    ret = 1;
    end ();
    return;
  }

  /* Set up peer 0 */
  if (GNUNET_SYSERR == GNUNET_CRYPTO_hash_from_string(PEERID0, &p[0].id.hashPubKey))
  {
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not setup peer!\n");
      ret = GNUNET_SYSERR;
      end ();
      return;
  }

  GNUNET_assert (0 == strcmp (PEERID0, GNUNET_i2s_full (&p[0].id)));

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n",
              GNUNET_i2s(&p[0].id));


  /* Set up peer 0 */
  if (GNUNET_SYSERR == GNUNET_CRYPTO_hash_from_string(PEERID1, &p[1].id.hashPubKey))
  {
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not setup peer!\n");
      ret = GNUNET_SYSERR;
      end ();
      return;
  }

  GNUNET_assert (0 == strcmp (PEERID1, GNUNET_i2s_full (&p[1].id)));

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n",
              GNUNET_i2s(&p[1].id));

  /* Prepare ATS Information */
  test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE);
  test_ats_info[0].value = htonl(GNUNET_ATS_NET_WAN);
  test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
  test_ats_info[1].value = htonl(1);
  test_ats_count = 2;

  /* Adding address with session */
  test_session[0] = &test_addr[0];
  create_test_address (&test_addr[0], "test0", test_session[0], "test0", strlen ("test0") + 1);
  test_hello_address[0].peer = p[0].id;
  test_hello_address[0].transport_name = test_addr[0].plugin;
  test_hello_address[0].address = test_addr[0].addr;
  test_hello_address[0].address_length = test_addr[0].addr_len;
  GNUNET_ATS_address_add (sched_ats, &test_hello_address[0], test_session[0], test_ats_info, test_ats_count);


  /* Adding address with session */
  test_session[1] = &test_addr[1];
  create_test_address (&test_addr[1], "test1", test_session[1], "test1", strlen ("test1") + 1);
  test_hello_address[1].peer = p[1].id;
  test_hello_address[1].transport_name = test_addr[0].plugin;
  test_hello_address[1].address = test_addr[0].addr;
  test_hello_address[1].address_length = test_addr[0].addr_len;
  GNUNET_ATS_address_add (sched_ats, &test_hello_address[1], test_session[1], test_ats_info, test_ats_count);


  /* Change bandwidth preference */
  GNUNET_ATS_change_preference (perf_ats,
      &p[0].id,
      GNUNET_ATS_PREFERENCE_BANDWIDTH,(double) 1000, GNUNET_ATS_PREFERENCE_END);
  GNUNET_ATS_change_preference (perf_ats,
      &p[1].id,
      GNUNET_ATS_PREFERENCE_BANDWIDTH,(double) 1000, GNUNET_ATS_PREFERENCE_END);


  /* Change latency preference */

  GNUNET_ATS_change_preference (perf_ats,
      &p[0].id,
      GNUNET_ATS_PREFERENCE_LATENCY,(double) 10, GNUNET_ATS_PREFERENCE_END);
  GNUNET_ATS_change_preference (perf_ats,
      &p[1].id,
      GNUNET_ATS_PREFERENCE_LATENCY,(double) 100, GNUNET_ATS_PREFERENCE_END);
  GNUNET_SCHEDULER_add_delayed (SLEEP, &sleep_task, NULL);
}
static void
address_suggest_cb (void *cls, const struct GNUNET_HELLO_Address *address,
                    struct Session *session,
                    struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
                    struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
                    const struct GNUNET_ATS_Information *atsi,
                    uint32_t ats_count)
{
  static int stage = 0;
  unsigned int bw_in = ntohl(bandwidth_in.value__);
  unsigned int bw_out = ntohl(bandwidth_out.value__);
  if (0 == stage)
  {
    if (GNUNET_OK == compare_addresses (address, session, &test_hello_address[0], test_session[0]))
    {
        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage %u: Callback with correct address `%s'\n",
                    stage,
                    GNUNET_i2s (&address->peer));
        ret = 0;
    }
    else
    {
        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage %u: Callback with invalid address `%s'\n",
            stage,
                    GNUNET_i2s (&address->peer));
        ret = 1;
    }

    if (GNUNET_OK != compare_ats(atsi, ats_count, test_ats_info, test_ats_count))
    {
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Callback with incorrect ats info \n",
          stage);
      ret = 1;
    }

    if (bw_in > wan_quota_in)
    {
        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggested WAN inbound quota %u bigger than allowed quota %llu \n",
            bw_in, wan_quota_in);
        ret = 1;
    }
    else
      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suggested WAN inbound quota %u, allowed quota %llu \n",
          bw_in, wan_quota_in);

    if (bw_out > wan_quota_out)
    {
        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggested WAN outbound quota %u bigger than allowed quota %llu \n",
            bw_out, wan_quota_out);
        ret = 1;
    }
    else
      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suggested WAN outbound quota %u, allowed quota %llu \n",
          bw_out, wan_quota_out);

    if (1 == ret)
    {
      GNUNET_ATS_suggest_address_cancel (sched_ats, &p[0].id);
      GNUNET_SCHEDULER_add_now (&end, NULL);
      return;
    }

    stage ++;

    GNUNET_ATS_suggest_address_cancel (sched_ats, &p[0].id);
    GNUNET_ATS_suggest_address (sched_ats, &p[1].id);
    return;
  }
  if (1 == stage)
  {
    if (GNUNET_OK == compare_addresses (address, session, &test_hello_address[1], test_session[1]))
    {
        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage %u: Callback with correct address `%s'\n",
                    stage,
                    GNUNET_i2s (&address->peer));
        ret = 0;
    }
    else
    {
        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage %u: Callback with invalid address `%s'\n",
                    stage,
                    GNUNET_i2s (&address->peer));
        ret = 1;
    }

    if (GNUNET_OK != compare_ats(atsi, ats_count, test_ats_info, test_ats_count))
    {
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Callback with incorrect ats info \n",
          stage);
      ret = 1;
    }

    if (bw_in > wan_quota_in)
    {
        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggested WAN inbound quota %u bigger than allowed quota %llu \n",
            bw_in, wan_quota_in);
        ret = 1;
    }
    else
      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suggested WAN inbound quota %u, allowed quota %llu \n",
          bw_in, wan_quota_in);

    if (bw_out > wan_quota_out)
    {
        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggested WAN outbound quota %u bigger than allowed quota %llu \n",
            bw_out, wan_quota_out);
        ret = 1;
    }
    else
      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suggested WAN outbound quota %u, allowed quota %llu \n",
          bw_out, wan_quota_out);

    if (1 == ret)
    {
      GNUNET_ATS_suggest_address_cancel (sched_ats, &p[0].id);
      GNUNET_SCHEDULER_add_now (&end, NULL);
      return;
    }

    stage ++;
    GNUNET_ATS_suggest_address_cancel (sched_ats, &p[1].id);
    GNUNET_SCHEDULER_add_now (&end, NULL);

    return;
  }
}
/**
 * Iterate over all edges of a block of a regex state.
 *
 * @param block Block to iterate over.
 * @param size Size of block.
 * @param iterator Function to call on each edge in the block.
 * @param iter_cls Closure for the iterator.
 *
 * @return How many bytes of block have been processed
 */
int
GNUNET_MESH_regex_block_iterate (const struct MeshRegexBlock *block,
                                 size_t size,
                                 GNUNET_MESH_EgdeIterator iterator,
                                 void *iter_cls)
{
  struct MeshRegexEdge *edge;
  unsigned int n;
  unsigned int n_token;
  unsigned int i;
  size_t offset;
  char *aux;

  offset = sizeof (struct MeshRegexBlock);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "* Start iterating block of size %u, off %u\n",
              size, offset);
  if (offset > size) // Is it safe to access the regex block?
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
              "*   Block is smaller than struct MeshRegexBlock, END\n");
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  n = ntohl (block->n_proof);
  offset += n;
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "*  Proof length: %u, off %u\n", n, offset);
  if (offset > size) // Is it safe to access the regex proof?
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                "*   Block is smaller than Block + proof, END\n");
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  aux = (char *) &block[1];  // Skip regex block
  aux = &aux[n];             // Skip regex proof
  n = ntohl (block->n_edges);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*  Edges: %u\n", n);
  for (i = 0; i < n; i++) // aux always points at the end of the previous block
  {
    offset += sizeof (struct MeshRegexEdge);
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*   Edge %u, off %u\n", i, offset);
    if (offset > size) // Is it safe to access the next edge block?
    {
      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                  "*   Size not enough for MeshRegexEdge, END\n");
      GNUNET_break_op (0);
      return GNUNET_SYSERR;
    }
    edge = (struct MeshRegexEdge *) aux;
    n_token = ntohl (edge->n_token);
    offset += n_token;
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "*    Token lenght %u, off %u\n", n_token, offset);
    if (offset > size) // Is it safe to access the edge token?
    {
      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                  "*   Size not enough for edge token, END\n");
      GNUNET_break_op (0);
      return GNUNET_SYSERR;
    }
    aux = (char *) &edge[1]; // Skip edge block
    if (NULL != iterator)
        if (GNUNET_NO == iterator (iter_cls, aux, n_token, &edge->key))
            return GNUNET_OK;
    aux = &aux[n_token];     // Skip edge token
  }
  // The total size should be exactly the size of (regex + all edges) blocks
  // If size == -1, block is from cache and therefore previously checked and
  // assumed correct.
  if (offset == size || SIZE_MAX == size)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                  "* Block processed, END OK\n");
    return GNUNET_OK;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
              "*   Size %u (%d), read %u END KO\n", size, size, offset);
  GNUNET_break_op (0);
  return GNUNET_SYSERR;
}