/**
 * Extract metadata from files.
 *
 * @param item entry we are processing
 * @return GNUNET_OK on success, GNUNET_SYSERR on fatal errors
 */
static int
extract_files (struct ScanTreeNode *item)
{  
  struct GNUNET_CONTAINER_MetaData *meta;
  ssize_t size;
  size_t slen;

  if (GNUNET_YES == item->is_directory)
  {
    /* for directories, we simply only descent, no extraction, no
       progress reporting */
    struct ScanTreeNode *pos;

    for (pos = item->children_head; NULL != pos; pos = pos->next)
      if (GNUNET_OK !=
	  extract_files (pos))
	return GNUNET_SYSERR;
    return GNUNET_OK;
  }
  
  /* this is the expensive operation, *afterwards* we'll check for aborts */
  meta = GNUNET_CONTAINER_meta_data_create ();
  if (NULL != plugins)
    EXTRACTOR_extract (plugins, item->filename, NULL, 0, &add_to_md, meta);
  slen = strlen (item->filename) + 1;
  size = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
  if (-1 == size)
  {
    /* no meta data */
    GNUNET_CONTAINER_meta_data_destroy (meta);
    if (GNUNET_OK !=
	write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_META_DATA,
		       item->filename, slen))
      return GNUNET_SYSERR;    
    return GNUNET_OK;
  }
  {
    char buf[size + slen];
    char *dst = &buf[slen];
    
    memcpy (buf, item->filename, slen);
    size = GNUNET_CONTAINER_meta_data_serialize (meta,
						 &dst, size,
						 GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
    if (size < 0)
    {
      GNUNET_break (0);
      size = 0;
    }
    GNUNET_CONTAINER_meta_data_destroy (meta);
    if (GNUNET_OK !=
	write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_META_DATA,
		       buf, 
		       slen + size))
      return GNUNET_SYSERR;
  }
  return GNUNET_OK;
}
Exemplo n.º 2
0
/**
 * Transmit a join request to the chat service.
 *
 * @param cls closure, pointer to the 'struct GNUNET_CHAT_Room'
 * @param size number of bytes available in buf
 * @param buf where the callee should write the message
 * @return number of bytes written to buf
 */
static size_t
transmit_join_request (void *cls, size_t size, void *buf)
{
  struct GNUNET_CHAT_Room *chat_room = cls;
  struct JoinRequestMessage *join_msg;
  char *room;
  char *meta;
  size_t room_len;
  ssize_t meta_len;
  size_t size_of_join;

  if (NULL == buf)
  {
#if DEBUG_CHAT
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Could not transmit join request, retrying...\n");
#endif
    rejoin_room (chat_room);
    return 0;
  }
#if DEBUG_CHAT
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Transmitting join request to the service\n");
#endif
  room_len = strlen (chat_room->room_name);
  meta_len =
      GNUNET_CONTAINER_meta_data_get_serialized_size (chat_room->member_info);
  size_of_join = sizeof (struct JoinRequestMessage) + meta_len + room_len;
  GNUNET_assert (size >= size_of_join);
  join_msg = buf;
  join_msg->header.size = htons (size);
  join_msg->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_JOIN_REQUEST);
  join_msg->msg_options = htonl (chat_room->msg_options);
  join_msg->room_name_len = htons (room_len);
  join_msg->reserved = htons (0);
  join_msg->reserved2 = htonl (0);
  GNUNET_CRYPTO_rsa_key_get_public (chat_room->my_private_key,
                                    &join_msg->public_key);
  room = (char *) &join_msg[1];
  memcpy (room, chat_room->room_name, room_len);
  meta = &room[room_len];
  if (GNUNET_SYSERR ==
      GNUNET_CONTAINER_meta_data_serialize (chat_room->member_info, &meta,
                                            meta_len,
                                            GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not serialize metadata\n"));
    return 0;
  }
  GNUNET_CLIENT_receive (chat_room->client, &receive_results, chat_room,
                         GNUNET_TIME_UNIT_FOREVER_REL);
  return size_of_join;
}
/**
 * Get the size of the full meta-data in serialized form.
 *
 * @param md metadata to inspect
 * @return number of bytes needed for serialization, -1 on error
 */
