/**
* 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;
}
/**
* 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)
{
GNUNET_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);
//.........这里部分代码省略.........
/**
* Test if the service is running. If we are given a UNIXPATH or a local address,
* we do this NOT by trying to connect to the service, but by trying to BIND to
* the same port. If the BIND fails, we know the service is running.
*
* @param service name of the service to wait for
* @param cfg configuration to use
* @param timeout how long to wait at most
* @param task task to run if service is running
* (reason will be "PREREQ_DONE" (service running)
* or "TIMEOUT" (service not known to be running))
* @param task_cls closure for task
*/
void
GNUNET_CLIENT_service_test (const char *service,
const struct GNUNET_CONFIGURATION_Handle *cfg,
struct GNUNET_TIME_Relative timeout,
GNUNET_SCHEDULER_Task task, void *task_cls)
{
char *hostname;
unsigned long long port;
struct GNUNET_NETWORK_Handle *sock;
struct GNUNET_CLIENT_Connection *client;
LOG (GNUNET_ERROR_TYPE_DEBUG, "Testing if service `%s' is running.\n",
service);
#ifdef AF_UNIX
{
/* probe UNIX support */
struct sockaddr_un s_un;
size_t slen;
char *unixpath;
unixpath = NULL;
if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, service, "UNIXPATH", &unixpath)) && (0 < strlen (unixpath))) /* We have a non-NULL unixpath, does that mean it's valid? */
{
if (strlen (unixpath) >= sizeof (s_un.sun_path))
{
LOG (GNUNET_ERROR_TYPE_WARNING,
_("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath,
(unsigned long long) sizeof (s_un.sun_path));
unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
LOG (GNUNET_ERROR_TYPE_INFO,
_("Using `%s' instead\n"), unixpath);
}
}
if (NULL != unixpath)
{
sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
if (NULL != sock)
{
memset (&s_un, 0, sizeof (s_un));
s_un.sun_family = AF_UNIX;
slen = strlen (unixpath) + 1;
if (slen >= sizeof (s_un.sun_path))
slen = sizeof (s_un.sun_path) - 1;
memcpy (s_un.sun_path, unixpath, slen);
s_un.sun_path[slen] = '\0';
slen = sizeof (struct sockaddr_un);
#if LINUX
s_un.sun_path[0] = '\0';
#endif
#if HAVE_SOCKADDR_IN_SIN_LEN
s_un.sun_len = (u_char) slen;
#endif
if (GNUNET_OK !=
GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_un,
slen))
{
/* failed to bind => service must be running */
GNUNET_free (unixpath);
(void) GNUNET_NETWORK_socket_close (sock);
GNUNET_SCHEDULER_add_continuation (task, task_cls,
GNUNET_SCHEDULER_REASON_PREREQ_DONE);
return;
}
(void) GNUNET_NETWORK_socket_close (sock);
/* let's try IP */
}
}
GNUNET_free_non_null (unixpath);
}
#endif
hostname = NULL;
if ((GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (cfg, service, "PORT", &port)) ||
(port > 65535) ||
(GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (cfg, service, "HOSTNAME",
&hostname)))
{
/* UNIXPATH failed (if possible) AND IP failed => error */
service_test_error (task, task_cls);
return;
}
if (0 == strcmp ("localhost", hostname)
#if !LINUX
&& 0
//.........这里部分代码省略.........
/**
* Try to connect to the service.
*
* @param service_name name of service to connect to
* @param cfg configuration to use
* @param attempt counter used to alternate between IP and UNIX domain sockets
* @return NULL on error
*/
static struct GNUNET_CONNECTION_Handle *
do_connect (const char *service_name,
const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int attempt)
{
struct GNUNET_CONNECTION_Handle *connection;
char *hostname;
unsigned long long port;
connection = NULL;
if (0 == (attempt % 2))
{
/* on even rounds, try UNIX first */
connection = try_unixpath (service_name, cfg);
if (NULL != connection)
return connection;
}
if (GNUNET_YES ==
GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT"))
{
if ((GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (cfg, service_name, "PORT", &port))
|| (port > 65535) ||
(GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "HOSTNAME",
&hostname)))
{
LOG (GNUNET_ERROR_TYPE_WARNING,
_
("Could not determine valid hostname and port for service `%s' from configuration.\n"),
service_name);
return NULL;
}
if (0 == strlen (hostname))
{
GNUNET_free (hostname);
LOG (GNUNET_ERROR_TYPE_WARNING,
_("Need a non-empty hostname for service `%s'.\n"), service_name);
return NULL;
}
}
else
{
/* unspecified means 0 (disabled) */
port = 0;
hostname = NULL;
}
if (0 == port)
{
/* if port is 0, try UNIX */
connection = try_unixpath (service_name, cfg);
if (NULL != connection)
return connection;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Port is 0 for service `%s', UNIXPATH did not work, returning NULL!\n",
service_name);
GNUNET_free_non_null (hostname);
return NULL;
}
connection = GNUNET_CONNECTION_create_from_connect (cfg, hostname, port);
GNUNET_free (hostname);
return connection;
}
请发表评论