#define PS_NAMES_DIR DIR_SEPARATOR_STR "data" DIR_SEPARATOR_STR "pseudonyms" DIR_SEPARATOR_STR "names" DIR_SEPARATOR_STR
+/**
+ * Configuration section we use.
+ */
+#define GNUNET_CLIENT_SERVICE_NAME "client"
+
+
+
/**
* Registered callbacks for discovery of pseudonyms.
*/
* @param rating rating of pseudonym
*/
static void
-internal_notify (const GNUNET_HashCode * id,
+internal_notify (const struct GNUNET_HashCode * id,
const struct GNUNET_CONTAINER_MetaData *md, int rating)
{
struct DiscoveryCallback *pos;
pos = head;
while (pos != NULL)
{
- pos->callback (pos->closure, id, md, rating);
+ pos->callback (pos->closure, id, NULL, NULL, md, rating);
pos = pos->next;
}
}
/**
* Register callback to be invoked whenever we discover
* a new pseudonym.
+ * Will immediately call provided iterator callback for all
+ * already discovered pseudonyms.
+ *
* @param cfg configuration to use
* @param iterator iterator over pseudonym
* @param closure point to a closure
*/
static char *
get_data_filename (const struct GNUNET_CONFIGURATION_Handle *cfg,
- const char *prefix, const GNUNET_HashCode * psid)
+ const char *prefix, const struct GNUNET_HashCode * psid)
{
struct GNUNET_CRYPTO_HashAsciiEncoded enc;
* @param nsid hash code of a pseudonym
* @param meta meta data to be written into a file
* @param ranking ranking of a pseudonym
- * @param ns_name name of a pseudonym
+ * @param ns_name non-unique name of a pseudonym
*/
static void
write_pseudonym_info (const struct GNUNET_CONFIGURATION_Handle *cfg,
- const GNUNET_HashCode * nsid,
+ const struct GNUNET_HashCode * nsid,
const struct GNUNET_CONTAINER_MetaData *meta,
int32_t ranking, const char *ns_name)
{
}
GNUNET_free (fn);
/* create entry for pseudonym name in names */
- /* FIXME: 90% of what this call does is not needed
- * here => refactor code to only create the entry! */
- GNUNET_free_non_null (GNUNET_PSEUDONYM_id_to_name (cfg, nsid));
+ if (ns_name != NULL)
+ GNUNET_free_non_null (GNUNET_PSEUDONYM_name_uniquify (cfg, nsid, ns_name,
+ NULL));
}
*/
static int
read_info (const struct GNUNET_CONFIGURATION_Handle *cfg,
- const GNUNET_HashCode * nsid,
+ const struct GNUNET_HashCode * nsid,
struct GNUNET_CONTAINER_MetaData **meta, int32_t * ranking,
char **ns_name)
{
fn = get_data_filename (cfg, PS_METADATA_DIR, nsid);
GNUNET_assert (fn != NULL);
+ if (GNUNET_YES !=
+ GNUNET_DISK_file_test (fn))
+ {
+ GNUNET_free (fn);
+ return GNUNET_SYSERR;
+ }
fileR = GNUNET_BIO_read_open (fn);
if (fileR == NULL)
{
}
-
/**
- * Return the unique, human readable name for the given namespace.
+ * Return unique variant of the namespace name.
+ * Use it after GNUNET_PSEUDONYM_get_info() to make sure
+ * that name is unique.
*
* @param cfg configuration
* @param nsid cryptographic ID of the namespace
- * @return NULL on failure (should never happen)
+ * @param name name to uniquify
+ * @param suffix if not NULL, filled with the suffix value
+ * @return NULL on failure (should never happen), name on success.
+ * Free the name with GNUNET_free().
*/
char *
-GNUNET_PSEUDONYM_id_to_name (const struct GNUNET_CONFIGURATION_Handle *cfg,
- const GNUNET_HashCode * nsid)
+GNUNET_PSEUDONYM_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const struct GNUNET_HashCode * nsid, const char *name, unsigned int *suffix)
{
- struct GNUNET_CONTAINER_MetaData *meta;
- char *name;
- GNUNET_HashCode nh;
- char *fn;
+ struct GNUNET_HashCode nh;
uint64_t len;
+ char *fn;
struct GNUNET_DISK_FileHandle *fh;
unsigned int i;
unsigned int idx;
char *ret;
struct stat sbuf;
- int32_t temp = 0;
- int32_t *rank = &temp;
- meta = NULL;
- name = NULL;
- if (GNUNET_OK == read_info (cfg, nsid, &meta, rank, &name))
- {
- if ((meta != NULL) && (name == NULL))
- name =
- GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
- EXTRACTOR_METATYPE_TITLE,
- EXTRACTOR_METATYPE_FILENAME,
- EXTRACTOR_METATYPE_DESCRIPTION,
- EXTRACTOR_METATYPE_SUBJECT,
- EXTRACTOR_METATYPE_PUBLISHER,
- EXTRACTOR_METATYPE_AUTHOR_NAME,
- EXTRACTOR_METATYPE_COMMENT,
- EXTRACTOR_METATYPE_SUMMARY,
- -1);
- if (meta != NULL)
- {
- GNUNET_CONTAINER_meta_data_destroy (meta);
- meta = NULL;
- }
- }
- if (name == NULL)
- name = GNUNET_strdup (_("no-name"));
GNUNET_CRYPTO_hash (name, strlen (name), &nh);
fn = get_data_filename (cfg, PS_NAMES_DIR, &nh);
GNUNET_assert (fn != NULL);
len = 0;
if (0 == STAT (fn, &sbuf))
- GNUNET_DISK_file_size (fn, &len, GNUNET_YES);
+ GNUNET_break (GNUNET_OK == GNUNET_DISK_file_size (fn, &len, GNUNET_YES, GNUNET_YES));
fh = GNUNET_DISK_file_open (fn,
GNUNET_DISK_OPEN_CREATE |
GNUNET_DISK_OPEN_READWRITE,
GNUNET_DISK_PERM_USER_WRITE);
i = 0;
idx = -1;
- while ((len >= sizeof (GNUNET_HashCode)) &&
- (sizeof (GNUNET_HashCode) ==
- GNUNET_DISK_file_read (fh, &nh, sizeof (GNUNET_HashCode))))
+ while ((len >= sizeof (struct GNUNET_HashCode)) &&
+ (sizeof (struct GNUNET_HashCode) ==
+ GNUNET_DISK_file_read (fh, &nh, sizeof (struct GNUNET_HashCode))))
{
- if (0 == memcmp (&nh, nsid, sizeof (GNUNET_HashCode)))
+ if (0 == memcmp (&nh, nsid, sizeof (struct GNUNET_HashCode)))
{
idx = i;
break;
}
i++;
- len -= sizeof (GNUNET_HashCode);
+ len -= sizeof (struct GNUNET_HashCode);
}
if (idx == -1)
{
idx = i;
- if (sizeof (GNUNET_HashCode) !=
- GNUNET_DISK_file_write (fh, nsid, sizeof (GNUNET_HashCode)))
+ if (sizeof (struct GNUNET_HashCode) !=
+ GNUNET_DISK_file_write (fh, nsid, sizeof (struct GNUNET_HashCode)))
LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "write", fn);
}
GNUNET_DISK_file_close (fh);
ret = GNUNET_malloc (strlen (name) + 32);
GNUNET_snprintf (ret, strlen (name) + 32, "%s-%u", name, idx);
- GNUNET_free (name);
+ if (suffix != NULL)
+ *suffix = idx;
GNUNET_free (fn);
return ret;
}
+/**
+ * Get namespace name, metadata and rank
+ * This is a wrapper around internal read_info() call, and ensures that
+ * returned data is not invalid (not NULL).
+ *
+ * @param cfg configuration
+ * @param nsid cryptographic ID of the namespace
+ * @param ret_meta a location to store metadata pointer. NULL, if metadata
+ * is not needed. Destroy with GNUNET_CONTAINER_meta_data_destroy().
+ * @param ret_rank a location to store rank. NULL, if rank not needed.
+ * @param ret_name a location to store human-readable name. Name is not unique.
+ * NULL, if name is not needed. Free with GNUNET_free().
+ * @param name_is_a_dup is set to GNUNET_YES, if ret_name was filled with
+ * a duplicate of a "no-name" placeholder
+ * @return GNUNET_OK on success. GNUENT_SYSERR if the data was
+ * unobtainable (in that case ret_* are filled with placeholders -
+ * empty metadata container, rank -1 and a "no-name" name).
+ */
+int
+GNUNET_PSEUDONYM_get_info (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const struct GNUNET_HashCode * nsid, struct GNUNET_CONTAINER_MetaData **ret_meta,
+ int32_t *ret_rank, char **ret_name, int *name_is_a_dup)
+{
+ struct GNUNET_CONTAINER_MetaData *meta;
+ char *name;
+ int32_t rank = -1;
+
+ meta = NULL;
+ name = NULL;
+ if (GNUNET_OK == read_info (cfg, nsid, &meta, &rank, &name))
+ {
+ if ((meta != NULL) && (name == NULL))
+ name =
+ GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
+ EXTRACTOR_METATYPE_TITLE,
+ EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME,
+ EXTRACTOR_METATYPE_FILENAME,
+ EXTRACTOR_METATYPE_DESCRIPTION,
+ EXTRACTOR_METATYPE_SUBJECT,
+ EXTRACTOR_METATYPE_PUBLISHER,
+ EXTRACTOR_METATYPE_AUTHOR_NAME,
+ EXTRACTOR_METATYPE_COMMENT,
+ EXTRACTOR_METATYPE_SUMMARY,
+ -1);
+ if (ret_name != NULL)
+ {
+ if (name == NULL)
+ {
+ name = GNUNET_strdup (_("no-name"));
+ if (name_is_a_dup != NULL)
+ *name_is_a_dup = GNUNET_YES;
+ }
+ else if (name_is_a_dup != NULL)
+ *name_is_a_dup = GNUNET_NO;
+ *ret_name = name;
+ }
+ else if (name != NULL)
+ GNUNET_free (name);
+
+ if (ret_meta != NULL)
+ {
+ if (meta == NULL)
+ meta = GNUNET_CONTAINER_meta_data_create ();
+ *ret_meta = meta;
+ }
+ else if (meta != NULL)
+ GNUNET_CONTAINER_meta_data_destroy (meta);
+
+ if (ret_rank != NULL)
+ *ret_rank = rank;
+
+ return GNUNET_OK;
+ }
+ if (ret_name != NULL)
+ *ret_name = GNUNET_strdup (_("no-name"));
+ if (ret_meta != NULL)
+ *ret_meta = GNUNET_CONTAINER_meta_data_create ();
+ if (ret_rank != NULL)
+ *ret_rank = -1;
+ if (name_is_a_dup != NULL)
+ *name_is_a_dup = GNUNET_YES;
+ return GNUNET_SYSERR;
+}
+
/**
* Get the namespace ID belonging to the given namespace name.
*
* @param cfg configuration to use
- * @param ns_uname human-readable name for the namespace
+ * @param ns_uname unique (!) human-readable name for the namespace
* @param nsid set to namespace ID based on 'ns_uname'
- * @return GNUNET_OK on success
+ * @return GNUNET_OK on success, GNUNET_SYSERR on failure
*/
int
GNUNET_PSEUDONYM_name_to_id (const struct GNUNET_CONFIGURATION_Handle *cfg,
- const char *ns_uname, GNUNET_HashCode * nsid)
+ const char *ns_uname, struct GNUNET_HashCode * nsid)
{
size_t slen;
uint64_t len;
unsigned int idx;
char *name;
- GNUNET_HashCode nh;
+ struct GNUNET_HashCode nh;
char *fn;
struct GNUNET_DISK_FileHandle *fh;
idx = -1;
slen = strlen (ns_uname);
- while ((slen > 0) && (1 != sscanf (&ns_uname[slen - 1], "-%u", &idx)))
+ while ((slen > 0) && (1 != SSCANF (&ns_uname[slen - 1], "-%u", &idx)))
slen--;
if (slen == 0)
return GNUNET_SYSERR;
name = GNUNET_strdup (ns_uname);
name[slen - 1] = '\0';
+
GNUNET_CRYPTO_hash (name, strlen (name), &nh);
GNUNET_free (name);
fn = get_data_filename (cfg, PS_NAMES_DIR, &nh);
GNUNET_assert (fn != NULL);
if ((GNUNET_OK != GNUNET_DISK_file_test (fn) ||
- (GNUNET_OK != GNUNET_DISK_file_size (fn, &len, GNUNET_YES))) ||
- ((idx + 1) * sizeof (GNUNET_HashCode) > len))
+ (GNUNET_OK != GNUNET_DISK_file_size (fn, &len, GNUNET_YES, GNUNET_YES))) ||
+ ((idx + 1) * sizeof (struct GNUNET_HashCode) > len))
{
GNUNET_free (fn);
return GNUNET_SYSERR;
GNUNET_DISK_PERM_USER_READ |
GNUNET_DISK_PERM_USER_WRITE);
GNUNET_free (fn);
- GNUNET_DISK_file_seek (fh, idx * sizeof (GNUNET_HashCode),
- GNUNET_DISK_SEEK_SET);
- if (sizeof (GNUNET_HashCode) !=
- GNUNET_DISK_file_read (fh, nsid, sizeof (GNUNET_HashCode)))
+ if (GNUNET_SYSERR ==
+ GNUNET_DISK_file_seek (fh, idx * sizeof (struct GNUNET_HashCode),
+ GNUNET_DISK_SEEK_SET))
+ {
+ GNUNET_DISK_file_close (fh);
+ return GNUNET_SYSERR;
+ }
+ if (sizeof (struct GNUNET_HashCode) !=
+ GNUNET_DISK_file_read (fh, nsid, sizeof (struct GNUNET_HashCode)))
{
GNUNET_DISK_file_close (fh);
return GNUNET_SYSERR;
{
struct ListPseudonymClosure *c = cls;
int ret;
- GNUNET_HashCode id;
- int rating;
+ struct GNUNET_HashCode id;
+ int32_t rating;
struct GNUNET_CONTAINER_MetaData *meta;
const char *fn;
char *str;
+ char *name_unique;
if (strlen (fullname) < sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded))
return GNUNET_OK;
if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (fn, &id))
return GNUNET_OK; /* invalid name */
str = NULL;
- if (GNUNET_OK != read_info (c->cfg, &id, &meta, &rating, &str))
- return GNUNET_OK; /* ignore entry */
- GNUNET_free_non_null (str);
+ if (GNUNET_OK != GNUNET_PSEUDONYM_get_info (c->cfg, &id, &meta, &rating,
+ &str, NULL))
+ {
+ /* ignore entry. FIXME: Why? Lack of data about a pseudonym is not a reason
+ * to ignore it... So yeah, it will have placeholders instead of name,
+ * empty metadata container and a default rank == -1, so what? We know
+ * its nsid - that's all we really need. Right? */
+ GNUNET_free (str);
+ GNUNET_CONTAINER_meta_data_destroy (meta);
+ return GNUNET_OK;
+ }
+ name_unique = GNUNET_PSEUDONYM_name_uniquify (c->cfg, &id, str, NULL);
if (c->iterator != NULL)
- ret = c->iterator (c->closure, &id, meta, rating);
+ ret = c->iterator (c->closure, &id, str, name_unique, meta, rating);
+ GNUNET_free_non_null (str);
+ GNUNET_free_non_null (name_unique);
GNUNET_CONTAINER_meta_data_destroy (meta);
return ret;
}
*/
int
GNUNET_PSEUDONYM_rank (const struct GNUNET_CONFIGURATION_Handle *cfg,
- const GNUNET_HashCode * nsid, int delta)
+ const struct GNUNET_HashCode * nsid, int delta)
{
struct GNUNET_CONTAINER_MetaData *meta;
int ret;
}
+/**
+ * Set the pseudonym metadata, rank and name.
+ *
+ * @param cfg overall configuration
+ * @param nsid id of the pseudonym
+ * @param name name to set. Must be the non-unique version of it.
+ * May be NULL, in which case it erases pseudonym's name!
+ * @param md metadata to set
+ * May be NULL, in which case it erases pseudonym's metadata!
+ * @param rank rank to assign
+ * @return GNUNET_OK on success, GNUNET_SYSERR on failure
+ */
+int
+GNUNET_PSEUDONYM_set_info (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const struct GNUNET_HashCode * nsid, const char *name,
+ const struct GNUNET_CONTAINER_MetaData *md, int rank)
+{
+ GNUNET_assert (cfg != NULL);
+ GNUNET_assert (nsid != NULL);
+
+ write_pseudonym_info (cfg, nsid, md, rank, name);
+ return GNUNET_OK;
+}
+
+
/**
* Add a pseudonym to the set of known pseudonyms.
* For all pseudonym advertisements that we discover
*/
void
GNUNET_PSEUDONYM_add (const struct GNUNET_CONFIGURATION_Handle *cfg,
- const GNUNET_HashCode * id,
+ const struct GNUNET_HashCode * id,
const struct GNUNET_CONTAINER_MetaData *meta)
{
char *name;