ssize_t
GNUNET_CONTAINER_meta_data_get_serialized_size (const struct
                                                GNUNET_CONTAINER_MetaData *md)
{
  ssize_t ret;
  char *ptr;

  if (md->sbuf != NULL)
    return md->sbuf_size;
  ptr = NULL;
  ret =
      GNUNET_CONTAINER_meta_data_serialize (md, &ptr, GNUNET_MAX_MALLOC_CHECKED,
                                            GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL);
  if (ret != -1)
    GNUNET_free (ptr);
  return ret;
}
Exemplo n.º 4
0
/**
 * Publish a UBlock.
 *
 * @param h handle to the file sharing subsystem
 * @param dsh datastore handle to use for storage operation
 * @param label identifier to use
 * @param ulabel update label to use, may be an empty string for none
 * @param ns namespace to publish in
 * @param meta metadata to use
 * @param uri URI to refer to in the UBlock
 * @param bo per-block options
 * @param options publication options
 * @param cont continuation
 * @param cont_cls closure for @a cont
 * @return NULL on error (@a cont will still be called)
 */
struct GNUNET_FS_PublishUblockContext *
GNUNET_FS_publish_ublock_ (struct GNUNET_FS_Handle *h,
			   struct GNUNET_DATASTORE_Handle *dsh,
			   const char *label,
			   const char *ulabel,
			   const struct GNUNET_CRYPTO_EcdsaPrivateKey *ns,
			   const struct GNUNET_CONTAINER_MetaData *meta,
			   const struct GNUNET_FS_Uri *uri,
			   const struct GNUNET_FS_BlockOptions *bo,
			   enum GNUNET_FS_PublishOptions options,
			   GNUNET_FS_UBlockContinuation cont, void *cont_cls)
{
  struct GNUNET_FS_PublishUblockContext *uc;
  struct GNUNET_HashCode query;
  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
  struct GNUNET_CRYPTO_SymmetricSessionKey skey;
  struct GNUNET_CRYPTO_EcdsaPrivateKey *nsd;
  struct GNUNET_CRYPTO_EcdsaPublicKey pub;
  char *uris;
  size_t size;
  char *kbe;
  char *sptr;
  ssize_t mdsize;
  size_t slen;
  size_t ulen;
  struct UBlock *ub_plain;
  struct UBlock *ub_enc;

  /* compute ublock to publish */
  if (NULL == meta)
    mdsize = 0;
  else
    mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
  GNUNET_assert (mdsize >= 0);
  uris = GNUNET_FS_uri_to_string (uri);
  slen = strlen (uris) + 1;
  if (NULL == ulabel)
    ulen = 1;
  else
    ulen = strlen (ulabel) + 1;
  size = mdsize + sizeof (struct UBlock) + slen + ulen;
  if (size > MAX_UBLOCK_SIZE)
  {
    size = MAX_UBLOCK_SIZE;
    mdsize = size - sizeof (struct UBlock) - (slen + ulen);
  }
  ub_plain = GNUNET_malloc (size);
  kbe = (char *) &ub_plain[1];
  if (NULL != ulabel)
    memcpy (kbe, ulabel, ulen);
  kbe += ulen;
  memcpy (kbe, uris, slen);
  kbe += slen;
  GNUNET_free (uris);
  sptr = kbe;
  if (NULL != meta)
    mdsize =
      GNUNET_CONTAINER_meta_data_serialize (meta, &sptr, mdsize,
					    GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
  if (-1 == mdsize)
  {
    GNUNET_break (0);
    GNUNET_free (ub_plain);
    cont (cont_cls, _("Internal error."));
    return NULL;
  }
  size = sizeof (struct UBlock) + slen + mdsize + ulen;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
	      "Publishing under identifier `%s'\n",
              label);
  /* get public key of the namespace */
  GNUNET_CRYPTO_ecdsa_key_get_public (ns,
				    &pub);
  derive_ublock_encryption_key (&skey, &iv,
				label, &pub);

  /* encrypt ublock */
  ub_enc = GNUNET_malloc (size);
  GNUNET_CRYPTO_symmetric_encrypt (&ub_plain[1],
			     ulen + slen + mdsize,
			     &skey, &iv,
                             &ub_enc[1]);
  GNUNET_free (ub_plain);
  ub_enc->purpose.size = htonl (ulen + slen + mdsize +
				sizeof (struct UBlock)
				- sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
  ub_enc->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK);

  /* derive signing-key from 'label' and public key of the namespace */
  nsd = GNUNET_CRYPTO_ecdsa_private_key_derive (ns, label, "fs-ublock");
  GNUNET_CRYPTO_ecdsa_key_get_public (nsd,
				    &ub_enc->verification_key);
  GNUNET_assert (GNUNET_OK ==
		 GNUNET_CRYPTO_ecdsa_sign (nsd,
					 &ub_enc->purpose,
					 &ub_enc->signature));
  GNUNET_CRYPTO_hash (&ub_enc->verification_key,
		      sizeof (ub_enc->verification_key),
		      &query);
  GNUNET_free (nsd);

  uc = GNUNET_new (struct GNUNET_FS_PublishUblockContext);
  uc->cont = cont;
  uc->cont_cls = cont_cls;
  uc->qre =
    GNUNET_DATASTORE_put (dsh, 0, &query,
			  ulen + slen + mdsize + sizeof (struct UBlock),
			  ub_enc, GNUNET_BLOCK_TYPE_FS_UBLOCK,
			  bo->content_priority, bo->anonymity_level,
			  bo->replication_level, bo->expiration_time,
			  -2, 1, GNUNET_CONSTANTS_SERVICE_TIMEOUT,
			  &ublock_put_cont, uc);
  return uc;
}
Exemplo n.º 5
0
/**
 * Publish a CHK under various keywords on GNUnet.
 *
 * @param h handle to the file sharing subsystem
 * @param ksk_uri keywords to use
 * @param meta metadata to use
 * @param uri URI to refer to in the KBlock
 * @param bo per-block options
 * @param options publication options
 * @param cont continuation
 * @param cont_cls closure for cont
 * @return NULL on error ('cont' will still be called)
 */
struct GNUNET_FS_PublishKskContext *
GNUNET_FS_publish_ksk (struct GNUNET_FS_Handle *h,
                       const struct GNUNET_FS_Uri *ksk_uri,
                       const struct GNUNET_CONTAINER_MetaData *meta,
                       const struct GNUNET_FS_Uri *uri,
                       const struct GNUNET_FS_BlockOptions *bo,
                       enum GNUNET_FS_PublishOptions options,
                       GNUNET_FS_PublishContinuation cont, void *cont_cls)
{
  struct GNUNET_FS_PublishKskContext *pkc;
  char *uris;
  size_t size;
  char *kbe;
  char *sptr;

  GNUNET_assert (NULL != uri);
  pkc = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishKskContext));
  pkc->h = h;
  pkc->bo = *bo;
  pkc->cont = cont;
  pkc->cont_cls = cont_cls;
  if (0 == (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY))
  {
    pkc->dsh = GNUNET_DATASTORE_connect (h->cfg);
    if (NULL == pkc->dsh)
    {
      cont (cont_cls, NULL, _("Could not connect to datastore."));
      GNUNET_free (pkc);
      return NULL;
    }
  }
  if (meta == NULL)
    pkc->mdsize = 0;
  else
    pkc->mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
  GNUNET_assert (pkc->mdsize >= 0);
  uris = GNUNET_FS_uri_to_string (uri);
  pkc->slen = strlen (uris) + 1;
  size = pkc->mdsize + sizeof (struct KBlock) + pkc->slen;
  if (size > MAX_KBLOCK_SIZE)
  {
    size = MAX_KBLOCK_SIZE;
    pkc->mdsize = size - sizeof (struct KBlock) - pkc->slen;
  }
  pkc->kb = GNUNET_malloc (size);
  kbe = (char *) &pkc->kb[1];
  memcpy (kbe, uris, pkc->slen);
  GNUNET_free (uris);
  sptr = &kbe[pkc->slen];
  if (meta != NULL)
    pkc->mdsize =
        GNUNET_CONTAINER_meta_data_serialize (meta, &sptr, pkc->mdsize,
                                              GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
  if (-1 == pkc->mdsize)
  {
    GNUNET_break (0);
    GNUNET_free (pkc->kb);
    if (pkc->dsh != NULL)
    {
      GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO);
      pkc->dsh = NULL;
    }
    GNUNET_free (pkc);
    cont (cont_cls, NULL, _("Internal error."));
    return NULL;
  }
  size = sizeof (struct KBlock) + pkc->slen + pkc->mdsize;

  pkc->cpy = GNUNET_malloc (size);
  pkc->cpy->purpose.size =
      htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
             sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
             pkc->mdsize + pkc->slen);
  pkc->cpy->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_KBLOCK);
  pkc->ksk_uri = GNUNET_FS_uri_dup (ksk_uri);
  pkc->ksk_task = GNUNET_SCHEDULER_add_now (&publish_ksk_cont, pkc);
  return pkc;
}
Exemplo n.º 6
0
/**
 * Finish building the directory.  Frees the
 * builder context and returns the directory
 * in-memory.
 *
 * @param bld directory to finish
 * @param rsize set to the number of bytes needed
 * @param rdata set to the encoded directory
 * @return GNUNET_OK on success
 */
int
GNUNET_FS_directory_builder_finish (struct GNUNET_FS_DirectoryBuilder *bld,
                                    size_t * rsize, void **rdata)
{
    char *data;
    char *sptr;
    size_t *sizes;
    unsigned int *perm;
    unsigned int i;
    unsigned int j;
    struct BuilderEntry *pos;
    struct BuilderEntry **bes;
    size_t size;
    size_t psize;
    size_t off;
    ssize_t ret;
    uint32_t big;

    size = strlen (GNUNET_DIRECTORY_MAGIC) + sizeof (uint32_t);
    size += GNUNET_CONTAINER_meta_data_get_serialized_size (bld->meta);
    sizes = NULL;
    perm = NULL;
    bes = NULL;
    if (0 < bld->count)
    {
        sizes = GNUNET_malloc (bld->count * sizeof (size_t));
        perm = GNUNET_malloc (bld->count * sizeof (unsigned int));
        bes = GNUNET_malloc (bld->count * sizeof (struct BuilderEntry *));
        pos = bld->head;
        for (i = 0; i < bld->count; i++)
        {
            perm[i] = i;
            bes[i] = pos;
            sizes[i] = pos->len;
            pos = pos->next;
        }
        block_align (size, bld->count, sizes, perm);
        /* compute final size with alignment */
        for (i = 0; i < bld->count; i++)
        {
            psize = size;
            size += sizes[perm[i]];
            size = do_align (psize, size);
        }
    }
    *rsize = size;
    data = GNUNET_malloc_large (size);
    if (data == NULL)
    {
        GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "malloc");
        *rsize = 0;
        *rdata = NULL;
        GNUNET_free_non_null (sizes);
        GNUNET_free_non_null (perm);
        GNUNET_free_non_null (bes);
        return GNUNET_SYSERR;
    }
    *rdata = data;
    memcpy (data, GNUNET_DIRECTORY_MAGIC, strlen (GNUNET_DIRECTORY_MAGIC));
    off = strlen (GNUNET_DIRECTORY_MAGIC);

    sptr = &data[off + sizeof (uint32_t)];
    ret =
        GNUNET_CONTAINER_meta_data_serialize (bld->meta, &sptr,
                size - off - sizeof (uint32_t),
                GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL);
    GNUNET_assert (ret != -1);
    big = htonl (ret);
    memcpy (&data[off], &big, sizeof (uint32_t));
    off += sizeof (uint32_t) + ret;
    for (j = 0; j < bld->count; j++)
    {
        i = perm[j];
        psize = off;
        off += sizes[i];
        off = do_align (psize, off);
        memcpy (&data[off - sizes[i]], &(bes[i])[1], sizes[i]);
        GNUNET_free (bes[i]);
    }
    GNUNET_free_non_null (sizes);
    GNUNET_free_non_null (perm);
    GNUNET_free_non_null (bes);
    GNUNET_assert (off == size);
    GNUNET_CONTAINER_meta_data_destroy (bld->meta);
    GNUNET_free (bld);
    return GNUNET_OK;
}
Exemplo n.º 7
0
/**
 * Add an entry to a directory.
 *
 * @param bld directory to extend
 * @param uri uri of the entry (must not be a KSK)
 * @param md metadata of the entry
 * @param data raw data of the entry, can be NULL, otherwise
 *        data must point to exactly the number of bytes specified
 *        by the uri which must be of type LOC or CHK
 */
void
GNUNET_FS_directory_builder_add (struct GNUNET_FS_DirectoryBuilder *bld,
                                 const struct GNUNET_FS_Uri *uri,
                                 const struct GNUNET_CONTAINER_MetaData *md,
                                 const void *data)
{
    struct GNUNET_FS_Uri *curi;
    struct BuilderEntry *e;
    uint64_t fsize;
    uint32_t big;
    ssize_t ret;
    size_t mds;
    size_t mdxs;
    char *uris;
    char *ser;
    char *sptr;
    size_t slen;
    struct GNUNET_CONTAINER_MetaData *meta;
    const struct GNUNET_CONTAINER_MetaData *meta_use;

    GNUNET_assert (!GNUNET_FS_uri_test_ksk (uri));
    if (NULL != data)
    {
        GNUNET_assert (!GNUNET_FS_uri_test_sks (uri));
        if (GNUNET_FS_uri_test_chk (uri))
        {
            fsize = GNUNET_FS_uri_chk_get_file_size (uri);
        }
        else
        {
            curi = GNUNET_FS_uri_loc_get_uri (uri);
            GNUNET_assert (NULL != curi);
            fsize = GNUNET_FS_uri_chk_get_file_size (curi);
            GNUNET_FS_uri_destroy (curi);
        }
    }
    else
    {
        fsize = 0;                  /* not given */
    }
    if (fsize > MAX_INLINE_SIZE)
        fsize = 0;                  /* too large */
    uris = GNUNET_FS_uri_to_string (uri);
    slen = strlen (uris) + 1;
    mds = GNUNET_CONTAINER_meta_data_get_serialized_size (md);
    meta_use = md;
    meta = NULL;
    if (fsize > 0)
    {
        meta = GNUNET_CONTAINER_meta_data_duplicate (md);
        GNUNET_CONTAINER_meta_data_insert (meta, "<gnunet>",
                                           EXTRACTOR_METATYPE_GNUNET_FULL_DATA,
                                           EXTRACTOR_METAFORMAT_BINARY, NULL, data,
                                           fsize);
        mdxs = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
        if ((slen + sizeof (uint32_t) + mdxs - 1) / DBLOCK_SIZE ==
                (slen + sizeof (uint32_t) + mds - 1) / DBLOCK_SIZE)
        {
            /* adding full data would not cause us to cross
             * additional blocks, so add it! */
            meta_use = meta;
            mds = mdxs;
        }
    }

    if (mds > GNUNET_MAX_MALLOC_CHECKED / 2)
        mds = GNUNET_MAX_MALLOC_CHECKED / 2;
    e = GNUNET_malloc (sizeof (struct BuilderEntry) + slen + mds +
                       sizeof (uint32_t));
    ser = (char *) &e[1];
    memcpy (ser, uris, slen);
    GNUNET_free (uris);
    sptr = &ser[slen + sizeof (uint32_t)];
    ret =
        GNUNET_CONTAINER_meta_data_serialize (meta_use, &sptr, mds,
                GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
    if (NULL != meta)
        GNUNET_CONTAINER_meta_data_destroy (meta);
    if (ret == -1)
        mds = 0;
    else
        mds = ret;
    big = htonl (mds);
    memcpy (&ser[slen], &big, sizeof (uint32_t));
    e->len = slen + sizeof (uint32_t) + mds;
    e->next = bld->head;
    bld->head = e;
    bld->count++;
}