gnunet

Main GNUnet Logic
Log | Files | Refs | Submodules | README | LICENSE

commit 50eaf8d7de763d25b7dae7ffdee8d7c6b5fe71ea
parent 3cbdbe18dbd56def00c0014381ff90b4ee664904
Author: Gabor X Toth <*@tg-x.net>
Date:   Tue, 12 Jan 2016 23:26:47 +0000

psycutil reorg: message, env, slicer

Diffstat:
Mconfigure.ac | 2+-
Msrc/Makefile.am | 2+-
Dsrc/env/Makefile.am | 43-------------------------------------------
Dsrc/env/env.c | 195-------------------------------------------------------------------------------
Dsrc/env/test_env.c | 95-------------------------------------------------------------------------------
Msrc/include/Makefile.am | 4+++-
Dsrc/include/gnunet_env_lib.h | 340-------------------------------------------------------------------------------
Asrc/include/gnunet_psyc_env.h | 340+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/gnunet_psyc_message.h | 273+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/include/gnunet_psyc_service.h | 47+++++++++++++++++++++++++++--------------------
Asrc/include/gnunet_psyc_slicer.h | 319+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/include/gnunet_psyc_util_lib.h | 227++-----------------------------------------------------------------------------
Msrc/include/gnunet_psycstore_plugin.h | 2+-
Msrc/include/gnunet_psycstore_service.h | 4++--
Msrc/include/gnunet_social_service.h | 293++++++-------------------------------------------------------------------------
Msrc/psyc/Makefile.am | 8+++-----
Msrc/psyc/gnunet-service-psyc.c | 2+-
Msrc/psyc/psyc_api.c | 1-
Msrc/psyc/test_psyc.c | 37++++++++++++++++++-------------------
Msrc/psycstore/Makefile.am | 14++------------
Msrc/psycstore/gnunet-service-psycstore.c | 4++--
Msrc/psycstore/plugin_psycstore_sqlite.c | 6+++---
Dsrc/psycstore/psyc_util_lib.c | 1330-------------------------------------------------------------------------------
Msrc/psycstore/psycstore_api.c | 2+-
Msrc/psycstore/test_plugin_psycstore.c | 13+++++++------
Msrc/psycstore/test_psycstore.c | 6+++---
Asrc/psycutil/Makefile.am | 45+++++++++++++++++++++++++++++++++++++++++++++
Asrc/psycutil/psyc_env.c | 196+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/psycutil/psyc_message.c | 1329+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/psycutil/psyc_slicer.c | 610++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/psycutil/test_psyc_env.c | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/social/Makefile.am | 8+++-----
Msrc/social/gnunet-service-social.c | 6+++---
Msrc/social/social.h | 32++++++++++++++------------------
Msrc/social/social_api.c | 690+++++++------------------------------------------------------------------------
Msrc/social/test_social.c | 127+++++++++++++++++++++++++++++++++++++++----------------------------------------
36 files changed, 3449 insertions(+), 3299 deletions(-)

diff --git a/configure.ac b/configure.ac @@ -1537,7 +1537,6 @@ src/dns/Makefile src/dns/dns.conf src/dv/Makefile src/dv/dv.conf -src/env/Makefile src/exit/Makefile src/fragmentation/Makefile src/fs/Makefile @@ -1568,6 +1567,7 @@ src/peerinfo-tool/Makefile src/peerstore/Makefile src/peerstore/peerstore.conf src/postgres/Makefile +src/psycutil/Makefile src/psyc/Makefile src/psyc/psyc.conf src/psycstore/Makefile diff --git a/src/Makefile.am b/src/Makefile.am @@ -16,7 +16,7 @@ if HAVE_EXPERIMENTAL EXP_DIR = \ dv \ multicast \ - env \ + psycutil \ psycstore \ psyc \ rps \ diff --git a/src/env/Makefile.am b/src/env/Makefile.am @@ -1,43 +0,0 @@ -# This Makefile.am is in the public domain -AM_CPPFLAGS = -I$(top_srcdir)/src/include - -pkgcfgdir= $(pkgdatadir)/config.d/ - -libexecdir= $(pkglibdir)/libexec/ - -if MINGW - WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -endif - -if USE_COVERAGE - AM_CFLAGS = --coverage -O0 - XLIB = -lgcov -endif - -lib_LTLIBRARIES = libgnunetenv.la - -libgnunetenv_la_SOURCES = \ - env.c -libgnunetenv_la_LIBADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(GN_LIBINTL) $(XLIB) -libgnunetenv_la_LDFLAGS = \ - $(GN_LIB_LDFLAGS) $(WINFLAGS) \ - -version-info 0:0:0 - -if HAVE_TESTING -check_PROGRAMS = \ - test_env -endif - -if ENABLE_TEST_RUN -AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; -TESTS = $(check_PROGRAMS) -endif - -test_env_SOURCES = \ - test_env.c -test_env_LDADD = \ - libgnunetenv.la \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/util/libgnunetutil.la diff --git a/src/env/env.c b/src/env/env.c @@ -1,195 +0,0 @@ -/* - * This file is part of GNUnet. - * Copyright (C) 2013 Christian Grothoff (and other contributing authors) - * - * 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 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. - */ - -/** - * @file env/env.c - * @brief Library providing operations for the @e environment of - * PSYC and Social messages, and for (de)serializing variable values. - * @author Gabor X Toth - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_env_lib.h" - -/** - * Environment for a message. - * - * Contains modifiers. - */ -struct GNUNET_ENV_Environment -{ - struct GNUNET_ENV_Modifier *mod_head; - struct GNUNET_ENV_Modifier *mod_tail; - size_t mod_count; -}; - - -/** - * Create an environment. - * - * @return A newly allocated environment. - */ -struct GNUNET_ENV_Environment * -GNUNET_ENV_environment_create () -{ - return GNUNET_new (struct GNUNET_ENV_Environment); -} - - -/** - * Add a modifier to the environment. - * - * @param env The environment. - * @param oper Operation to perform. - * @param name Name of the variable. - * @param value Value of the variable. - * @param value_size Size of @a value. - */ -void -GNUNET_ENV_environment_add (struct GNUNET_ENV_Environment *env, - enum GNUNET_ENV_Operator oper, const char *name, - const void *value, size_t value_size) -{ - struct GNUNET_ENV_Modifier *mod = GNUNET_new (struct GNUNET_ENV_Modifier); - mod->oper = oper; - mod->name = name; - mod->value = value; - mod->value_size = value_size; - GNUNET_CONTAINER_DLL_insert_tail (env->mod_head, env->mod_tail, mod); - env->mod_count++; -} - - -/** - * Get the first modifier of the environment. - */ -struct GNUNET_ENV_Modifier * -GNUNET_ENV_environment_head (const struct GNUNET_ENV_Environment *env) -{ - return env->mod_head; -} - - -/** - * Get the last modifier of the environment. - */ -struct GNUNET_ENV_Modifier * -GNUNET_ENV_environment_tail (const struct GNUNET_ENV_Environment *env) -{ - return env->mod_tail; -} - - -/** - * Remove a modifier from the environment. - */ -void -GNUNET_ENV_environment_remove (struct GNUNET_ENV_Environment *env, - struct GNUNET_ENV_Modifier *mod) -{ - GNUNET_CONTAINER_DLL_remove (env->mod_head, env->mod_tail, mod); -} - - -/** - * Get the modifier at the beginning of an environment and remove it. - * - * @param env - * @param oper - * @param name - * @param value - * @param value_size - * - * @return - */ -int -GNUNET_ENV_environment_shift (struct GNUNET_ENV_Environment *env, - enum GNUNET_ENV_Operator *oper, const char **name, - const void **value, size_t *value_size) -{ - if (NULL == env->mod_head) - return GNUNET_NO; - - struct GNUNET_ENV_Modifier *mod = env->mod_head; - *oper = mod->oper; - *name = mod->name; - *value = mod->value; - *value_size = mod->value_size; - - GNUNET_CONTAINER_DLL_remove (env->mod_head, env->mod_tail, mod); - GNUNET_free (mod); - env->mod_count--; - - return GNUNET_YES; -} - - -/** - * Iterate through all modifiers in the environment. - * - * @param env The environment. - * @param it Iterator. - * @param it_cls Closure for iterator. - */ -void -GNUNET_ENV_environment_iterate (const struct GNUNET_ENV_Environment *env, - GNUNET_ENV_Iterator it, void *it_cls) -{ - struct GNUNET_ENV_Modifier *mod; - for (mod = env->mod_head; NULL != mod; mod = mod->next) - it (it_cls, mod->oper, mod->name, mod->value, mod->value_size); -} - - -/** - * Get the number of modifiers in the environment. - * - * @param env The environment. - * - * @return Number of modifiers. - */ -size_t -GNUNET_ENV_environment_get_count (const struct GNUNET_ENV_Environment *env) -{ - return env->mod_count; -} - - -/** - * Destroy an environment. - * - * @param env The environment to destroy. - */ -void -GNUNET_ENV_environment_destroy (struct GNUNET_ENV_Environment *env) -{ - struct GNUNET_ENV_Modifier *mod, *prev = NULL; - for (mod = env->mod_head; NULL != mod; mod = mod->next) - { - if (NULL != prev) - GNUNET_free (prev); - prev = mod; - } - if (NULL != prev) - GNUNET_free (prev); - - GNUNET_free (env); -} diff --git a/src/env/test_env.c b/src/env/test_env.c @@ -1,95 +0,0 @@ -/* - * This file is part of GNUnet. - * Copyright (C) 2013 Christian Grothoff (and other contributing authors) - * - * 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 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. - */ - -/** - * @file env/test_env.c - * @brief Tests for the environment library. - * @author Gabor X Toth - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testing_lib.h" -#include "gnunet_env_lib.h" - -struct GNUNET_ENV_Modifier mods[] = { - { .oper = GNUNET_ENV_OP_SET, - .name = "_foo", .value = "foo", .value_size = 3 }, - - { .oper = GNUNET_ENV_OP_ASSIGN, - .name = "_foo_bar", .value = "foo bar", .value_size = 7 }, - - { .oper = GNUNET_ENV_OP_AUGMENT, - .name = "_foo_bar_baz", .value = "foo bar baz", .value_size = 11 } -}; - -struct ItCls -{ - size_t n; -}; - -int -iterator (void *cls, enum GNUNET_ENV_Operator oper, - const char *name, const char *value, uint32_t value_size) -{ - struct ItCls *it_cls = cls; - struct GNUNET_ENV_Modifier *m = &mods[it_cls->n++]; - - GNUNET_assert (oper == m->oper); - GNUNET_assert (value_size == m->value_size); - GNUNET_assert (0 == memcmp (name, m->name, strlen (m->name))); - GNUNET_assert (0 == memcmp (value, m->value, m->value_size)); - - return GNUNET_YES; -} - -int -main (int argc, char *argv[]) -{ - GNUNET_log_setup ("test-env", "WARNING", NULL); - - struct GNUNET_ENV_Environment *env = GNUNET_ENV_environment_create (); - GNUNET_assert (NULL != env); - int i, len = 3; - - for (i = 0; i < len; i++) - { - GNUNET_ENV_environment_add (env, mods[i].oper, mods[i].name, - mods[i].value, mods[i].value_size); - } - - struct ItCls it_cls = { .n = 0 }; - GNUNET_ENV_environment_iterate (env, iterator, &it_cls); - GNUNET_assert (len == it_cls.n); - - for (i = 0; i < len; i++) - { - enum GNUNET_ENV_Operator oper; - const char *name; - const void *value; - size_t value_size; - GNUNET_ENV_environment_shift (env, &oper, &name, &value, &value_size); - GNUNET_assert (len - i - 1 == GNUNET_ENV_environment_get_count (env)); - } - - GNUNET_ENV_environment_destroy (env); - - return 0; -} diff --git a/src/include/Makefile.am b/src/include/Makefile.am @@ -55,7 +55,6 @@ gnunetinclude_HEADERS = \ gnunet_dnsstub_lib.h \ gnunet_dns_service.h \ gnunet_dv_service.h \ - gnunet_env_lib.h \ gnunet_fragmentation_lib.h \ gnunet_friends_lib.h \ gnunet_fs_service.h \ @@ -90,6 +89,9 @@ gnunetinclude_HEADERS = \ gnunet_psycstore_service.h \ gnunet_psyc_service.h \ gnunet_psyc_util_lib.h \ + gnunet_psyc_env.h \ + gnunet_psyc_message.h \ + gnunet_psyc_slicer.h \ gnunet_program_lib.h \ gnunet_protocols.h \ gnunet_resolver_service.h \ diff --git a/src/include/gnunet_env_lib.h b/src/include/gnunet_env_lib.h @@ -1,340 +0,0 @@ -/* - * This file is part of GNUnet. - * Copyright (C) 2013 Christian Grothoff (and other contributing authors) - * - * 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 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. - */ - -/** - * @author Gabor X Toth - * - * @file - * Environment library - * - * @defgroup env Environment library - * Environment data structure for PSYC and Social messages. - * - * Library providing operations for the @e environment of - * PSYC and Social messages, and for (de)serializing variable values. - * - * @{ - */ - - -#ifndef GNUNET_ENV_LIB_H -#define GNUNET_ENV_LIB_H - -#ifdef __cplusplus -extern "C" -{ -#if 0 /* keep Emacsens' auto-indent happy */ -} -#endif -#endif - - -/** - * Possible operations on PSYC state (persistent) and transient variables (per message). - */ -enum GNUNET_ENV_Operator -{ - /** - * Set value of a transient variable. - */ - GNUNET_ENV_OP_SET = ':', - - /** - * Assign value for a persistent state variable. - * - * If an assigned value is NULL, the variable is deleted. - */ - GNUNET_ENV_OP_ASSIGN = '=', - - /** - * Augment state variable. - * - * Used for appending strings, adding numbers, and adding new items to a list or dictionary. - */ - GNUNET_ENV_OP_AUGMENT = '+', - - /** - * Diminish state variable. - * - * Used for subtracting numbers, and removing items from a list or dictionary. - */ - GNUNET_ENV_OP_DIMINISH = '-', - - /** - * Update state variable. - * - * Used for modifying a single item of a list or dictionary. - */ - GNUNET_ENV_OP_UPDATE = '@', -}; - - -/** - * PSYC variable types. - */ -enum GNUNET_ENV_Type -{ - GNUNET_ENV_TYPE_DATA = 0, - GNUNET_ENV_TYPE_NUMBER, - GNUNET_ENV_TYPE_LIST, - GNUNET_ENV_TYPE_DICT -}; - - -/** - * PSYC state modifier. - */ -struct GNUNET_ENV_Modifier -{ - /** - * State operation. - */ - enum GNUNET_ENV_Operator oper; - - /** - * Variable name. - */ - const char *name; - - /** - * Size of @a value. - */ - size_t value_size; - - /** - * Value of variable. - */ - const void *value; - - /** - * Next modifier. - */ - struct GNUNET_ENV_Modifier *next; - - /** - * Previous modifier. - */ - struct GNUNET_ENV_Modifier *prev; -}; - - -/** - * Environment for a message. - * - * Contains modifiers. - */ -struct GNUNET_ENV_Environment; - - -/** - * Create an environment. - * - * @return A newly allocated environment. - */ -struct GNUNET_ENV_Environment * -GNUNET_ENV_environment_create (); - - -/** - * Add a modifier to the environment. - * - * @param env The environment. - * @param oper Operation to perform. - * @param name Name of the variable. - * @param value Value of the variable. - * @param value_size Size of @a value. - */ -void -GNUNET_ENV_environment_add (struct GNUNET_ENV_Environment *env, - enum GNUNET_ENV_Operator oper, const char *name, - const void *value, size_t value_size); - - -/** - * Get the first modifier of the environment. - */ -struct GNUNET_ENV_Modifier * -GNUNET_ENV_environment_head (const struct GNUNET_ENV_Environment *env); - - - -/** - * Get the last modifier of the environment. - */ -struct GNUNET_ENV_Modifier * -GNUNET_ENV_environment_tail (const struct GNUNET_ENV_Environment *env); - - -/** - * Remove a modifier from the environment. - */ -void -GNUNET_ENV_environment_remove (struct GNUNET_ENV_Environment *env, - struct GNUNET_ENV_Modifier *mod); - - -/** - * Remove a modifier at the beginning of the environment. - */ -int -GNUNET_ENV_environment_shift (struct GNUNET_ENV_Environment *env, - enum GNUNET_ENV_Operator *oper, const char **name, - const void **value, size_t *value_size); - - -/** - * Iterator for modifiers in the environment. - * - * @param cls Closure. - * @param mod Modifier. - * - * @return #GNUNET_YES to continue iterating, - * #GNUNET_NO to stop. - */ -typedef int -(*GNUNET_ENV_Iterator) (void *cls, enum GNUNET_ENV_Operator oper, - const char *name, const char *value, - uint32_t value_size); - - -/** - * Iterate through all modifiers in the environment. - * - * @param env The environment. - * @param it Iterator. - * @param it_cls Closure for iterator. - */ -void -GNUNET_ENV_environment_iterate (const struct GNUNET_ENV_Environment *env, - GNUNET_ENV_Iterator it, void *it_cls); - - -/** - * Get the number of modifiers in the environment. - * - * @param env The environment. - * - * @return Number of modifiers. - */ -size_t -GNUNET_ENV_environment_get_count (const struct GNUNET_ENV_Environment *env); - - -/** - * Destroy an environment. - * - * @param env The environment to destroy. - */ -void -GNUNET_ENV_environment_destroy (struct GNUNET_ENV_Environment *env); - - -/** - * Get the type of variable. - * - * @param name Name of the variable. - * - * @return Variable type. - */ -enum GNUNET_ENV_Type -GNUNET_ENV_var_get_type (char *name); - - -/** - * Perform an operation on a variable. - * - * @param name Name of variable. - * @param current_value Current value of variable. - * @param current_value_size Size of @a current_value. - * @param oper Operator. - * @param args Arguments for the operation. - * @param args_size Size of @a args. - * @param return_value Return value. - * @param return_value_size Size of @a return_value. - * - * @return #GNUNET_OK on success, else #GNUNET_SYSERR - */ -int -GNUNET_ENV_operation (char *name, void *current_value, size_t current_value_size, - enum GNUNET_ENV_Operator oper, void *args, size_t args_size, - void **return_value, size_t *return_value_size); - - -/** - * Get the variable's value as an integer. - * - * @param size Size of value. - * @param value Raw value of variable. - * @param[out] number Value converted to a 64-bit integer. - * - * @return #GNUNET_OK on success, #GNUNET_SYSERR if an error occurred (e.g. the value is invalid). - */ -int -GNUNET_ENV_value_to_number (size_t size, const void *value, int64_t *number); - - -/** - * Get the variable's value as a dictionary. - * - * @param size Size of value. - * @param value Raw value of variable. - * @param[out] dict A newly created hashmap holding the elements of the dictionary. - * - * @return #GNUNET_OK on success, #GNUNET_SYSERR if an error occurred (e.g. the value is invalid). - */ -int -GNUNET_ENV_value_to_dict (size_t size, const void *value, struct GNUNET_CONTAINER_MultiHashMap **dict); - - -/** - * Create a PSYC variable value from an integer. - * - * @param number The number to convert. - * @param[out] value_size Size of returned value. - * - * @return A newly allocated value or NULL on error. - */ -void * -GNUNET_ENV_value_from_number (int64_t number, size_t *value_size); - - -/** - * Create a PSYC variable value from a dictionary. - * - * @param dict The dict to convert. - * @param[out] value_size Size of returned value. - * - * @return A newly allocated value or NULL on error. - */ -void * -GNUNET_ENV_value_from_dict (struct GNUNET_CONTAINER_MultiHashMap *dict, size_t *value_size); - - -#if 0 /* keep Emacsens' auto-indent happy */ -{ -#endif -#ifdef __cplusplus -} -#endif - -/* ifndef GNUNET_ENV_LIB_H */ -#endif - -/** @} */ /* end of group */ diff --git a/src/include/gnunet_psyc_env.h b/src/include/gnunet_psyc_env.h @@ -0,0 +1,340 @@ +/* + * This file is part of GNUnet. + * Copyright (C) 2013 Christian Grothoff (and other contributing authors) + * + * 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 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. + */ + +/** + * @author Gabor X Toth + * + * @file + * PSYC Environment library + * + * @defgroup psyc-util-env PSYC Utilities library: Environment + * Environment data structure operations for PSYC and Social messages. + * + * Library providing operations for the @e environment of + * PSYC and Social messages, and for (de)serializing variable values. + * + * @{ + */ + + +#ifndef GNUNET_PSYC_ENV_H +#define GNUNET_PSYC_ENV_H + +#ifdef __cplusplus +extern "C" +{ +#if 0 /* keep Emacsens' auto-indent happy */ +} +#endif +#endif + + +/** + * Possible operations on PSYC state (persistent) and transient variables (per message). + */ +enum GNUNET_PSYC_Operator +{ + /** + * Set value of a transient variable. + */ + GNUNET_PSYC_OP_SET = ':', + + /** + * Assign value for a persistent state variable. + * + * If an assigned value is NULL, the variable is deleted. + */ + GNUNET_PSYC_OP_ASSIGN = '=', + + /** + * Augment state variable. + * + * Used for appending strings, adding numbers, and adding new items to a list or dictionary. + */ + GNUNET_PSYC_OP_AUGMENT = '+', + + /** + * Diminish state variable. + * + * Used for subtracting numbers, and removing items from a list or dictionary. + */ + GNUNET_PSYC_OP_DIMINISH = '-', + + /** + * Update state variable. + * + * Used for modifying a single item of a list or dictionary. + */ + GNUNET_PSYC_OP_UPDATE = '@', +}; + + +/** + * PSYC variable types. + */ +enum GNUNET_PSYC_Type +{ + GNUNET_PSYC_TYPE_DATA = 0, + GNUNET_PSYC_TYPE_NUMBER, + GNUNET_PSYC_TYPE_LIST, + GNUNET_PSYC_TYPE_DICT +}; + + +/** + * PSYC state modifier. + */ +struct GNUNET_PSYC_Modifier +{ + /** + * State operation. + */ + enum GNUNET_PSYC_Operator oper; + + /** + * Variable name. + */ + const char *name; + + /** + * Size of @a value. + */ + size_t value_size; + + /** + * Value of variable. + */ + const void *value; + + /** + * Next modifier. + */ + struct GNUNET_PSYC_Modifier *next; + + /** + * Previous modifier. + */ + struct GNUNET_PSYC_Modifier *prev; +}; + + +/** + * Environment for a message. + * + * Contains modifiers. + */ +struct GNUNET_PSYC_Environment; + + +/** + * Create an environment. + * + * @return A newly allocated environment. + */ +struct GNUNET_PSYC_Environment * +GNUNET_PSYC_env_create (); + + +/** + * Add a modifier to the environment. + * + * @param env The environment. + * @param oper Operation to perform. + * @param name Name of the variable. + * @param value Value of the variable. + * @param value_size Size of @a value. + */ +void +GNUNET_PSYC_env_add (struct GNUNET_PSYC_Environment *env, + enum GNUNET_PSYC_Operator oper, const char *name, + const void *value, size_t value_size); + + +/** + * Get the first modifier of the environment. + */ +struct GNUNET_PSYC_Modifier * +GNUNET_PSYC_env_head (const struct GNUNET_PSYC_Environment *env); + + + +/** + * Get the last modifier of the environment. + */ +struct GNUNET_PSYC_Modifier * +GNUNET_PSYC_env_tail (const struct GNUNET_PSYC_Environment *env); + + +/** + * Remove a modifier from the environment. + */ +void +GNUNET_PSYC_env_remove (struct GNUNET_PSYC_Environment *env, + struct GNUNET_PSYC_Modifier *mod); + + +/** + * Remove a modifier at the beginning of the environment. + */ +int +GNUNET_PSYC_env_shift (struct GNUNET_PSYC_Environment *env, + enum GNUNET_PSYC_Operator *oper, const char **name, + const void **value, size_t *value_size); + + +/** + * Iterator for modifiers in the environment. + * + * @param cls Closure. + * @param mod Modifier. + * + * @return #GNUNET_YES to continue iterating, + * #GNUNET_NO to stop. + */ +typedef int +(*GNUNET_PSYC_Iterator) (void *cls, enum GNUNET_PSYC_Operator oper, + const char *name, const char *value, + uint32_t value_size); + + +/** + * Iterate through all modifiers in the environment. + * + * @param env The environment. + * @param it Iterator. + * @param it_cls Closure for iterator. + */ +void +GNUNET_PSYC_env_iterate (const struct GNUNET_PSYC_Environment *env, + GNUNET_PSYC_Iterator it, void *it_cls); + + +/** + * Get the number of modifiers in the environment. + * + * @param env The environment. + * + * @return Number of modifiers. + */ +size_t +GNUNET_PSYC_env_get_count (const struct GNUNET_PSYC_Environment *env); + + +/** + * Destroy an environment. + * + * @param env The environment to destroy. + */ +void +GNUNET_PSYC_env_destroy (struct GNUNET_PSYC_Environment *env); + + +/** + * Get the type of variable. + * + * @param name Name of the variable. + * + * @return Variable type. + */ +enum GNUNET_PSYC_Type +GNUNET_PSYC_var_get_type (char *name); + + +/** + * Perform an operation on a variable. + * + * @param name Name of variable. + * @param current_value Current value of variable. + * @param current_value_size Size of @a current_value. + * @param oper Operator. + * @param args Arguments for the operation. + * @param args_size Size of @a args. + * @param return_value Return value. + * @param return_value_size Size of @a return_value. + * + * @return #GNUNET_OK on success, else #GNUNET_SYSERR + */ +int +GNUNET_PSYC_operation (char *name, void *current_value, size_t current_value_size, + enum GNUNET_PSYC_Operator oper, void *args, size_t args_size, + void **return_value, size_t *return_value_size); + + +/** + * Get the variable's value as an integer. + * + * @param size Size of value. + * @param value Raw value of variable. + * @param[out] number Value converted to a 64-bit integer. + * + * @return #GNUNET_OK on success, #GNUNET_SYSERR if an error occurred (e.g. the value is invalid). + */ +int +GNUNET_PSYC_value_to_number (size_t size, const void *value, int64_t *number); + + +/** + * Get the variable's value as a dictionary. + * + * @param size Size of value. + * @param value Raw value of variable. + * @param[out] dict A newly created hashmap holding the elements of the dictionary. + * + * @return #GNUNET_OK on success, #GNUNET_SYSERR if an error occurred (e.g. the value is invalid). + */ +int +GNUNET_PSYC_value_to_dict (size_t size, const void *value, struct GNUNET_CONTAINER_MultiHashMap **dict); + + +/** + * Create a PSYC variable value from an integer. + * + * @param number The number to convert. + * @param[out] value_size Size of returned value. + * + * @return A newly allocated value or NULL on error. + */ +void * +GNUNET_PSYC_value_from_number (int64_t number, size_t *value_size); + + +/** + * Create a PSYC variable value from a dictionary. + * + * @param dict The dict to convert. + * @param[out] value_size Size of returned value. + * + * @return A newly allocated value or NULL on error. + */ +void * +GNUNET_PSYC_value_from_dict (struct GNUNET_CONTAINER_MultiHashMap *dict, size_t *value_size); + + +#if 0 /* keep Emacsens' auto-indent happy */ +{ +#endif +#ifdef __cplusplus +} +#endif + +/* ifndef GNUNET_PSYC_ENV_H */ +#endif + +/** @} */ /* end of group */ diff --git a/src/include/gnunet_psyc_message.h b/src/include/gnunet_psyc_message.h @@ -0,0 +1,273 @@ +/* + This file is part of GNUnet. + Copyright (C) 2012, 2013 Christian Grothoff (and other contributing authors) + + 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 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. +*/ + +/** + * @author Gabor X Toth + * + * @file + * PSYC message utilities; receiving/transmitting/logging PSYC messages + * + * @defgroup psyc-util-message PSYC Utilities library: Messages + * Receiving, transmitting, logging PSYC messages. + * @{ + */ + +#ifndef GNUNET_PSYC_MESSAGE_H +#define GNUNET_PSYC_MESSAGE_H + +#ifdef __cplusplus +extern "C" +{ +#if 0 /* keep Emacsens' auto-indent happy */ +} +#endif +#endif + + +#include "gnunet_util_lib.h" +#include "gnunet_psyc_util_lib.h" +#include "gnunet_psyc_service.h" + + +/** + * Create a PSYC message. + * + * @param method_name + * PSYC method for the message. + * @param env + * Environment for the message. + * @param data + * Data payload for the message. + * @param data_size + * Size of @a data. + * + * @return Message header with size information, + * followed by the message parts. + */ +struct GNUNET_PSYC_Message * +GNUNET_PSYC_message_create (const char *method_name, + const struct GNUNET_PSYC_Environment *env, + const void *data, + size_t data_size); + +/** + * Parse PSYC message. + * + * @param msg + * The PSYC message to parse. + * @param env + * The environment for the message with a list of modifiers. + * @param[out] method_name + * Pointer to the method name inside @a pmsg. + * @param[out] data + * Pointer to data inside @a pmsg. + * @param[out] data_size + * Size of @data is written here. + * + * @return #GNUNET_OK on success, + * #GNUNET_SYSERR on parse error. + */ +int +GNUNET_PSYC_message_parse (const struct GNUNET_PSYC_MessageHeader *msg, + const char **method_name, + struct GNUNET_PSYC_Environment *env, + const void **data, + uint16_t *data_size); + + +void +GNUNET_PSYC_log_message (enum GNUNET_ErrorType kind, + const struct GNUNET_MessageHeader *msg); + + +int +GNUNET_PSYC_check_message_parts (uint16_t data_size, const char *data, + uint16_t *first_ptype, uint16_t *last_ptype); + + +struct GNUNET_PSYC_TransmitHandle; + +/** + * Create a transmission handle. + */ +struct GNUNET_PSYC_TransmitHandle * +GNUNET_PSYC_transmit_create (); + + +/** + * Destroy a transmission handle. + */ +void +GNUNET_PSYC_transmit_destroy (struct GNUNET_PSYC_TransmitHandle *tmit); + + +/** + * Transmit a message. + * + * @param tmit + * Transmission handle. + * @param method_name + * Which method should be invoked. + * @param env + * Environment for the message. + * Should stay available until the first call to notify_data. + * Can be NULL if there are no modifiers or @a notify_mod is + * provided instead. + * @param notify_mod + * Function to call to obtain modifiers. + * Can be NULL if there are no modifiers or @a env is provided instead. + * @param notify_data + * Function to call to obtain fragments of the data. + * @param notify_cls + * Closure for @a notify_mod and @a notify_data. + * @param flags + * Flags for the message being transmitted. + * + * @return #GNUNET_OK if the transmission was started. + * #GNUNET_SYSERR if another transmission is already going on. + */ +int +GNUNET_PSYC_transmit_message (struct GNUNET_PSYC_TransmitHandle *tmit, + const char *method_name, + const struct GNUNET_PSYC_Environment *env, + GNUNET_PSYC_TransmitNotifyModifier notify_mod, + GNUNET_PSYC_TransmitNotifyData notify_data, + void *notify_cls, + uint32_t flags); + + +/** + * Resume transmission. + * + * @param tmit Transmission handle. + */ +void +GNUNET_PSYC_transmit_resume (struct GNUNET_PSYC_TransmitHandle *tmit); + + +/** + * Abort transmission request. + * + * @param tmit Transmission handle. + */ +void +GNUNET_PSYC_transmit_cancel (struct GNUNET_PSYC_TransmitHandle *tmit); + + +/** + * Got acknowledgement of a transmitted message part, continue transmission. + * + * @param tmit Transmission handle. + */ +void +GNUNET_PSYC_transmit_got_ack (struct GNUNET_PSYC_TransmitHandle *tmit); + + +struct GNUNET_PSYC_ReceiveHandle; + + +/** + * Create handle for receiving messages. + */ +struct GNUNET_PSYC_ReceiveHandle * +GNUNET_PSYC_receive_create (GNUNET_PSYC_MessageCallback message_cb, + GNUNET_PSYC_MessagePartCallback message_part_cb, + void *cb_cls); + + +/** + * Destroy handle for receiving messages. + */ +void +GNUNET_PSYC_receive_destroy (struct GNUNET_PSYC_ReceiveHandle *recv); + + +/** + * Reset stored data related to the last received message. + */ +void +GNUNET_PSYC_receive_reset (struct GNUNET_PSYC_ReceiveHandle *recv); + + +/** + * Handle incoming PSYC message. + * + * @param recv Receive handle. + * @param msg The message. + * + * @return #GNUNET_OK on success, + * #GNUNET_SYSERR on receive error. + */ +int +GNUNET_PSYC_receive_message (struct GNUNET_PSYC_ReceiveHandle *recv, + const struct GNUNET_PSYC_MessageHeader *msg); + + +/** + * Check if @a data contains a series of valid message parts. + * + * @param data_size Size of @a data. + * @param data Data. + * @param[out] first_ptype Type of first message part. + * @param[out] last_ptype Type of last message part. + * + * @return Number of message parts found in @a data. + * or GNUNET_SYSERR if the message contains invalid parts. + */ +int +GNUNET_PSYC_receive_check_parts (uint16_t data_size, const char *data, + uint16_t *first_ptype, uint16_t *last_ptype); + + +/** + * Initialize PSYC message header. + */ +void +GNUNET_PSYC_message_header_init (struct GNUNET_PSYC_MessageHeader *pmsg, + const struct GNUNET_MULTICAST_MessageHeader *mmsg, + uint32_t flags); + + +/** + * Create a new PSYC message header from a multicast message for sending it to clients. + */ +struct GNUNET_PSYC_MessageHeader * +GNUNET_PSYC_message_header_create (const struct GNUNET_MULTICAST_MessageHeader *mmsg, + uint32_t flags); + + +/** + * Create a new PSYC message header from a PSYC message. + */ +struct GNUNET_PSYC_MessageHeader * +GNUNET_PSYC_message_header_create_from_psyc (const struct GNUNET_PSYC_Message *msg); + + +#if 0 /* keep Emacsens' auto-indent happy */ +{ +#endif +#ifdef __cplusplus +} +#endif + +/* ifndef GNUNET_PSYC_MESSAGE_H */ +#endif + +/** @} */ /* end of group */ diff --git a/src/include/gnunet_psyc_service.h b/src/include/gnunet_psyc_service.h @@ -92,7 +92,6 @@ extern "C" #endif #include "gnunet_util_lib.h" -#include "gnunet_env_lib.h" #include "gnunet_multicast_service.h" //Mingw work around #ifdef MINGW @@ -917,33 +916,41 @@ enum GNUNET_PSYC_SlaveJoinFlags * notification on failure (as the channel may simply take days to approve, * and disapproval is simply being ignored). * - * @param cfg Configuration to use. - * @param channel_key ECC public key that identifies the channel we wish to join. - * @param slave_key ECC private-public key pair that identifies the slave, and + * @param cfg + * Configuration to use. + * @param channel_pub_key + * ECC public key that identifies the channel we wish to join. + * @param slave_key + * ECC private-public key pair that identifies the slave, and * used by multicast to sign the join request and subsequent unicast * requests sent to the master. - * @param origin Peer identity of the origin. - * @param relay_count Number of peers in the @a relays array. - * @param relays Peer identities of members of the multicast group, which serve + * @param flags + * Join flags. + * @param origin + * Peer identity of the origin. + * @param relay_count + * Number of peers in the @a relays array. + * @param relays + * Peer identities of members of the multicast group, which serve * as relays and used to join the group at. - * @param message_cb Function to invoke on message parts received from the - * channel, typically at least contains method handlers for @e join and - * @e part. - * @param slave_connect_cb Function invoked once we have connected to the - * PSYC service. - * @param join_decision_cb Function invoked once we have received a join - * decision. - * @param cls Closure for @a message_cb and @a slave_joined_cb. - * @param method_name Method name for the join request. - * @param env Environment containing transient variables for the request, or NULL. - * @param data Payload for the join message. - * @param data_size Number of bytes in @a data. + * @param message_cb + * Function to invoke on message fragments received from the channel. + * @param message_part_cb + * Function to invoke on message parts received from the channel. + * @param slave_connect_cb + * Function invoked once we have connected to the PSYC service. + * @param join_decision_cb + * Function invoked once we have received a join decision. + * @param cls + * Closure for @a message_cb and @a slave_joined_cb. + * @param join_msg + * Join message. * * @return Handle for the slave, NULL on error. */ struct GNUNET_PSYC_Slave * GNUNET_PSYC_slave_join (const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, + const struct GNUNET_CRYPTO_EddsaPublicKey *channel_pub_key, const struct GNUNET_CRYPTO_EcdsaPrivateKey *slave_key, enum GNUNET_PSYC_SlaveJoinFlags flags, const struct GNUNET_PeerIdentity *origin, diff --git a/src/include/gnunet_psyc_slicer.h b/src/include/gnunet_psyc_slicer.h @@ -0,0 +1,319 @@ +/* + This file is part of GNUnet. + Copyright (C) 2013 Christian Grothoff (and other contributing authors) + + 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 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. +*/ + +/** + * @author Gabor X Toth + * @author Christian Grothoff + * + * @file + * PSYC Slicer library + * + * @defgroup psyc-util-slicer PSYC Utilities library: Slicer + * Try-and-slice processing of PSYC method names and environment. + * @{ + */ + +#ifndef GNUNET_PSYC_SLICER_H +#define GNUNET_PSYC_SLICER_H + + +#ifdef __cplusplus +extern "C" +{ +#if 0 /* keep Emacsens' auto-indent happy */ +} +#endif +#endif + +#include "gnunet_util_lib.h" + + +/** + * Handle to an implementation of try-and-slice. + */ +struct GNUNET_PSYC_Slicer; + + +/** + * Function called upon receiving a message indicating a call to a @e method. + * + * This function is called one or more times for each message until all data + * fragments arrive from the network. + * + * @param cls + * Closure. + * @param msg + * Message part, as it arrived from the network. + * @param message_id + * Message counter, monotonically increasing from 1. + * @param nym + * The sender of the message. + * Can be NULL if the message is not connected to a pseudonym. + * @param flags + * OR'ed GNUNET_PSYC_MessageFlags + * @param method_name + * Original method name from PSYC. + * May be more specific than the registered method name due to + * try-and-slice matching. + */ +typedef void +(*GNUNET_PSYC_MethodCallback) (void *cls, + const struct GNUNET_PSYC_MessageMethod *msg, + uint64_t message_id, + uint32_t flags, + const struct GNUNET_CRYPTO_EcdsaPublicKey *nym_pub_key, + const char *method_name); + + +/** + * Function called upon receiving a modifier of a message. + * + * @param cls + * Closure. + * @param message_id + * Message ID this data fragment belongs to. + * @param msg + * Message part, as it arrived from the network. + * @param oper + * Operation to perform. + * 0 in case of a modifier continuation. + * @param name + * Name of the modifier. + * NULL in case of a modifier continuation. + * @param value + * Value of the modifier. + * @param value_size + * Size of @value. + */ +typedef void +(*GNUNET_PSYC_ModifierCallback) (void *cls, + const struct GNUNET_MessageHeader *msg, + uint64_t message_id, + enum GNUNET_PSYC_Operator oper, + const char *name, + const void *value, + uint16_t value_size, + uint16_t full_value_size); + + +/** + * Function called upon receiving a data fragment of a message. + * + * @param cls + * Closure. + * @param message_id + * Message ID this data fragment belongs to. + * @param msg + * Message part, as it arrived from the network. + * @param data_offset + * Byte offset of @a data in the overall data of the method. + * @param data_size + * Number of bytes in @a data. + * @param data + * Data stream given to the method. + * @param end + * End of message? + * #GNUNET_NO if there are further fragments, + * #GNUNET_YES if this is the last fragment, + * #GNUNET_SYSERR indicates the message was cancelled by the sender. + */ +typedef void +(*GNUNET_PSYC_DataCallback) (void *cls, + const struct GNUNET_MessageHeader *msg, + uint64_t message_id, + uint64_t data_offset, + const void *data, + uint16_t data_size); + + +/** + * End of message. + * + * @param cls + * Closure. + * @param msg + * Message part, as it arrived from the network. + * @param message_id + * Message ID this data fragment belongs to. + * @param cancelled + * #GNUNET_YES if the message was cancelled, + * #GNUNET_NO if the message is complete. + */ +typedef void +(*GNUNET_PSYC_EndOfMessageCallback) (void *cls, + const struct GNUNET_MessageHeader *msg, + uint64_t message_id, + uint8_t cancelled); + + +/** + * Create a try-and-slice instance. + * + * A slicer processes incoming messages and notifies callbacks about matching + * methods or modifiers encountered. + * + * @return A new try-and-slice construct. + */ +struct GNUNET_PSYC_Slicer * +GNUNET_PSYC_slicer_create (void); + + +/** + * Add a method to the try-and-slice instance. + * + * The callbacks are called for messages with a matching @a method_name prefix. + * + * @param slicer + * The try-and-slice instance to extend. + * @param method_name + * Name of the given method, use empty string to match all. + * @param method_cb + * Method handler invoked upon a matching message. + * @param modifier_cb + * Modifier handler, invoked after @a method_cb + * for each modifier in the message. + * @param data_cb + * Data handler, invoked after @a modifier_cb for each data fragment. + * @param eom_cb + * Invoked upon reaching the end of a matching message. + * @param cls + * Closure for the callbacks. + */ +void +GNUNET_PSYC_slicer_method_add (struct GNUNET_PSYC_Slicer *slicer, + const char *method_name, + GNUNET_PSYC_MethodCallback method_cb, + GNUNET_PSYC_ModifierCallback modifier_cb, + GNUNET_PSYC_DataCallback data_cb, + GNUNET_PSYC_EndOfMessageCallback eom_cb, + void *cls); + +/** + * Remove a registered method from the try-and-slice instance. + * + * Removes one matching handler registered with the given + * @a method_name and callbacks. + * + * @param slicer + * The try-and-slice instance. + * @param method_name + * Name of the method to remove. + * @param method_cb + * Method handler. + * @param modifier_cb + * Modifier handler. + * @param data_cb + * Data handler. + * @param eom_cb + * End of message handler. + * + * @return #GNUNET_OK if a method handler was removed, + * #GNUNET_NO if no handler matched the given method name and callbacks. + */ +int +GNUNET_PSYC_slicer_method_remove (struct GNUNET_PSYC_Slicer *slicer, + const char *method_name, + GNUNET_PSYC_MethodCallback method_cb, + GNUNET_PSYC_ModifierCallback modifier_cb, + GNUNET_PSYC_DataCallback data_cb, + GNUNET_PSYC_EndOfMessageCallback eom_cb); + + +/** + * Watch a place for changed objects. + * + * @param slicer + * The try-and-slice instance. + * @param object_filter + * Object prefix to match. + * @param modifier_cb + * Function to call when encountering a state modifier. + * @param cls + * Closure for callback. + */ +void +GNUNET_PSYC_slicer_modifier_add (struct GNUNET_PSYC_Slicer *slicer, + const char *object_filter, + GNUNET_PSYC_ModifierCallback modifier_cb, + void *cls); + + +/** + * Remove a registered modifier from the try-and-slice instance. + * + * Removes one matching handler registered with the given + * @a object_filter and callback. + * + * @param slicer + * The try-and-slice instance. + * @param object_filter + * Object prefix to match. + * @param modifier_cb + * Function to call when encountering a state modifier changes. + */ +int +GNUNET_PSYC_slicer_modifier_remove (struct GNUNET_PSYC_Slicer *slicer, + const char *object_filter, + GNUNET_PSYC_ModifierCallback modifier_cb); + + +/** + * Process an incoming message part and call matching handlers. + * + * @param cls + * Closure. + * @param message_id + * ID of the message. + * @param flags + * Flags for the message. + * @see enum GNUNET_PSYC_MessageFlags + * @param msg + * The message part. as it arrived from the network. + */ +void +GNUNET_PSYC_slicer_message (void *cls, + const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_pub_key, + uint64_t message_id, + uint32_t flags, + uint64_t fragment_offset, + const struct GNUNET_MessageHeader *msg); + + +/** + * Destroy a given try-and-slice instance. + * + * @param slicer + * Slicer to destroy + */ +void +GNUNET_PSYC_slicer_destroy (struct GNUNET_PSYC_Slicer *slicer); + + +#if 0 /* keep Emacsens' auto-indent happy */ +{ +#endif +#ifdef __cplusplus +} +#endif + +/* ifndef GNUNET_PSYC_SLICER_H */ +#endif + +/** @} */ /* end of group */ diff --git a/src/include/gnunet_psyc_util_lib.h b/src/include/gnunet_psyc_util_lib.h @@ -22,11 +22,7 @@ * @author Gabor X Toth * * @file - * PSYC utilities; receiving/transmitting/logging PSYC messages - * - * @defgroup psyc-util PSYC Utilities library - * Receiving, transmitting, logging PSYC messages. - * @{ + * PSYC utilities: messages, environment, slicer */ #ifndef GNUNET_PSYC_UTIL_LIB_H @@ -40,223 +36,10 @@ extern "C" #endif #endif -#include "gnunet_util_lib.h" -#include "gnunet_env_lib.h" -#include "gnunet_psyc_service.h" - - -/** - * Create a PSYC message. - * - * @param method_name - * PSYC method for the message. - * @param env - * Environment for the message. - * @param data - * Data payload for the message. - * @param data_size - * Size of @a data. - * - * @return Message header with size information, - * followed by the message parts. - */ -struct GNUNET_PSYC_Message * -GNUNET_PSYC_message_create (const char *method_name, - const struct GNUNET_ENV_Environment *env, - const void *data, - size_t data_size); - -/** - * Parse PSYC message. - * - * @param msg - * The PSYC message to parse. - * @param env - * The environment for the message with a list of modifiers. - * @param[out] method_name - * Pointer to the method name inside @a pmsg. - * @param[out] data - * Pointer to data inside @a pmsg. - * @param[out] data_size - * Size of @data is written here. - * - * @return #GNUNET_OK on success, - * #GNUNET_SYSERR on parse error. - */ -int -GNUNET_PSYC_message_parse (const struct GNUNET_PSYC_MessageHeader *msg, - const char **method_name, - struct GNUNET_ENV_Environment *env, - const void **data, - uint16_t *data_size); - - -void -GNUNET_PSYC_log_message (enum GNUNET_ErrorType kind, - const struct GNUNET_MessageHeader *msg); - - -int -GNUNET_PSYC_check_message_parts (uint16_t data_size, const char *data, - uint16_t *first_ptype, uint16_t *last_ptype); - - -struct GNUNET_PSYC_TransmitHandle; - -/** - * Create a transmission handle. - */ -struct GNUNET_PSYC_TransmitHandle * -GNUNET_PSYC_transmit_create (); - - -/** - * Destroy a transmission handle. - */ -void -GNUNET_PSYC_transmit_destroy (struct GNUNET_PSYC_TransmitHandle *tmit); - - -/** - * Transmit a message. - * - * @param tmit - * Transmission handle. - * @param method_name - * Which method should be invoked. - * @param env - * Environment for the message. - * Should stay available until the first call to notify_data. - * Can be NULL if there are no modifiers or @a notify_mod is - * provided instead. - * @param notify_mod - * Function to call to obtain modifiers. - * Can be NULL if there are no modifiers or @a env is provided instead. - * @param notify_data - * Function to call to obtain fragments of the data. - * @param notify_cls - * Closure for @a notify_mod and @a notify_data. - * @param flags - * Flags for the message being transmitted. - * - * @return #GNUNET_OK if the transmission was started. - * #GNUNET_SYSERR if another transmission is already going on. - */ -int -GNUNET_PSYC_transmit_message (struct GNUNET_PSYC_TransmitHandle *tmit, - const char *method_name, - const struct GNUNET_ENV_Environment *env, - GNUNET_PSYC_TransmitNotifyModifier notify_mod, - GNUNET_PSYC_TransmitNotifyData notify_data, - void *notify_cls, - uint32_t flags); - - -/** - * Resume transmission. - * - * @param tmit Transmission handle. - */ -void -GNUNET_PSYC_transmit_resume (struct GNUNET_PSYC_TransmitHandle *tmit); - - -/** - * Abort transmission request. - * - * @param tmit Transmission handle. - */ -void -GNUNET_PSYC_transmit_cancel (struct GNUNET_PSYC_TransmitHandle *tmit); - - -/** - * Got acknowledgement of a transmitted message part, continue transmission. - * - * @param tmit Transmission handle. - */ -void -GNUNET_PSYC_transmit_got_ack (struct GNUNET_PSYC_TransmitHandle *tmit); - - -struct GNUNET_PSYC_ReceiveHandle; - - -/** - * Create handle for receiving messages. - */ -struct GNUNET_PSYC_ReceiveHandle * -GNUNET_PSYC_receive_create (GNUNET_PSYC_MessageCallback message_cb, - GNUNET_PSYC_MessagePartCallback message_part_cb, - void *cb_cls); - - -/** - * Destroy handle for receiving messages. - */ -void -GNUNET_PSYC_receive_destroy (struct GNUNET_PSYC_ReceiveHandle *recv); - - -/** - * Reset stored data related to the last received message. - */ -void -GNUNET_PSYC_receive_reset (struct GNUNET_PSYC_ReceiveHandle *recv); - - -/** - * Handle incoming PSYC message. - * - * @param recv Receive handle. - * @param msg The message. - * - * @return #GNUNET_OK on success, - * #GNUNET_SYSERR on receive error. - */ -int -GNUNET_PSYC_receive_message (struct GNUNET_PSYC_ReceiveHandle *recv, - const struct GNUNET_PSYC_MessageHeader *msg); - -/** - * Check if @a data contains a series of valid message parts. - * - * @param data_size Size of @a data. - * @param data Data. - * @param[out] first_ptype Type of first message part. - * @param[out] last_ptype Type of last message part. - * - * @return Number of message parts found in @a data. - * or GNUNET_SYSERR if the message contains invalid parts. - */ -int -GNUNET_PSYC_receive_check_parts (uint16_t data_size, const char *data, - uint16_t *first_ptype, uint16_t *last_ptype); - - -/** - * Initialize PSYC message header. - */ -void -GNUNET_PSYC_message_header_init (struct GNUNET_PSYC_MessageHeader *pmsg, - const struct GNUNET_MULTICAST_MessageHeader *mmsg, - uint32_t flags); - - -/** - * Create a new PSYC message header from a multicast message for sending it to clients. - */ -struct GNUNET_PSYC_MessageHeader * -GNUNET_PSYC_message_header_create (const struct GNUNET_MULTICAST_MessageHeader *mmsg, - uint32_t flags); - - -/** - * Create a new PSYC message header from a PSYC message. - */ -struct GNUNET_PSYC_MessageHeader * -GNUNET_PSYC_message_header_create_from_psyc (const struct GNUNET_PSYC_Message *msg); +#include "gnunet_psyc_env.h" +#include "gnunet_psyc_message.h" +#include "gnunet_psyc_slicer.h" #if 0 /* keep Emacsens' auto-indent happy */ @@ -268,5 +51,3 @@ GNUNET_PSYC_message_header_create_from_psyc (const struct GNUNET_PSYC_Message *m /* ifndef GNUNET_PSYC_UTIL_LIB_H */ #endif - -/** @} */ /* end of group */ diff --git a/src/include/gnunet_psycstore_plugin.h b/src/include/gnunet_psycstore_plugin.h @@ -248,7 +248,7 @@ struct GNUNET_PSYCSTORE_PluginFunctions int (*state_modify_op) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, - enum GNUNET_ENV_Operator op, + enum GNUNET_PSYC_Operator op, const char *name, const void *value, size_t value_size); diff --git a/src/include/gnunet_psycstore_service.h b/src/include/gnunet_psycstore_service.h @@ -41,7 +41,7 @@ extern "C" #endif #include "gnunet_util_lib.h" -#include "gnunet_env_lib.h" +#include "gnunet_psyc_util_lib.h" #include "gnunet_multicast_service.h" #include "gnunet_psyc_service.h" @@ -546,7 +546,7 @@ GNUNET_PSYCSTORE_state_sync (struct GNUNET_PSYCSTORE_Handle *h, uint64_t max_state_message_id, uint64_t state_hash_message_id, size_t modifier_count, - const struct GNUNET_ENV_Modifier *modifiers, + const struct GNUNET_PSYC_Modifier *modifiers, GNUNET_PSYCSTORE_ResultCallback rcb, void *rcb_cls); diff --git a/src/include/gnunet_social_service.h b/src/include/gnunet_social_service.h @@ -216,7 +216,7 @@ extern "C" #include <stdint.h> #include "gnunet_util_lib.h" -#include "gnunet_env_lib.h" +#include "gnunet_psyc_util_lib.h" #include "gnunet_identity_service.h" #include "gnunet_namestore_service.h" #include "gnunet_psyc_service.h" @@ -263,14 +263,6 @@ struct GNUNET_SOCIAL_Host; struct GNUNET_SOCIAL_Guest; /** - * Handle to an implementation of try-and-slice. - */ -struct GNUNET_SOCIAL_Slicer; - - - - -/** * Handle that can be used to reconnect to a place as host. */ struct GNUNET_SOCIAL_HostConnection; @@ -450,239 +442,6 @@ GNUNET_SOCIAL_nym_get_pub_key_hash (const struct GNUNET_SOCIAL_Nym *nym); /** - * Function called upon receiving a message indicating a call to a @e method. - * - * This function is called one or more times for each message until all data - * fragments arrive from the network. - * - * @param cls - * Closure. - * @param msg - * Message part, as it arrived from the network. - * @param message_id - * Message counter, monotonically increasing from 1. - * @param nym - * The sender of the message. - * Can be NULL if the message is not connected to a pseudonym. - * @param flags - * OR'ed GNUNET_PSYC_MessageFlags - * @param method_name - * Original method name from PSYC. - * May be more specific than the registered method name due to - * try-and-slice matching. - */ -typedef void -(*GNUNET_SOCIAL_MethodCallback) (void *cls, - const struct GNUNET_PSYC_MessageMethod *msg, - uint64_t message_id, - uint32_t flags, - const struct GNUNET_SOCIAL_Nym *nym, - const char *method_name); - - -/** - * Function called upon receiving a modifier of a message. - * - * @param cls - * Closure. - * @param message_id - * Message ID this data fragment belongs to. - * @param msg - * Message part, as it arrived from the network. - * @param oper - * Operation to perform. - * 0 in case of a modifier continuation. - * @param name - * Name of the modifier. - * NULL in case of a modifier continuation. - * @param value - * Value of the modifier. - * @param value_size - * Size of @value. - */ -typedef void -(*GNUNET_SOCIAL_ModifierCallback) (void *cls, - const struct GNUNET_MessageHeader *msg, - uint64_t message_id, - enum GNUNET_ENV_Operator oper, - const char *name, - const void *value, - uint16_t value_size, - uint16_t full_value_size); - - -/** - * Function called upon receiving a data fragment of a message. - * - * @param cls - * Closure. - * @param message_id - * Message ID this data fragment belongs to. - * @param msg - * Message part, as it arrived from the network. - * @param data_offset - * Byte offset of @a data in the overall data of the method. - * @param data_size - * Number of bytes in @a data. - * @param data - * Data stream given to the method. - * @param end - * End of message? - * #GNUNET_NO if there are further fragments, - * #GNUNET_YES if this is the last fragment, - * #GNUNET_SYSERR indicates the message was cancelled by the sender. - */ -typedef void -(*GNUNET_SOCIAL_DataCallback) (void *cls, - const struct GNUNET_MessageHeader *msg, - uint64_t message_id, - uint64_t data_offset, - const void *data, - uint16_t data_size); - - -/** - * End of message. - * - * @param cls - * Closure. - * @param msg - * Message part, as it arrived from the network. - * @param message_id - * Message ID this data fragment belongs to. - * @param cancelled - * #GNUNET_YES if the message was cancelled, - * #GNUNET_NO if the message is complete. - */ -typedef void -(*GNUNET_SOCIAL_EndOfMessageCallback) (void *cls, - const struct GNUNET_MessageHeader *msg, - uint64_t message_id, - uint8_t cancelled); - - -/** - * Create a try-and-slice instance. - * - * A slicer processes incoming messages and notifies callbacks about matching - * methods or modifiers encountered. - * - * @return A new try-and-slice construct. - */ -struct GNUNET_SOCIAL_Slicer * -GNUNET_SOCIAL_slicer_create (void); - - -/** - * Add a method to the try-and-slice instance. - * - * The callbacks are called for messages with a matching @a method_name prefix. - * - * @param slicer - * The try-and-slice instance to extend. - * @param method_name - * Name of the given method, use empty string to match all. - * @param method_cb - * Method handler invoked upon a matching message. - * @param modifier_cb - * Modifier handler, invoked after @a method_cb - * for each modifier in the message. - * @param data_cb - * Data handler, invoked after @a modifier_cb for each data fragment. - * @param eom_cb - * Invoked upon reaching the end of a matching message. - * @param cls - * Closure for the callbacks. - */ -void -GNUNET_SOCIAL_slicer_method_add (struct GNUNET_SOCIAL_Slicer *slicer, - const char *method_name, - GNUNET_SOCIAL_MethodCallback method_cb, - GNUNET_SOCIAL_ModifierCallback modifier_cb, - GNUNET_SOCIAL_DataCallback data_cb, - GNUNET_SOCIAL_EndOfMessageCallback eom_cb, - void *cls); - -/** - * Remove a registered method from the try-and-slice instance. - * - * Removes one matching handler registered with the given - * @a method_name and callbacks. - * - * @param slicer - * The try-and-slice instance. - * @param method_name - * Name of the method to remove. - * @param method_cb - * Method handler. - * @param modifier_cb - * Modifier handler. - * @param data_cb - * Data handler. - * @param eom_cb - * End of message handler. - * - * @return #GNUNET_OK if a method handler was removed, - * #GNUNET_NO if no handler matched the given method name and callbacks. - */ -int -GNUNET_SOCIAL_slicer_method_remove (struct GNUNET_SOCIAL_Slicer *slicer, - const char *method_name, - GNUNET_SOCIAL_MethodCallback method_cb, - GNUNET_SOCIAL_ModifierCallback modifier_cb, - GNUNET_SOCIAL_DataCallback data_cb, - GNUNET_SOCIAL_EndOfMessageCallback eom_cb); - - -/** - * Watch a place for changed objects. - * - * @param slicer - * The try-and-slice instance. - * @param object_filter - * Object prefix to match. - * @param modifier_cb - * Function to call when encountering a state modifier. - * @param cls - * Closure for callback. - */ -void -GNUNET_SOCIAL_slicer_modifier_add (struct GNUNET_SOCIAL_Slicer *slicer, - const char *object_filter, - GNUNET_SOCIAL_ModifierCallback modifier_cb, - void *cls); - - -/** - * Remove a registered modifier from the try-and-slice instance. - * - * Removes one matching handler registered with the given - * @a object_filter and callback. - * - * @param slicer - * The try-and-slice instance. - * @param object_filter - * Object prefix to match. - * @param modifier_cb - * Function to call when encountering a state modifier changes. - */ -int -GNUNET_SOCIAL_slicer_modifier_remove (struct GNUNET_SOCIAL_Slicer *slicer, - const char *object_filter, - GNUNET_SOCIAL_ModifierCallback modifier_cb); - - -/** - * Destroy a given try-and-slice instance. - * - * @param slicer - * Slicer to destroy - */ -void -GNUNET_SOCIAL_slicer_destroy (struct GNUNET_SOCIAL_Slicer *slicer); - - -/** * Function called asking for nym to be admitted to the place. * * Should call either GNUNET_SOCIAL_host_admit() or @@ -704,7 +463,7 @@ typedef void (*GNUNET_SOCIAL_AnswerDoorCallback) (void *cls, struct GNUNET_SOCIAL_Nym *nym, const char *method_name, - struct GNUNET_ENV_Environment *env, + struct GNUNET_PSYC_Environment *env, size_t data_size, const void *data); @@ -723,7 +482,7 @@ typedef void typedef void (*GNUNET_SOCIAL_FarewellCallback) (void *cls, const struct GNUNET_SOCIAL_Nym *nym, - struct GNUNET_ENV_Environment *env); + struct GNUNET_PSYC_Environment *env); /** @@ -778,7 +537,7 @@ struct GNUNET_SOCIAL_Host * GNUNET_SOCIAL_host_enter (const struct GNUNET_SOCIAL_App *app, const struct GNUNET_SOCIAL_Ego *ego, enum GNUNET_PSYC_Policy policy, - struct GNUNET_SOCIAL_Slicer *slicer, + struct GNUNET_PSYC_Slicer *slicer, GNUNET_SOCIAL_HostEnterCallback enter_cb, GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb, GNUNET_SOCIAL_FarewellCallback farewell_cb, @@ -806,7 +565,7 @@ GNUNET_SOCIAL_host_enter (const struct GNUNET_SOCIAL_App *app, */ struct GNUNET_SOCIAL_Host * GNUNET_SOCIAL_host_enter_reconnect (struct GNUNET_SOCIAL_HostConnection *hconn, - struct GNUNET_SOCIAL_Slicer *slicer, + struct GNUNET_PSYC_Slicer *slicer, GNUNET_SOCIAL_HostEnterCallback enter_cb, GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb, GNUNET_SOCIAL_FarewellCallback farewell_cb, @@ -862,7 +621,7 @@ GNUNET_SOCIAL_host_entry_decision (struct GNUNET_SOCIAL_Host *hst, void GNUNET_SOCIAL_host_eject (struct GNUNET_SOCIAL_Host *host, const struct GNUNET_SOCIAL_Nym *nym, - struct GNUNET_ENV_Environment *env); + struct GNUNET_PSYC_Environment *env); /** @@ -915,7 +674,7 @@ struct GNUNET_SOCIAL_Announcement; struct GNUNET_SOCIAL_Announcement * GNUNET_SOCIAL_host_announce (struct GNUNET_SOCIAL_Host *host, const char *method_name, - const struct GNUNET_ENV_Environment *env, + const struct GNUNET_PSYC_Environment *env, GNUNET_PSYC_TransmitNotifyData notify_data, void *notify_data_cls, enum GNUNET_SOCIAL_AnnounceFlags flags); @@ -1032,7 +791,7 @@ GNUNET_SOCIAL_host_disconnect (struct GNUNET_SOCIAL_Host *hst, */ void GNUNET_SOCIAL_host_leave (struct GNUNET_SOCIAL_Host *hst, - const struct GNUNET_ENV_Environment *env, + const struct GNUNET_PSYC_Environment *env, GNUNET_ContinuationCallback disconnect_cb, void *cls); @@ -1062,22 +821,12 @@ typedef void * Function called upon a guest receives a decision about entry to the place. * * @param is_admitted - * Is the guest admitted to the place? - * #GNUNET_YES if admitted, - * #GNUNET_NO if refused entry - * #GNUNET_SYSERR if the request could not be answered. - * @param method_name - * Method for the message sent along with the decision. - * NULL if no message was sent. - * @param env - * Environment with variables for the message. - * NULL if there are no variables. - * It has to be freed using GNUNET_ENV_environment_destroy() - * when it is not needed anymore. - * @param data_size - * Size of @data. + * Is the guest admitted to the place? + * #GNUNET_YES if admitted, + * #GNUNET_NO if refused entry, + * #GNUNET_SYSERR if the request could not be answered. * @param data - * Payload of the message. + * Entry response message. */ typedef void (*GNUNET_SOCIAL_EntryDecisionCallback) (void *cls, @@ -1124,7 +873,7 @@ GNUNET_SOCIAL_guest_enter (const struct GNUNET_SOCIAL_App *app, uint32_t relay_count, const struct GNUNET_PeerIdentity *relays, const struct GNUNET_PSYC_Message *entry_msg, - struct GNUNET_SOCIAL_Slicer *slicer, + struct GNUNET_PSYC_Slicer *slicer, GNUNET_SOCIAL_GuestEnterCallback local_enter_cb, GNUNET_SOCIAL_EntryDecisionCallback entry_dcsn_cb, void *cls); @@ -1162,7 +911,7 @@ GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_SOCIAL_App *app, const char *gns_name, const char *password, const struct GNUNET_PSYC_Message *join_msg, - struct GNUNET_SOCIAL_Slicer *slicer, + struct GNUNET_PSYC_Slicer *slicer, GNUNET_SOCIAL_GuestEnterCallback local_enter_cb, GNUNET_SOCIAL_EntryDecisionCallback entry_decision_cb, void *cls); @@ -1188,7 +937,7 @@ GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_SOCIAL_App *app, struct GNUNET_SOCIAL_Guest * GNUNET_SOCIAL_guest_enter_reconnect (struct GNUNET_SOCIAL_GuestConnection *gconn, enum GNUNET_PSYC_SlaveJoinFlags flags, - struct GNUNET_SOCIAL_Slicer *slicer, + struct GNUNET_PSYC_Slicer *slicer, GNUNET_SOCIAL_GuestEnterCallback local_enter_cb, void *cls); @@ -1230,7 +979,7 @@ struct GNUNET_SOCIAL_TalkRequest; struct GNUNET_SOCIAL_TalkRequest * GNUNET_SOCIAL_guest_talk (struct GNUNET_SOCIAL_Guest *guest, const char *method_name, - const struct GNUNET_ENV_Environment *env, + const struct GNUNET_PSYC_Environment *env, GNUNET_PSYC_TransmitNotifyData notify_data, void *notify_data_cls, enum GNUNET_SOCIAL_TalkFlags flags); @@ -1289,7 +1038,7 @@ GNUNET_SOCIAL_guest_disconnect (struct GNUNET_SOCIAL_Guest *gst, */ void GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Guest *gst, - struct GNUNET_ENV_Environment *env, + struct GNUNET_PSYC_Environment *env, GNUNET_ContinuationCallback disconnect_cb, void *leave_cls); @@ -1343,7 +1092,7 @@ GNUNET_SOCIAL_place_history_replay (struct GNUNET_SOCIAL_Place *plc, uint64_t end_message_id, const char *method_prefix, uint32_t flags, - struct GNUNET_SOCIAL_Slicer *slicer, + struct GNUNET_PSYC_Slicer *slicer, GNUNET_ResultCallback result_cb, void *cls); @@ -1371,7 +1120,7 @@ GNUNET_SOCIAL_place_history_replay_latest (struct GNUNET_SOCIAL_Place *plc, uint64_t message_limit, const char *method_prefix, uint32_t flags, - struct GNUNET_SOCIAL_Slicer *slicer, + struct GNUNET_PSYC_Slicer *slicer, GNUNET_ResultCallback result_cb, void *cls); @@ -1524,4 +1273,4 @@ GNUNET_SOCIAL_zone_add_nym (const struct GNUNET_SOCIAL_App *app, /* ifndef GNUNET_SOCIAL_SERVICE_H */ #endif -/** @} */ /* end of group social */ +/** @} */ /* end of group */ diff --git a/src/psyc/Makefile.am b/src/psyc/Makefile.am @@ -24,8 +24,7 @@ libgnunetpsyc_la_SOURCES = \ psyc_api.c psyc.h libgnunetpsyc_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/env/libgnunetenv.la \ - $(top_builddir)/src/psycstore/libgnunetpsycutil.la \ + $(top_builddir)/src/psycutil/libgnunetpsycutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetpsyc_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ @@ -43,7 +42,7 @@ gnunet_service_psyc_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/multicast/libgnunetmulticast.la \ $(top_builddir)/src/psycstore/libgnunetpsycstore.la \ - $(top_builddir)/src/psycstore/libgnunetpsycutil.la \ + $(top_builddir)/src/psycutil/libgnunetpsycutil.la \ $(GN_LIBINTL) gnunet_service_psyc_CFLAGS = $(AM_CFLAGS) @@ -62,10 +61,9 @@ test_psyc_SOURCES = \ test_psyc.c test_psyc_LDADD = \ libgnunetpsyc.la \ - $(top_builddir)/src/psycstore/libgnunetpsycutil.la \ + $(top_builddir)/src/psycutil/libgnunetpsycutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/env/libgnunetenv.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ diff --git a/src/psyc/gnunet-service-psyc.c b/src/psyc/gnunet-service-psyc.c @@ -2477,7 +2477,7 @@ store_recv_state_var (void *cls, const char *name, mod->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER); mod->name_size = htons (name_size); mod->value_size = htonl (value_size); - mod->oper = htons (GNUNET_ENV_OP_ASSIGN); + mod->oper = htons (GNUNET_PSYC_OP_ASSIGN); memcpy (&mod[1], name, name_size); memcpy (((char *) &mod[1]) + name_size, value, value_size); } diff --git a/src/psyc/psyc_api.c b/src/psyc/psyc_api.c @@ -34,7 +34,6 @@ #include "platform.h" #include "gnunet_util_lib.h" -#include "gnunet_env_lib.h" #include "gnunet_multicast_service.h" #include "gnunet_psyc_service.h" #include "gnunet_psyc_util_lib.h" diff --git a/src/psyc/test_psyc.c b/src/psyc/test_psyc.c @@ -32,7 +32,6 @@ #include "gnunet_common.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" -#include "gnunet_env_lib.h" #include "gnunet_psyc_util_lib.h" #include "gnunet_psyc_service.h" #include "gnunet_core_service.h" @@ -69,8 +68,8 @@ struct TransmitClosure { struct GNUNET_PSYC_MasterTransmitHandle *mst_tmit; struct GNUNET_PSYC_SlaveTransmitHandle *slv_tmit; - struct GNUNET_ENV_Environment *env; - struct GNUNET_ENV_Modifier *mod; + struct GNUNET_PSYC_Environment *env; + struct GNUNET_PSYC_Modifier *mod; char *data[16]; const char *mod_value; size_t mod_value_size; @@ -116,7 +115,7 @@ void master_stopped (void *cls) { if (NULL != tmit) { - GNUNET_ENV_environment_destroy (tmit->env); + GNUNET_PSYC_env_destroy (tmit->env); GNUNET_free (tmit); tmit = NULL; } @@ -617,7 +616,7 @@ tmit_notify_mod (void *cls, uint16_t *data_size, void *data, uint8_t *oper, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test #%d: Transmit notify modifier: %lu bytes available, " "%u modifiers left to process.\n", - test, *data_size, GNUNET_ENV_environment_get_count (tmit->env)); + test, *data_size, GNUNET_PSYC_env_get_count (tmit->env)); uint16_t name_size = 0; size_t value_size = 0; @@ -697,12 +696,12 @@ slave_transmit () "Test #%d: Slave sending request to master.\n", test); tmit = GNUNET_new (struct TransmitClosure); - tmit->env = GNUNET_ENV_environment_create (); - GNUNET_ENV_environment_add (tmit->env, GNUNET_ENV_OP_ASSIGN, + tmit->env = GNUNET_PSYC_env_create (); + GNUNET_PSYC_env_add (tmit->env, GNUNET_PSYC_OP_ASSIGN, "_abc", "abc def", 7); - GNUNET_ENV_environment_add (tmit->env, GNUNET_ENV_OP_ASSIGN, + GNUNET_PSYC_env_add (tmit->env, GNUNET_PSYC_OP_ASSIGN, "_abc_def", "abc def ghi", 11); - tmit->mod = GNUNET_ENV_environment_head (tmit->env); + tmit->mod = GNUNET_PSYC_env_head (tmit->env); tmit->n = 0; tmit->data[0] = "slave test"; tmit->data_count = 1; @@ -835,10 +834,10 @@ slave_join (int t) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Test #%d: Joining slave.\n"); struct GNUNET_PeerIdentity origin = this_peer; - struct GNUNET_ENV_Environment *env = GNUNET_ENV_environment_create (); - GNUNET_ENV_environment_add (env, GNUNET_ENV_OP_ASSIGN, + struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create (); + GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_ASSIGN, "_foo", "bar baz", 7); - GNUNET_ENV_environment_add (env, GNUNET_ENV_OP_ASSIGN, + GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_ASSIGN, "_foo_bar", "foo bar baz", 11); struct GNUNET_PSYC_Message * join_msg = GNUNET_PSYC_message_create ("_request_join", env, "some data", 9); @@ -851,7 +850,7 @@ slave_join (int t) join_msg); GNUNET_free (join_msg); slv_chn = GNUNET_PSYC_slave_get_channel (slv); - GNUNET_ENV_environment_destroy (env); + GNUNET_PSYC_env_destroy (env); } @@ -881,20 +880,20 @@ master_transmit () val_cont[i] = (0 == j % 10000) ? '0' + j / 10000 : '!'; tmit = GNUNET_new (struct TransmitClosure); - tmit->env = GNUNET_ENV_environment_create (); - GNUNET_ENV_environment_add (tmit->env, GNUNET_ENV_OP_ASSIGN, + tmit->env = GNUNET_PSYC_env_create (); + GNUNET_PSYC_env_add (tmit->env, GNUNET_PSYC_OP_ASSIGN, "_foo", "bar baz", 7); - GNUNET_ENV_environment_add (tmit->env, GNUNET_ENV_OP_ASSIGN, + GNUNET_PSYC_env_add (tmit->env, GNUNET_PSYC_OP_ASSIGN, name_max, val_max, GNUNET_PSYC_MODIFIER_MAX_PAYLOAD - name_max_size); - GNUNET_ENV_environment_add (tmit->env, GNUNET_ENV_OP_ASSIGN, + GNUNET_PSYC_env_add (tmit->env, GNUNET_PSYC_OP_ASSIGN, "_foo_bar", "foo bar baz", 11); - GNUNET_ENV_environment_add (tmit->env, GNUNET_ENV_OP_ASSIGN, + GNUNET_PSYC_env_add (tmit->env, GNUNET_PSYC_OP_ASSIGN, name_cont, val_cont, GNUNET_PSYC_MODIFIER_MAX_PAYLOAD - name_cont_size + GNUNET_PSYC_MOD_CONT_MAX_PAYLOAD); - tmit->mod = GNUNET_ENV_environment_head (tmit->env); + tmit->mod = GNUNET_PSYC_env_head (tmit->env); tmit->data[0] = "foo"; tmit->data[1] = GNUNET_malloc (GNUNET_PSYC_DATA_MAX_PAYLOAD + 1); for (i = 0; i < GNUNET_PSYC_DATA_MAX_PAYLOAD; i++) diff --git a/src/psycstore/Makefile.am b/src/psycstore/Makefile.am @@ -27,17 +27,7 @@ SQLITE_TESTS = test_plugin_psycstore_sqlite endif endif -lib_LTLIBRARIES = libgnunetpsycutil.la libgnunetpsycstore.la - -libgnunetpsycutil_la_SOURCES = \ - psyc_util_lib.c -libgnunetpsycutil_la_LIBADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/env/libgnunetenv.la \ - $(GN_LIBINTL) $(XLIB) -libgnunetpsycutil_la_LDFLAGS = \ - $(GN_LIB_LDFLAGS) $(WINFLAGS) \ - -version-info 0:0:0 +lib_LTLIBRARIES = libgnunetpsycstore.la libgnunetpsycstore_la_SOURCES = \ psycstore_api.c \ @@ -59,7 +49,7 @@ gnunet_service_psycstore_SOURCES = \ gnunet_service_psycstore_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ - libgnunetpsycutil.la \ + $(top_builddir)/src/psycutil/libgnunetpsycutil.la \ $(GN_LIBINTL) plugin_LTLIBRARIES = \ diff --git a/src/psycstore/gnunet-service-psycstore.c b/src/psycstore/gnunet-service-psycstore.c @@ -551,7 +551,7 @@ recv_state_message_part (void *cls, const char *name = (const char *) &pmod[1]; const void *value = name + name_size; - if (GNUNET_ENV_OP_SET != pmod->oper) + if (GNUNET_PSYC_OP_SET != pmod->oper) { // Apply non-transient operation. if (psize == sizeof (*pmod) + name_size + value_size) { @@ -576,7 +576,7 @@ recv_state_message_part (void *cls, } case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT: - if (GNUNET_ENV_OP_SET != scls->mod_oper) + if (GNUNET_PSYC_OP_SET != scls->mod_oper) { if (scls->mod_value_remaining == 0) { diff --git a/src/psycstore/plugin_psycstore_sqlite.c b/src/psycstore/plugin_psycstore_sqlite.c @@ -35,7 +35,7 @@ #include "gnunet_psycstore_service.h" #include "gnunet_multicast_service.h" #include "gnunet_crypto_lib.h" -#include "gnunet_env_lib.h" +#include "gnunet_psyc_util_lib.h" #include "psycstore.h" #include <sqlite3.h> @@ -1564,7 +1564,7 @@ state_modify_begin (void *cls, static int state_modify_op (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, - enum GNUNET_ENV_Operator op, + enum GNUNET_PSYC_Operator op, const char *name, const void *value, size_t value_size) { struct Plugin *plugin = cls; @@ -1572,7 +1572,7 @@ state_modify_op (void *cls, switch (op) { - case GNUNET_ENV_OP_ASSIGN: + case GNUNET_PSYC_OP_ASSIGN: return state_assign (plugin, plugin->insert_state_current, channel_key, name, value, value_size); diff --git a/src/psycstore/psyc_util_lib.c b/src/psycstore/psyc_util_lib.c @@ -1,1330 +0,0 @@ -/* - * This file is part of GNUnet - * Copyright (C) 2013 Christian Grothoff (and other contributing authors) - * - * 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 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. - */ - -/** - * @file psycstore/psyc_util_lib.c - * @brief PSYC utilities; receiving/transmitting/logging PSYC messages. - * @author Gabor X Toth - */ - -#include <inttypes.h> - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_env_lib.h" -#include "gnunet_psyc_service.h" -#include "gnunet_psyc_util_lib.h" - -#define LOG(kind,...) GNUNET_log_from (kind, "psyc-util",__VA_ARGS__) - - -struct GNUNET_PSYC_TransmitHandle -{ - /** - * Client connection to service. - */ - struct GNUNET_CLIENT_MANAGER_Connection *client; - - /** - * Message currently being received from the client. - */ - struct GNUNET_MessageHeader *msg; - - /** - * Callback to request next modifier from client. - */ - GNUNET_PSYC_TransmitNotifyModifier notify_mod; - - /** - * Closure for the notify callbacks. - */ - void *notify_mod_cls; - - /** - * Callback to request next data fragment from client. - */ - GNUNET_PSYC_TransmitNotifyData notify_data; - - /** - * Closure for the notify callbacks. - */ - void *notify_data_cls; - - /** - * Modifier of the environment that is currently being transmitted. - */ - struct GNUNET_ENV_Modifier *mod; - - /** - * - */ - const char *mod_value; - - /** - * Number of bytes remaining to be transmitted from the current modifier value. - */ - uint32_t mod_value_remaining; - - /** - * State of the current message being received from client. - */ - enum GNUNET_PSYC_MessageState state; - - /** - * Number of PSYC_TRANSMIT_ACK messages we are still waiting for. - */ - uint8_t acks_pending; - - /** - * Is transmission paused? - */ - uint8_t paused; - - /** - * Are we currently transmitting a message? - */ - uint8_t in_transmit; - - /** - * Notify callback is currently being called. - */ - uint8_t in_notify; - -}; - - - -struct GNUNET_PSYC_ReceiveHandle -{ - /** - * Message callback. - */ - GNUNET_PSYC_MessageCallback message_cb; - - /** - * Message part callback. - */ - GNUNET_PSYC_MessagePartCallback message_part_cb; - - /** - * Closure for the callbacks. - */ - void *cb_cls; - - /** - * ID of the message being received from the PSYC service. - */ - uint64_t message_id; - - /** - * Public key of the slave from which a message is being received. - */ - struct GNUNET_CRYPTO_EcdsaPublicKey slave_key; - - /** - * State of the currently being received message from the PSYC service. - */ - enum GNUNET_PSYC_MessageState state; - - /** - * Flags for the currently being received message from the PSYC service. - */ - enum GNUNET_PSYC_MessageFlags flags; - - /** - * Expected value size for the modifier being received from the PSYC service. - */ - uint32_t mod_value_size_expected; - - /** - * Actual value size for the modifier being received from the PSYC service. - */ - uint32_t mod_value_size; -}; - - -/**** Messages ****/ - - -/** - * Create a PSYC message. - * - * @param method_name - * PSYC method for the message. - * @param env - * Environment for the message. - * @param data - * Data payload for the message. - * @param data_size - * Size of @a data. - * - * @return Message header with size information, - * followed by the message parts. - */ -struct GNUNET_PSYC_Message * -GNUNET_PSYC_message_create (const char *method_name, - const struct GNUNET_ENV_Environment *env, - const void *data, - size_t data_size) -{ - struct GNUNET_ENV_Modifier *mod = NULL; - struct GNUNET_PSYC_MessageMethod *pmeth = NULL; - struct GNUNET_PSYC_MessageModifier *pmod = NULL; - struct GNUNET_MessageHeader *pmsg = NULL; - uint16_t env_size = 0; - if (NULL != env) - { - mod = GNUNET_ENV_environment_head (env); - while (NULL != mod) - { - env_size += sizeof (*pmod) + strlen (mod->name) + 1 + mod->value_size; - mod = mod->next; - } - } - - struct GNUNET_PSYC_Message *msg; - uint16_t method_name_size = strlen (method_name) + 1; - if (method_name_size == 1) - return NULL; - - uint16_t msg_size = sizeof (*msg) /* header */ - + sizeof (*pmeth) + method_name_size /* method */ - + env_size /* modifiers */ - + ((0 < data_size) ? sizeof (*pmsg) + data_size : 0) /* data */ - + sizeof (*pmsg); /* end of message */ - msg = GNUNET_malloc (msg_size); - msg->header.size = htons (msg_size); - msg->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE); /* FIXME */ - - pmeth = (struct GNUNET_PSYC_MessageMethod *) &msg[1]; - pmeth->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD); - pmeth->header.size = htons (sizeof (*pmeth) + method_name_size); - memcpy (&pmeth[1], method_name, method_name_size); - - uint16_t p = sizeof (*msg) + sizeof (*pmeth) + method_name_size; - if (NULL != env) - { - mod = GNUNET_ENV_environment_head (env); - while (NULL != mod) - { - uint16_t mod_name_size = strlen (mod->name) + 1; - pmod = (struct GNUNET_PSYC_MessageModifier *) ((char *) msg + p); - pmod->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER); - pmod->header.size = sizeof (*pmod) + mod_name_size + mod->value_size; - p += pmod->header.size; - pmod->header.size = htons (pmod->header.size); - - pmod->oper = mod->oper; - pmod->name_size = htons (mod_name_size); - pmod->value_size = htonl (mod->value_size); - - memcpy (&pmod[1], mod->name, mod_name_size); - if (0 < mod->value_size) - memcpy ((char *) &pmod[1] + mod_name_size, mod->value, mod->value_size); - - mod = mod->next; - } - } - - if (0 < data_size) - { - pmsg = (struct GNUNET_MessageHeader *) ((char *) msg + p); - pmsg->size = sizeof (*pmsg) + data_size; - p += pmsg->size; - pmsg->size = htons (pmsg->size); - pmsg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA); - memcpy (&pmsg[1], data, data_size); - } - - pmsg = (struct GNUNET_MessageHeader *) ((char *) msg + p); - pmsg->size = htons (sizeof (*pmsg)); - pmsg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END); - - GNUNET_assert (p + sizeof (*pmsg) == msg_size); - return msg; -} - - -void -GNUNET_PSYC_log_message (enum GNUNET_ErrorType kind, - const struct GNUNET_MessageHeader *msg) -{ - uint16_t size = ntohs (msg->size); - uint16_t type = ntohs (msg->type); - GNUNET_log (kind, "Message of type %d and size %u:\n", type, size); - switch (type) - { - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE: - { - struct GNUNET_PSYC_MessageHeader *pmsg - = (struct GNUNET_PSYC_MessageHeader *) msg; - GNUNET_log (kind, "\tID: %" PRIu64 "\tflags: %x" PRIu32 "\n", - GNUNET_ntohll (pmsg->message_id), ntohl (pmsg->flags)); - break; - } - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD: - { - struct GNUNET_PSYC_MessageMethod *meth - = (struct GNUNET_PSYC_MessageMethod *) msg; - GNUNET_log (kind, "\t%.*s\n", size - sizeof (*meth), &meth[1]); - break; - } - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: - { - struct GNUNET_PSYC_MessageModifier *mod - = (struct GNUNET_PSYC_MessageModifier *) msg; - uint16_t name_size = ntohs (mod->name_size); - char oper = ' ' < mod->oper ? mod->oper : ' '; - GNUNET_log (kind, "\t%c%.*s\t%.*s\n", oper, name_size, &mod[1], - size - sizeof (*mod) - name_size, - ((char *) &mod[1]) + name_size); - break; - } - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT: - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA: - GNUNET_log (kind, "\t%.*s\n", size - sizeof (*msg), &msg[1]); - break; - } -} - - -/**** Transmitting messages ****/ - - -/** - * Create a transmission handle. - */ -struct GNUNET_PSYC_TransmitHandle * -GNUNET_PSYC_transmit_create (struct GNUNET_CLIENT_MANAGER_Connection *client) -{ - struct GNUNET_PSYC_TransmitHandle *tmit = GNUNET_malloc (sizeof (*tmit)); - tmit->client = client; - return tmit; -} - - -/** - * Destroy a transmission handle. - */ -void -GNUNET_PSYC_transmit_destroy (struct GNUNET_PSYC_TransmitHandle *tmit) -{ - GNUNET_free (tmit); -} - - -/** - * Queue a message part for transmission. - * - * The message part is added to the current message buffer. - * When this buffer is full, it is added to the transmission queue. - * - * @param tmit - * Transmission handle. - * @param msg - * Message part, or NULL. - * @param tmit_now - * Transmit message now, or wait for buffer to fill up? - * #GNUNET_YES or #GNUNET_NO. - */ -static void -transmit_queue_insert (struct GNUNET_PSYC_TransmitHandle *tmit, - const struct GNUNET_MessageHeader *msg, - uint8_t tmit_now) -{ - uint16_t size = (NULL != msg) ? ntohs (msg->size) : 0; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Queueing message part of type %u and size %u (tmit_now: %u)).\n", - NULL != msg ? ntohs (msg->type) : 0, size, tmit_now); - - if (NULL != tmit->msg) - { - if (NULL == msg - || GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD < tmit->msg->size + size) - { - /* End of message or buffer is full, add it to transmission queue - * and start with empty buffer */ - tmit->msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE); - tmit->msg->size = htons (tmit->msg->size); - GNUNET_CLIENT_MANAGER_transmit (tmit->client, tmit->msg); - tmit->msg = NULL; - tmit->acks_pending++; - } - else - { - /* Message fits in current buffer, append */ - tmit->msg = GNUNET_realloc (tmit->msg, tmit->msg->size + size); - memcpy ((char *) tmit->msg + tmit->msg->size, msg, size); - tmit->msg->size += size; - } - } - - if (NULL == tmit->msg && NULL != msg) - { - /* Empty buffer, copy over message. */ - tmit->msg = GNUNET_malloc (sizeof (*tmit->msg) + size); - tmit->msg->size = sizeof (*tmit->msg) + size; - memcpy (&tmit->msg[1], msg, size); - } - - if (NULL != tmit->msg - && (GNUNET_YES == tmit_now - || (GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD - < tmit->msg->size + sizeof (struct GNUNET_MessageHeader)))) - { - /* End of message or buffer is full, add it to transmission queue. */ - tmit->msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE); - tmit->msg->size = htons (tmit->msg->size); - GNUNET_CLIENT_MANAGER_transmit (tmit->client, tmit->msg); - tmit->msg = NULL; - tmit->acks_pending++; - } -} - - -/** - * Request data from client to transmit. - * - * @param tmit Transmission handle. - */ -static void -transmit_data (struct GNUNET_PSYC_TransmitHandle *tmit) -{ - int notify_ret = GNUNET_YES; - uint16_t data_size = 0; - char data[GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD] = ""; - struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) data; - msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA); - - if (NULL != tmit->notify_data) - { - data_size = GNUNET_PSYC_DATA_MAX_PAYLOAD; - tmit->in_notify = GNUNET_YES; - notify_ret = tmit->notify_data (tmit->notify_data_cls, &data_size, &msg[1]); - tmit->in_notify = GNUNET_NO; - } - LOG (GNUNET_ERROR_TYPE_DEBUG, - "transmit_data (ret: %d, size: %u): %.*s\n", - notify_ret, data_size, data_size, &msg[1]); - switch (notify_ret) - { - case GNUNET_NO: - if (0 == data_size) - { - /* Transmission paused, nothing to send. */ - tmit->paused = GNUNET_YES; - return; - } - break; - - case GNUNET_YES: - tmit->state = GNUNET_PSYC_MESSAGE_STATE_END; - break; - - default: - LOG (GNUNET_ERROR_TYPE_ERROR, - "TransmitNotifyData callback returned error when requesting data.\n"); - - tmit->state = GNUNET_PSYC_MESSAGE_STATE_CANCEL; - msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL); - msg->size = htons (sizeof (*msg)); - transmit_queue_insert (tmit, msg, GNUNET_YES); - tmit->in_transmit = GNUNET_NO; - return; - } - - if (0 < data_size) - { - GNUNET_assert (data_size <= GNUNET_PSYC_DATA_MAX_PAYLOAD); - msg->size = htons (sizeof (*msg) + data_size); - transmit_queue_insert (tmit, msg, !notify_ret); - } - - /* End of message. */ - if (GNUNET_YES == notify_ret) - { - msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END); - msg->size = htons (sizeof (*msg)); - transmit_queue_insert (tmit, msg, GNUNET_YES); - /* FIXME: wait for ACK before setting in_transmit to no */ - tmit->in_transmit = GNUNET_NO; - } -} - - -/** - * Request a modifier from a client to transmit. - * - * @param tmit Transmission handle. - */ -static void -transmit_mod (struct GNUNET_PSYC_TransmitHandle *tmit) -{ - uint16_t max_data_size = 0; - uint16_t data_size = 0; - char data[GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD] = ""; - struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) data; - int notify_ret = GNUNET_YES; - - switch (tmit->state) - { - case GNUNET_PSYC_MESSAGE_STATE_MODIFIER: - { - struct GNUNET_PSYC_MessageModifier *mod - = (struct GNUNET_PSYC_MessageModifier *) msg; - msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER); - msg->size = sizeof (struct GNUNET_PSYC_MessageModifier); - - if (NULL != tmit->notify_mod) - { - max_data_size = GNUNET_PSYC_MODIFIER_MAX_PAYLOAD; - data_size = max_data_size; - tmit->in_notify = GNUNET_YES; - notify_ret = tmit->notify_mod (tmit->notify_mod_cls, &data_size, &mod[1], - &mod->oper, &mod->value_size); - tmit->in_notify = GNUNET_NO; - } - - mod->name_size = strnlen ((char *) &mod[1], data_size) + 1; - LOG (GNUNET_ERROR_TYPE_DEBUG, - "transmit_mod (ret: %d, size: %u + %u): %.*s\n", - notify_ret, mod->name_size, mod->value_size, data_size, &mod[1]); - if (mod->name_size < data_size) - { - tmit->mod_value_remaining - = mod->value_size - (data_size - mod->name_size); - mod->value_size = htonl (mod->value_size); - mod->name_size = htons (mod->name_size); - } - else if (0 < data_size) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got invalid modifier name.\n"); - notify_ret = GNUNET_SYSERR; - } - break; - } - case GNUNET_PSYC_MESSAGE_STATE_MOD_CONT: - { - msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT); - msg->size = sizeof (struct GNUNET_MessageHeader); - - if (NULL != tmit->notify_mod) - { - max_data_size = GNUNET_PSYC_MOD_CONT_MAX_PAYLOAD; - data_size = max_data_size; - tmit->in_notify = GNUNET_YES; - notify_ret = tmit->notify_mod (tmit->notify_mod_cls, - &data_size, &msg[1], NULL, NULL); - tmit->in_notify = GNUNET_NO; - } - tmit->mod_value_remaining -= data_size; - LOG (GNUNET_ERROR_TYPE_DEBUG, - "transmit_mod (ret: %d, size: %u): %.*s\n", - notify_ret, data_size, data_size, &msg[1]); - break; - } - default: - GNUNET_assert (0); - } - - switch (notify_ret) - { - case GNUNET_NO: - if (0 == data_size) - { /* Transmission paused, nothing to send. */ - tmit->paused = GNUNET_YES; - return; - } - tmit->state - = (0 == tmit->mod_value_remaining) - ? GNUNET_PSYC_MESSAGE_STATE_MODIFIER - : GNUNET_PSYC_MESSAGE_STATE_MOD_CONT; - break; - - case GNUNET_YES: /* End of modifiers. */ - GNUNET_assert (0 == tmit->mod_value_remaining); - break; - - default: - LOG (GNUNET_ERROR_TYPE_ERROR, - "TransmitNotifyModifier callback returned with error.\n"); - - tmit->state = GNUNET_PSYC_MESSAGE_STATE_CANCEL; - msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL); - msg->size = htons (sizeof (*msg)); - transmit_queue_insert (tmit, msg, GNUNET_YES); - tmit->in_transmit = GNUNET_NO; - return; - } - - if (0 < data_size) - { - GNUNET_assert (data_size <= max_data_size); - msg->size = htons (msg->size + data_size); - transmit_queue_insert (tmit, msg, GNUNET_NO); - } - - if (GNUNET_YES == notify_ret) - { - tmit->state = GNUNET_PSYC_MESSAGE_STATE_DATA; - if (0 == tmit->acks_pending) - transmit_data (tmit); - } - else - { - transmit_mod (tmit); - } -} - - -int -transmit_notify_env (void *cls, uint16_t *data_size, void *data, uint8_t *oper, - uint32_t *full_value_size) - -{ - struct GNUNET_PSYC_TransmitHandle *tmit = cls; - uint16_t name_size = 0; - uint32_t value_size = 0; - const char *value = NULL; - - if (NULL != oper) - { /* New modifier */ - if (NULL != tmit->mod) - tmit->mod = tmit->mod->next; - if (NULL == tmit->mod) - { /* No more modifiers, continue with data */ - *data_size = 0; - return GNUNET_YES; - } - - GNUNET_assert (tmit->mod->value_size < UINT32_MAX); - *full_value_size = tmit->mod->value_size; - *oper = tmit->mod->oper; - name_size = strlen (tmit->mod->name) + 1; - - if (name_size + tmit->mod->value_size <= *data_size) - { - value_size = tmit->mod->value_size; - *data_size = name_size + value_size; - } - else /* full modifier does not fit in data, continuation needed */ - { - value_size = *data_size - name_size; - tmit->mod_value = tmit->mod->value + value_size; - } - - memcpy (data, tmit->mod->name, name_size); - memcpy ((char *)data + name_size, tmit->mod->value, value_size); - return GNUNET_NO; - } - else - { /* Modifier continuation */ - GNUNET_assert (NULL != tmit->mod_value && 0 < tmit->mod_value_remaining); - value = tmit->mod_value; - if (tmit->mod_value_remaining <= *data_size) - { - value_size = tmit->mod_value_remaining; - tmit->mod_value = NULL; - } - else - { - value_size = *data_size; - tmit->mod_value += value_size; - } - - if (*data_size < value_size) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Value in environment larger than buffer: %u < %zu\n", - *data_size, value_size); - *data_size = 0; - return GNUNET_NO; - } - - *data_size = value_size; - memcpy (data, value, value_size); - return (NULL == tmit->mod_value) ? GNUNET_YES : GNUNET_NO; - } -} - - -/** - * Transmit a message. - * - * @param tmit - * Transmission handle. - * @param method_name - * Which method should be invoked. - * @param env - * Environment for the message. - * Should stay available until the first call to notify_data. - * Can be NULL if there are no modifiers or @a notify_mod is - * provided instead. - * @param notify_mod - * Function to call to obtain modifiers. - * Can be NULL if there are no modifiers or @a env is provided instead. - * @param notify_data - * Function to call to obtain fragments of the data. - * @param notify_cls - * Closure for @a notify_mod and @a notify_data. - * @param flags - * Flags for the message being transmitted. - * - * @return #GNUNET_OK if the transmission was started. - * #GNUNET_SYSERR if another transmission is already going on. - */ -int -GNUNET_PSYC_transmit_message (struct GNUNET_PSYC_TransmitHandle *tmit, - const char *method_name, - const struct GNUNET_ENV_Environment *env, - GNUNET_PSYC_TransmitNotifyModifier notify_mod, - GNUNET_PSYC_TransmitNotifyData notify_data, - void *notify_cls, - uint32_t flags) -{ - if (GNUNET_NO != tmit->in_transmit) - return GNUNET_SYSERR; - tmit->in_transmit = GNUNET_YES; - - size_t size = strlen (method_name) + 1; - struct GNUNET_PSYC_MessageMethod *pmeth; - tmit->msg = GNUNET_malloc (sizeof (*tmit->msg) + sizeof (*pmeth) + size); - tmit->msg->size = sizeof (*tmit->msg) + sizeof (*pmeth) + size; - - if (NULL != notify_mod) - { - tmit->notify_mod = notify_mod; - tmit->notify_mod_cls = notify_cls; - } - else - { - tmit->notify_mod = &transmit_notify_env; - tmit->notify_mod_cls = tmit; - if (NULL != env) - { - struct GNUNET_ENV_Modifier mod = {}; - mod.next = GNUNET_ENV_environment_head (env); - tmit->mod = &mod; - - struct GNUNET_ENV_Modifier *m = tmit->mod; - while (NULL != (m = m->next)) - { - if (m->oper != GNUNET_ENV_OP_SET) - flags |= GNUNET_PSYC_MASTER_TRANSMIT_STATE_MODIFY; - } - } - else - { - tmit->mod = NULL; - } - } - - pmeth = (struct GNUNET_PSYC_MessageMethod *) &tmit->msg[1]; - pmeth->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD); - pmeth->header.size = htons (sizeof (*pmeth) + size); - pmeth->flags = htonl (flags); - memcpy (&pmeth[1], method_name, size); - - tmit->state = GNUNET_PSYC_MESSAGE_STATE_MODIFIER; - tmit->notify_data = notify_data; - tmit->notify_data_cls = notify_cls; - - transmit_mod (tmit); - return GNUNET_OK; -} - - -/** - * Resume transmission. - * - * @param tmit Transmission handle. - */ -void -GNUNET_PSYC_transmit_resume (struct GNUNET_PSYC_TransmitHandle *tmit) -{ - if (GNUNET_YES != tmit->in_transmit || GNUNET_NO != tmit->in_notify) - return; - - if (0 == tmit->acks_pending) - { - tmit->paused = GNUNET_NO; - transmit_data (tmit); - } -} - - -/** - * Abort transmission request. - * - * @param tmit Transmission handle. - */ -void -GNUNET_PSYC_transmit_cancel (struct GNUNET_PSYC_TransmitHandle *tmit) -{ - if (GNUNET_NO == tmit->in_transmit) - return; - - tmit->state = GNUNET_PSYC_MESSAGE_STATE_CANCEL; - tmit->in_transmit = GNUNET_NO; - tmit->paused = GNUNET_NO; - - /* FIXME */ - struct GNUNET_MessageHeader msg; - msg.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA); - msg.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL); - msg.size = htons (sizeof (msg)); - transmit_queue_insert (tmit, &msg, GNUNET_YES); -} - - -/** - * Got acknowledgement of a transmitted message part, continue transmission. - * - * @param tmit Transmission handle. - */ -void -GNUNET_PSYC_transmit_got_ack (struct GNUNET_PSYC_TransmitHandle *tmit) -{ - if (0 == tmit->acks_pending) - { - LOG (GNUNET_ERROR_TYPE_WARNING, "Ignoring extraneous message ACK\n"); - GNUNET_break (0); - return; - } - tmit->acks_pending--; - - switch (tmit->state) - { - case GNUNET_PSYC_MESSAGE_STATE_MODIFIER: - case GNUNET_PSYC_MESSAGE_STATE_MOD_CONT: - transmit_mod (tmit); - break; - - case GNUNET_PSYC_MESSAGE_STATE_DATA: - transmit_data (tmit); - break; - - case GNUNET_PSYC_MESSAGE_STATE_END: - case GNUNET_PSYC_MESSAGE_STATE_CANCEL: - break; - - default: - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Ignoring message ACK in state %u.\n", tmit->state); - } -} - - -/**** Receiving messages ****/ - - -/** - * Create handle for receiving messages. - */ -struct GNUNET_PSYC_ReceiveHandle * -GNUNET_PSYC_receive_create (GNUNET_PSYC_MessageCallback message_cb, - GNUNET_PSYC_MessagePartCallback message_part_cb, - void *cb_cls) -{ - struct GNUNET_PSYC_ReceiveHandle *recv = GNUNET_malloc (sizeof (*recv)); - recv->message_cb = message_cb; - recv->message_part_cb = message_part_cb; - recv->cb_cls = cb_cls; - return recv; -} - - -/** - * Destroy handle for receiving messages. - */ -void -GNUNET_PSYC_receive_destroy (struct GNUNET_PSYC_ReceiveHandle *recv) -{ - GNUNET_free (recv); -} - - -/** - * Reset stored data related to the last received message. - */ -void -GNUNET_PSYC_receive_reset (struct GNUNET_PSYC_ReceiveHandle *recv) -{ - recv->state = GNUNET_PSYC_MESSAGE_STATE_START; - recv->flags = 0; - recv->message_id = 0; - recv->mod_value_size = 0; - recv->mod_value_size_expected = 0; -} - - -static void -recv_error (struct GNUNET_PSYC_ReceiveHandle *recv) -{ - if (NULL != recv->message_part_cb) - recv->message_part_cb (recv->cb_cls, NULL, recv->message_id, recv->flags, - 0, NULL); - - if (NULL != recv->message_cb) - recv->message_cb (recv->cb_cls, recv->message_id, recv->flags, NULL); - - GNUNET_PSYC_receive_reset (recv); -} - - -/** - * Handle incoming PSYC message. - * - * @param recv Receive handle. - * @param msg The message. - * - * @return #GNUNET_OK on success, - * #GNUNET_SYSERR on receive error. - */ -int -GNUNET_PSYC_receive_message (struct GNUNET_PSYC_ReceiveHandle *recv, - const struct GNUNET_PSYC_MessageHeader *msg) -{ - uint16_t size = ntohs (msg->header.size); - uint32_t flags = ntohl (msg->flags); - uint64_t message_id; - - GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, - (struct GNUNET_MessageHeader *) msg); - - if (GNUNET_PSYC_MESSAGE_STATE_START == recv->state) - { - recv->message_id = GNUNET_ntohll (msg->message_id); - recv->flags = flags; - recv->slave_key = msg->slave_key; - recv->mod_value_size = 0; - recv->mod_value_size_expected = 0; - } - else if (GNUNET_ntohll (msg->message_id) != recv->message_id) - { - // FIXME - LOG (GNUNET_ERROR_TYPE_WARNING, - "Unexpected message ID. Got: %" PRIu64 ", expected: %" PRIu64 "\n", - GNUNET_ntohll (msg->message_id), recv->message_id); - GNUNET_break_op (0); - recv_error (recv); - return GNUNET_SYSERR; - } - else if (flags != recv->flags) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Unexpected message flags. Got: %lu, expected: %lu\n", - flags, recv->flags); - GNUNET_break_op (0); - recv_error (recv); - return GNUNET_SYSERR; - } - message_id = recv->message_id; - - uint16_t pos = 0, psize = 0, ptype, size_eq, size_min; - - for (pos = 0; sizeof (*msg) + pos < size; pos += psize) - { - const struct GNUNET_MessageHeader *pmsg - = (const struct GNUNET_MessageHeader *) ((char *) &msg[1] + pos); - psize = ntohs (pmsg->size); - ptype = ntohs (pmsg->type); - size_eq = size_min = 0; - - if (psize < sizeof (*pmsg) || sizeof (*msg) + pos + psize > size) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Dropping message of type %u with invalid size %u.\n", - ptype, psize); - recv_error (recv); - return GNUNET_SYSERR; - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received message part of type %u and size %u from PSYC.\n", - ptype, psize); - GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, pmsg); - - switch (ptype) - { - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD: - size_min = sizeof (struct GNUNET_PSYC_MessageMethod); - break; - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: - size_min = sizeof (struct GNUNET_PSYC_MessageModifier); - break; - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT: - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA: - size_min = sizeof (struct GNUNET_MessageHeader); - break; - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END: - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL: - size_eq = sizeof (struct GNUNET_MessageHeader); - break; - default: - GNUNET_break_op (0); - recv_error (recv); - return GNUNET_SYSERR; - } - - if (! ((0 < size_eq && psize == size_eq) - || (0 < size_min && size_min <= psize))) - { - GNUNET_break_op (0); - recv_error (recv); - return GNUNET_SYSERR; - } - - switch (ptype) - { - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD: - { - struct GNUNET_PSYC_MessageMethod *meth - = (struct GNUNET_PSYC_MessageMethod *) pmsg; - - if (GNUNET_PSYC_MESSAGE_STATE_START != recv->state) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Dropping out of order message method (%u).\n", - recv->state); - /* It is normal to receive an incomplete message right after connecting, - * but should not happen later. - * FIXME: add a check for this condition. - */ - GNUNET_break_op (0); - recv_error (recv); - return GNUNET_SYSERR; - } - - if ('\0' != *((char *) meth + psize - 1)) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Dropping message with malformed method. " - "Message ID: %" PRIu64 "\n", recv->message_id); - GNUNET_break_op (0); - recv_error (recv); - return GNUNET_SYSERR; - } - recv->state = GNUNET_PSYC_MESSAGE_STATE_METHOD; - break; - } - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: - { - if (!(GNUNET_PSYC_MESSAGE_STATE_METHOD == recv->state - || GNUNET_PSYC_MESSAGE_STATE_MODIFIER == recv->state - || GNUNET_PSYC_MESSAGE_STATE_MOD_CONT == recv->state)) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Dropping out of order message modifier (%u).\n", - recv->state); - GNUNET_break_op (0); - recv_error (recv); - return GNUNET_SYSERR; - } - - struct GNUNET_PSYC_MessageModifier *mod - = (struct GNUNET_PSYC_MessageModifier *) pmsg; - - uint16_t name_size = ntohs (mod->name_size); - recv->mod_value_size_expected = ntohl (mod->value_size); - recv->mod_value_size = psize - sizeof (*mod) - name_size; - - if (psize < sizeof (*mod) + name_size - || '\0' != *((char *) &mod[1] + name_size - 1) - || recv->mod_value_size_expected < recv->mod_value_size) - { - LOG (GNUNET_ERROR_TYPE_WARNING, "Dropping malformed modifier.\n"); - GNUNET_break_op (0); - recv_error (recv); - return GNUNET_SYSERR; - } - recv->state = GNUNET_PSYC_MESSAGE_STATE_MODIFIER; - break; - } - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT: - { - recv->mod_value_size += psize - sizeof (*pmsg); - - if (!(GNUNET_PSYC_MESSAGE_STATE_MODIFIER == recv->state - || GNUNET_PSYC_MESSAGE_STATE_MOD_CONT == recv->state) - || recv->mod_value_size_expected < recv->mod_value_size) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Dropping out of order message modifier continuation " - "!(%u == %u || %u == %u) || %lu < %lu.\n", - GNUNET_PSYC_MESSAGE_STATE_MODIFIER, recv->state, - GNUNET_PSYC_MESSAGE_STATE_MOD_CONT, recv->state, - recv->mod_value_size_expected, recv->mod_value_size); - GNUNET_break_op (0); - recv_error (recv); - return GNUNET_SYSERR; - } - break; - } - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA: - { - if (recv->state < GNUNET_PSYC_MESSAGE_STATE_METHOD - || recv->mod_value_size_expected != recv->mod_value_size) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Dropping out of order message data fragment " - "(%u < %u || %lu != %lu).\n", - recv->state, GNUNET_PSYC_MESSAGE_STATE_METHOD, - recv->mod_value_size_expected, recv->mod_value_size); - - GNUNET_break_op (0); - recv_error (recv); - return GNUNET_SYSERR; - } - recv->state = GNUNET_PSYC_MESSAGE_STATE_DATA; - break; - } - } - - if (NULL != recv->message_part_cb) - recv->message_part_cb (recv->cb_cls, &recv->slave_key, - recv->message_id, recv->flags, - 0, // FIXME: data_offset - pmsg); - - switch (ptype) - { - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END: - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL: - GNUNET_PSYC_receive_reset (recv); - break; - } - } - - if (NULL != recv->message_cb) - recv->message_cb (recv->cb_cls, message_id, flags, msg); - return GNUNET_OK; -} - - -/** - * Check if @a data contains a series of valid message parts. - * - * @param data_size Size of @a data. - * @param data Data. - * @param[out] first_ptype Type of first message part. - * @param[out] last_ptype Type of last message part. - * - * @return Number of message parts found in @a data. - * or GNUNET_SYSERR if the message contains invalid parts. - */ -int -GNUNET_PSYC_receive_check_parts (uint16_t data_size, const char *data, - uint16_t *first_ptype, uint16_t *last_ptype) -{ - const struct GNUNET_MessageHeader *pmsg; - uint16_t parts = 0, ptype = 0, psize = 0, pos = 0; - if (NULL != first_ptype) - *first_ptype = 0; - if (NULL != last_ptype) - *last_ptype = 0; - - for (pos = 0; pos < data_size; pos += psize, parts++) - { - pmsg = (const struct GNUNET_MessageHeader *) (data + pos); - GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, pmsg); - psize = ntohs (pmsg->size); - ptype = ntohs (pmsg->type); - if (0 == parts && NULL != first_ptype) - *first_ptype = ptype; - if (NULL != last_ptype - && *last_ptype < GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END) - *last_ptype = ptype; - if (psize < sizeof (*pmsg) - || pos + psize > data_size - || ptype < GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD - || GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL < ptype) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid message part of type %u and size %u.\n", - ptype, psize); - return GNUNET_SYSERR; - } - /** @todo FIXME: check message part order */ - } - return parts; -} - - -struct ParseMessageClosure -{ - struct GNUNET_ENV_Environment *env; - const char **method_name; - const void **data; - uint16_t *data_size; - enum GNUNET_PSYC_MessageState msg_state; -}; - - -static void -parse_message_part_cb (void *cls, - const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key, - uint64_t message_id, uint32_t flags, uint64_t data_offset, - const struct GNUNET_MessageHeader *msg) -{ - struct ParseMessageClosure *pmc = cls; - if (NULL == msg) - { - pmc->msg_state = GNUNET_PSYC_MESSAGE_STATE_ERROR; - return; - } - - switch (ntohs (msg->type)) - { - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD: - { - struct GNUNET_PSYC_MessageMethod * - pmeth = (struct GNUNET_PSYC_MessageMethod *) msg; - *pmc->method_name = (const char *) &pmeth[1]; - pmc->msg_state = GNUNET_PSYC_MESSAGE_STATE_METHOD; - break; - } - - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: - { - struct GNUNET_PSYC_MessageModifier * - pmod = (struct GNUNET_PSYC_MessageModifier *) msg; - - const char *name = (const char *) &pmod[1]; - const void *value = name + ntohs (pmod->name_size); - GNUNET_ENV_environment_add (pmc->env, pmod->oper, name, value, - ntohl (pmod->value_size)); - pmc->msg_state = GNUNET_PSYC_MESSAGE_STATE_MODIFIER; - break; - } - - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA: - *pmc->data = &msg[1]; - *pmc->data_size = ntohs (msg->size) - sizeof (*msg); - pmc->msg_state = GNUNET_PSYC_MESSAGE_STATE_DATA; - break; - - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END: - pmc->msg_state = GNUNET_PSYC_MESSAGE_STATE_END; - break; - - default: - pmc->msg_state = GNUNET_PSYC_MESSAGE_STATE_ERROR; - } -} - - -/** - * Parse PSYC message. - * - * @param msg - * The PSYC message to parse. - * @param[out] method_name - * Pointer to the method name inside @a pmsg. - * @param env - * The environment for the message with a list of modifiers. - * @param[out] data - * Pointer to data inside @a pmsg. - * @param[out] data_size - * Size of @data is written here. - * - * @return #GNUNET_OK on success, - * #GNUNET_SYSERR on parse error. - */ -int -GNUNET_PSYC_message_parse (const struct GNUNET_PSYC_MessageHeader *msg, - const char **method_name, - struct GNUNET_ENV_Environment *env, - const void **data, - uint16_t *data_size) -{ - struct ParseMessageClosure cls; - cls.env = env; - cls.method_name = method_name; - cls.data = data; - cls.data_size = data_size; - - struct GNUNET_PSYC_ReceiveHandle * - recv = GNUNET_PSYC_receive_create (NULL, parse_message_part_cb, &cls); - int ret = GNUNET_PSYC_receive_message (recv, msg); - GNUNET_PSYC_receive_destroy (recv); - - if (GNUNET_OK != ret) - return GNUNET_SYSERR; - - return (GNUNET_PSYC_MESSAGE_STATE_END == cls.msg_state) - ? GNUNET_OK - : GNUNET_NO; -} - - -/** - * Initialize PSYC message header. - */ -void -GNUNET_PSYC_message_header_init (struct GNUNET_PSYC_MessageHeader *pmsg, - const struct GNUNET_MULTICAST_MessageHeader *mmsg, - uint32_t flags) -{ - uint16_t size = ntohs (mmsg->header.size); - uint16_t psize = sizeof (*pmsg) + size - sizeof (*mmsg); - - pmsg->header.size = htons (psize); - pmsg->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE); - pmsg->message_id = mmsg->message_id; - pmsg->fragment_offset = mmsg->fragment_offset; - pmsg->flags = htonl (flags); - - memcpy (&pmsg[1], &mmsg[1], size - sizeof (*mmsg)); -} - - -/** - * Create a new PSYC message header from a multicast message. - */ -struct GNUNET_PSYC_MessageHeader * -GNUNET_PSYC_message_header_create (const struct GNUNET_MULTICAST_MessageHeader *mmsg, - uint32_t flags) -{ - struct GNUNET_PSYC_MessageHeader *pmsg; - uint16_t size = ntohs (mmsg->header.size); - uint16_t psize = sizeof (*pmsg) + size - sizeof (*mmsg); - - pmsg = GNUNET_malloc (psize); - GNUNET_PSYC_message_header_init (pmsg, mmsg, flags); - return pmsg; -} - - -/** - * Create a new PSYC message header from a PSYC message. - */ -struct GNUNET_PSYC_MessageHeader * -GNUNET_PSYC_message_header_create_from_psyc (const struct GNUNET_PSYC_Message *msg) -{ - uint16_t msg_size = ntohs (msg->header.size); - struct GNUNET_PSYC_MessageHeader * - pmsg = GNUNET_malloc (sizeof (*pmsg) + msg_size - sizeof (*msg)); - pmsg->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE); - pmsg->header.size = htons (sizeof (*pmsg) + msg_size - sizeof (*msg)); - memcpy (&pmsg[1], &msg[1], msg_size - sizeof (*msg)); - return pmsg; -} diff --git a/src/psycstore/psycstore_api.c b/src/psycstore/psycstore_api.c @@ -1303,7 +1303,7 @@ GNUNET_PSYCSTORE_state_sync (struct GNUNET_PSYCSTORE_Handle *h, uint64_t max_state_message_id, uint64_t state_hash_message_id, size_t modifier_count, - const struct GNUNET_ENV_Modifier *modifiers, + const struct GNUNET_PSYC_Modifier *modifiers, GNUNET_PSYCSTORE_ResultCallback rcb, void *rcb_cls) { diff --git a/src/psycstore/test_plugin_psycstore.c b/src/psycstore/test_plugin_psycstore.c @@ -18,11 +18,12 @@ * Boston, MA 02110-1301, USA. */ -/* - * @file psycstore/test_plugin_psycstore.c - * @brief Test for the PSYCstore plugins. +/** * @author Gabor X Toth * @author Christian Grothoff + * + * @file + * Test for the PSYCstore plugins. */ #include "platform.h" #include "gnunet_util_lib.h" @@ -309,12 +310,12 @@ run (void *cls, char *const *args, const char *cfgfile, message_id, 0)); GNUNET_assert (GNUNET_OK == db->state_modify_op (db->cls, &channel_pub_key, - GNUNET_ENV_OP_ASSIGN, + GNUNET_PSYC_OP_ASSIGN, "_foo", C2ARG("one two three"))); GNUNET_assert (GNUNET_OK == db->state_modify_op (db->cls, &channel_pub_key, - GNUNET_ENV_OP_ASSIGN, + GNUNET_PSYC_OP_ASSIGN, "_foo_bar", slave_key, sizeof (*slave_key))); @@ -401,7 +402,7 @@ run (void *cls, char *const *args, const char *cfgfile, message_id - max_state_msg_id)); GNUNET_assert (GNUNET_OK == db->state_modify_op (db->cls, &channel_pub_key, - GNUNET_ENV_OP_ASSIGN, + GNUNET_PSYC_OP_ASSIGN, "_sync_foo", C2ARG("five six seven"))); diff --git a/src/psycstore/test_psycstore.c b/src/psycstore/test_psycstore.c @@ -77,7 +77,7 @@ struct StateClosure { size_t value_size[16]; } scls; -static struct GNUNET_ENV_Modifier modifiers[16]; +static struct GNUNET_PSYC_Modifier modifiers[16]; /** * Clean up all resources used. @@ -328,13 +328,13 @@ message_get_latest_result (void *cls, int64_t result, GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "message_get_latest:\t%d\n", result); GNUNET_assert (0 < result && fcls->n == fcls->n_expected); - modifiers[0] = (struct GNUNET_ENV_Modifier) { + modifiers[0] = (struct GNUNET_PSYC_Modifier) { .oper = '=', .name = "_sync_foo", .value = "three two one", .value_size = sizeof ("three two one") - 1 }; - modifiers[1] = (struct GNUNET_ENV_Modifier) { + modifiers[1] = (struct GNUNET_PSYC_Modifier) { .oper = '=', .name = "_sync_bar", .value = "ten eleven twelve", diff --git a/src/psycutil/Makefile.am b/src/psycutil/Makefile.am @@ -0,0 +1,45 @@ +# This Makefile.am is in the public domain +AM_CPPFLAGS = -I$(top_srcdir)/src/include + +pkgcfgdir= $(pkgdatadir)/config.d/ + +libexecdir= $(pkglibdir)/libexec/ + +if MINGW + WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols +endif + +if USE_COVERAGE + AM_CFLAGS = --coverage -O0 + XLIB = -lgcov +endif + +lib_LTLIBRARIES = libgnunetpsycutil.la + +libgnunetpsycutil_la_SOURCES = \ + psyc_env.c \ + psyc_message.c \ + psyc_slicer.c +libgnunetpsycutil_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) $(XLIB) +libgnunetpsycutil_la_LDFLAGS = \ + $(GN_LIB_LDFLAGS) $(WINFLAGS) \ + -version-info 0:0:0 + +if HAVE_TESTING +check_PROGRAMS = \ + test_psyc_env +endif + +if ENABLE_TEST_RUN +AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; +TESTS = $(check_PROGRAMS) +endif + +test_psyc_env_SOURCES = \ + test_psyc_env.c +test_psyc_env_LDADD = \ + libgnunetpsycutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/util/libgnunetutil.la diff --git a/src/psycutil/psyc_env.c b/src/psycutil/psyc_env.c @@ -0,0 +1,196 @@ +/* + * This file is part of GNUnet. + * Copyright (C) 2013 Christian Grothoff (and other contributing authors) + * + * 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 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. + */ + +/** + * @author Gabor X Toth + * + * @file + * Library providing operations for the @e environment of + * PSYC and Social messages. + */ + +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_psyc_env.h" + +/** + * Environment for a message. + * + * Contains modifiers. + */ +struct GNUNET_PSYC_Environment +{ + struct GNUNET_PSYC_Modifier *mod_head; + struct GNUNET_PSYC_Modifier *mod_tail; + size_t mod_count; +}; + + +/** + * Create an environment. + * + * @return A newly allocated environment. + */ +struct GNUNET_PSYC_Environment * +GNUNET_PSYC_env_create () +{ + return GNUNET_new (struct GNUNET_PSYC_Environment); +} + + +/** + * Add a modifier to the environment. + * + * @param env The environment. + * @param oper Operation to perform. + * @param name Name of the variable. + * @param value Value of the variable. + * @param value_size Size of @a value. + */ +void +GNUNET_PSYC_env_add (struct GNUNET_PSYC_Environment *env, + enum GNUNET_PSYC_Operator oper, const char *name, + const void *value, size_t value_size) +{ + struct GNUNET_PSYC_Modifier *mod = GNUNET_new (struct GNUNET_PSYC_Modifier); + mod->oper = oper; + mod->name = name; + mod->value = value; + mod->value_size = value_size; + GNUNET_CONTAINER_DLL_insert_tail (env->mod_head, env->mod_tail, mod); + env->mod_count++; +} + + +/** + * Get the first modifier of the environment. + */ +struct GNUNET_PSYC_Modifier * +GNUNET_PSYC_env_head (const struct GNUNET_PSYC_Environment *env) +{ + return env->mod_head; +} + + +/** + * Get the last modifier of the environment. + */ +struct GNUNET_PSYC_Modifier * +GNUNET_PSYC_env_tail (const struct GNUNET_PSYC_Environment *env) +{ + return env->mod_tail; +} + + +/** + * Remove a modifier from the environment. + */ +void +GNUNET_PSYC_env_remove (struct GNUNET_PSYC_Environment *env, + struct GNUNET_PSYC_Modifier *mod) +{ + GNUNET_CONTAINER_DLL_remove (env->mod_head, env->mod_tail, mod); +} + + +/** + * Get the modifier at the beginning of an environment and remove it. + * + * @param env + * @param oper + * @param name + * @param value + * @param value_size + * + * @return + */ +int +GNUNET_PSYC_env_shift (struct GNUNET_PSYC_Environment *env, + enum GNUNET_PSYC_Operator *oper, const char **name, + const void **value, size_t *value_size) +{ + if (NULL == env->mod_head) + return GNUNET_NO; + + struct GNUNET_PSYC_Modifier *mod = env->mod_head; + *oper = mod->oper; + *name = mod->name; + *value = mod->value; + *value_size = mod->value_size; + + GNUNET_CONTAINER_DLL_remove (env->mod_head, env->mod_tail, mod); + GNUNET_free (mod); + env->mod_count--; + + return GNUNET_YES; +} + + +/** + * Iterate through all modifiers in the environment. + * + * @param env The environment. + * @param it Iterator. + * @param it_cls Closure for iterator. + */ +void +GNUNET_PSYC_env_iterate (const struct GNUNET_PSYC_Environment *env, + GNUNET_PSYC_Iterator it, void *it_cls) +{ + struct GNUNET_PSYC_Modifier *mod; + for (mod = env->mod_head; NULL != mod; mod = mod->next) + it (it_cls, mod->oper, mod->name, mod->value, mod->value_size); +} + + +/** + * Get the number of modifiers in the environment. + * + * @param env The environment. + * + * @return Number of modifiers. + */ +size_t +GNUNET_PSYC_env_get_count (const struct GNUNET_PSYC_Environment *env) +{ + return env->mod_count; +} + + +/** + * Destroy an environment. + * + * @param env The environment to destroy. + */ +void +GNUNET_PSYC_env_destroy (struct GNUNET_PSYC_Environment *env) +{ + struct GNUNET_PSYC_Modifier *mod, *prev = NULL; + for (mod = env->mod_head; NULL != mod; mod = mod->next) + { + if (NULL != prev) + GNUNET_free (prev); + prev = mod; + } + if (NULL != prev) + GNUNET_free (prev); + + GNUNET_free (env); +} diff --git a/src/psycutil/psyc_message.c b/src/psycutil/psyc_message.c @@ -0,0 +1,1329 @@ +/* + * This file is part of GNUnet + * Copyright (C) 2013 Christian Grothoff (and other contributing authors) + * + * 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 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. + */ + +/** + * @file psycstore/psyc_util_lib.c + * @brief PSYC utilities; receiving/transmitting/logging PSYC messages. + * @author Gabor X Toth + */ + +#include <inttypes.h> + +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_psyc_util_lib.h" +#include "gnunet_psyc_service.h" + +#define LOG(kind,...) GNUNET_log_from (kind, "psyc-util",__VA_ARGS__) + + +struct GNUNET_PSYC_TransmitHandle +{ + /** + * Client connection to service. + */ + struct GNUNET_CLIENT_MANAGER_Connection *client; + + /** + * Message currently being received from the client. + */ + struct GNUNET_MessageHeader *msg; + + /** + * Callback to request next modifier from client. + */ + GNUNET_PSYC_TransmitNotifyModifier notify_mod; + + /** + * Closure for the notify callbacks. + */ + void *notify_mod_cls; + + /** + * Callback to request next data fragment from client. + */ + GNUNET_PSYC_TransmitNotifyData notify_data; + + /** + * Closure for the notify callbacks. + */ + void *notify_data_cls; + + /** + * Modifier of the environment that is currently being transmitted. + */ + struct GNUNET_PSYC_Modifier *mod; + + /** + * + */ + const char *mod_value; + + /** + * Number of bytes remaining to be transmitted from the current modifier value. + */ + uint32_t mod_value_remaining; + + /** + * State of the current message being received from client. + */ + enum GNUNET_PSYC_MessageState state; + + /** + * Number of PSYC_TRANSMIT_ACK messages we are still waiting for. + */ + uint8_t acks_pending; + + /** + * Is transmission paused? + */ + uint8_t paused; + + /** + * Are we currently transmitting a message? + */ + uint8_t in_transmit; + + /** + * Notify callback is currently being called. + */ + uint8_t in_notify; + +}; + + + +struct GNUNET_PSYC_ReceiveHandle +{ + /** + * Message callback. + */ + GNUNET_PSYC_MessageCallback message_cb; + + /** + * Message part callback. + */ + GNUNET_PSYC_MessagePartCallback message_part_cb; + + /** + * Closure for the callbacks. + */ + void *cb_cls; + + /** + * ID of the message being received from the PSYC service. + */ + uint64_t message_id; + + /** + * Public key of the slave from which a message is being received. + */ + struct GNUNET_CRYPTO_EcdsaPublicKey slave_key; + + /** + * State of the currently being received message from the PSYC service. + */ + enum GNUNET_PSYC_MessageState state; + + /** + * Flags for the currently being received message from the PSYC service. + */ + enum GNUNET_PSYC_MessageFlags flags; + + /** + * Expected value size for the modifier being received from the PSYC service. + */ + uint32_t mod_value_size_expected; + + /** + * Actual value size for the modifier being received from the PSYC service. + */ + uint32_t mod_value_size; +}; + + +/**** Messages ****/ + + +/** + * Create a PSYC message. + * + * @param method_name + * PSYC method for the message. + * @param env + * Environment for the message. + * @param data + * Data payload for the message. + * @param data_size + * Size of @a data. + * + * @return Message header with size information, + * followed by the message parts. + */ +struct GNUNET_PSYC_Message * +GNUNET_PSYC_message_create (const char *method_name, + const struct GNUNET_PSYC_Environment *env, + const void *data, + size_t data_size) +{ + struct GNUNET_PSYC_Modifier *mod = NULL; + struct GNUNET_PSYC_MessageMethod *pmeth = NULL; + struct GNUNET_PSYC_MessageModifier *pmod = NULL; + struct GNUNET_MessageHeader *pmsg = NULL; + uint16_t env_size = 0; + if (NULL != env) + { + mod = GNUNET_PSYC_env_head (env); + while (NULL != mod) + { + env_size += sizeof (*pmod) + strlen (mod->name) + 1 + mod->value_size; + mod = mod->next; + } + } + + struct GNUNET_PSYC_Message *msg; + uint16_t method_name_size = strlen (method_name) + 1; + if (method_name_size == 1) + return NULL; + + uint16_t msg_size = sizeof (*msg) /* header */ + + sizeof (*pmeth) + method_name_size /* method */ + + env_size /* modifiers */ + + ((0 < data_size) ? sizeof (*pmsg) + data_size : 0) /* data */ + + sizeof (*pmsg); /* end of message */ + msg = GNUNET_malloc (msg_size); + msg->header.size = htons (msg_size); + msg->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE); /* FIXME */ + + pmeth = (struct GNUNET_PSYC_MessageMethod *) &msg[1]; + pmeth->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD); + pmeth->header.size = htons (sizeof (*pmeth) + method_name_size); + memcpy (&pmeth[1], method_name, method_name_size); + + uint16_t p = sizeof (*msg) + sizeof (*pmeth) + method_name_size; + if (NULL != env) + { + mod = GNUNET_PSYC_env_head (env); + while (NULL != mod) + { + uint16_t mod_name_size = strlen (mod->name) + 1; + pmod = (struct GNUNET_PSYC_MessageModifier *) ((char *) msg + p); + pmod->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER); + pmod->header.size = sizeof (*pmod) + mod_name_size + mod->value_size; + p += pmod->header.size; + pmod->header.size = htons (pmod->header.size); + + pmod->oper = mod->oper; + pmod->name_size = htons (mod_name_size); + pmod->value_size = htonl (mod->value_size); + + memcpy (&pmod[1], mod->name, mod_name_size); + if (0 < mod->value_size) + memcpy ((char *) &pmod[1] + mod_name_size, mod->value, mod->value_size); + + mod = mod->next; + } + } + + if (0 < data_size) + { + pmsg = (struct GNUNET_MessageHeader *) ((char *) msg + p); + pmsg->size = sizeof (*pmsg) + data_size; + p += pmsg->size; + pmsg->size = htons (pmsg->size); + pmsg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA); + memcpy (&pmsg[1], data, data_size); + } + + pmsg = (struct GNUNET_MessageHeader *) ((char *) msg + p); + pmsg->size = htons (sizeof (*pmsg)); + pmsg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END); + + GNUNET_assert (p + sizeof (*pmsg) == msg_size); + return msg; +} + + +void +GNUNET_PSYC_log_message (enum GNUNET_ErrorType kind, + const struct GNUNET_MessageHeader *msg) +{ + uint16_t size = ntohs (msg->size); + uint16_t type = ntohs (msg->type); + GNUNET_log (kind, "Message of type %d and size %u:\n", type, size); + switch (type) + { + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE: + { + struct GNUNET_PSYC_MessageHeader *pmsg + = (struct GNUNET_PSYC_MessageHeader *) msg; + GNUNET_log (kind, "\tID: %" PRIu64 "\tflags: %x" PRIu32 "\n", + GNUNET_ntohll (pmsg->message_id), ntohl (pmsg->flags)); + break; + } + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD: + { + struct GNUNET_PSYC_MessageMethod *meth + = (struct GNUNET_PSYC_MessageMethod *) msg; + GNUNET_log (kind, "\t%.*s\n", size - sizeof (*meth), &meth[1]); + break; + } + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: + { + struct GNUNET_PSYC_MessageModifier *mod + = (struct GNUNET_PSYC_MessageModifier *) msg; + uint16_t name_size = ntohs (mod->name_size); + char oper = ' ' < mod->oper ? mod->oper : ' '; + GNUNET_log (kind, "\t%c%.*s\t%.*s\n", oper, name_size, &mod[1], + size - sizeof (*mod) - name_size, + ((char *) &mod[1]) + name_size); + break; + } + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT: + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA: + GNUNET_log (kind, "\t%.*s\n", size - sizeof (*msg), &msg[1]); + break; + } +} + + +/**** Transmitting messages ****/ + + +/** + * Create a transmission handle. + */ +struct GNUNET_PSYC_TransmitHandle * +GNUNET_PSYC_transmit_create (struct GNUNET_CLIENT_MANAGER_Connection *client) +{ + struct GNUNET_PSYC_TransmitHandle *tmit = GNUNET_malloc (sizeof (*tmit)); + tmit->client = client; + return tmit; +} + + +/** + * Destroy a transmission handle. + */ +void +GNUNET_PSYC_transmit_destroy (struct GNUNET_PSYC_TransmitHandle *tmit) +{ + GNUNET_free (tmit); +} + + +/** + * Queue a message part for transmission. + * + * The message part is added to the current message buffer. + * When this buffer is full, it is added to the transmission queue. + * + * @param tmit + * Transmission handle. + * @param msg + * Message part, or NULL. + * @param tmit_now + * Transmit message now, or wait for buffer to fill up? + * #GNUNET_YES or #GNUNET_NO. + */ +static void +transmit_queue_insert (struct GNUNET_PSYC_TransmitHandle *tmit, + const struct GNUNET_MessageHeader *msg, + uint8_t tmit_now) +{ + uint16_t size = (NULL != msg) ? ntohs (msg->size) : 0; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Queueing message part of type %u and size %u (tmit_now: %u)).\n", + NULL != msg ? ntohs (msg->type) : 0, size, tmit_now); + + if (NULL != tmit->msg) + { + if (NULL == msg + || GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD < tmit->msg->size + size) + { + /* End of message or buffer is full, add it to transmission queue + * and start with empty buffer */ + tmit->msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE); + tmit->msg->size = htons (tmit->msg->size); + GNUNET_CLIENT_MANAGER_transmit (tmit->client, tmit->msg); + tmit->msg = NULL; + tmit->acks_pending++; + } + else + { + /* Message fits in current buffer, append */ + tmit->msg = GNUNET_realloc (tmit->msg, tmit->msg->size + size); + memcpy ((char *) tmit->msg + tmit->msg->size, msg, size); + tmit->msg->size += size; + } + } + + if (NULL == tmit->msg && NULL != msg) + { + /* Empty buffer, copy over message. */ + tmit->msg = GNUNET_malloc (sizeof (*tmit->msg) + size); + tmit->msg->size = sizeof (*tmit->msg) + size; + memcpy (&tmit->msg[1], msg, size); + } + + if (NULL != tmit->msg + && (GNUNET_YES == tmit_now + || (GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD + < tmit->msg->size + sizeof (struct GNUNET_MessageHeader)))) + { + /* End of message or buffer is full, add it to transmission queue. */ + tmit->msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE); + tmit->msg->size = htons (tmit->msg->size); + GNUNET_CLIENT_MANAGER_transmit (tmit->client, tmit->msg); + tmit->msg = NULL; + tmit->acks_pending++; + } +} + + +/** + * Request data from client to transmit. + * + * @param tmit Transmission handle. + */ +static void +transmit_data (struct GNUNET_PSYC_TransmitHandle *tmit) +{ + int notify_ret = GNUNET_YES; + uint16_t data_size = 0; + char data[GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD] = ""; + struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) data; + msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA); + + if (NULL != tmit->notify_data) + { + data_size = GNUNET_PSYC_DATA_MAX_PAYLOAD; + tmit->in_notify = GNUNET_YES; + notify_ret = tmit->notify_data (tmit->notify_data_cls, &data_size, &msg[1]); + tmit->in_notify = GNUNET_NO; + } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "transmit_data (ret: %d, size: %u): %.*s\n", + notify_ret, data_size, data_size, &msg[1]); + switch (notify_ret) + { + case GNUNET_NO: + if (0 == data_size) + { + /* Transmission paused, nothing to send. */ + tmit->paused = GNUNET_YES; + return; + } + break; + + case GNUNET_YES: + tmit->state = GNUNET_PSYC_MESSAGE_STATE_END; + break; + + default: + LOG (GNUNET_ERROR_TYPE_ERROR, + "TransmitNotifyData callback returned error when requesting data.\n"); + + tmit->state = GNUNET_PSYC_MESSAGE_STATE_CANCEL; + msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL); + msg->size = htons (sizeof (*msg)); + transmit_queue_insert (tmit, msg, GNUNET_YES); + tmit->in_transmit = GNUNET_NO; + return; + } + + if (0 < data_size) + { + GNUNET_assert (data_size <= GNUNET_PSYC_DATA_MAX_PAYLOAD); + msg->size = htons (sizeof (*msg) + data_size); + transmit_queue_insert (tmit, msg, !notify_ret); + } + + /* End of message. */ + if (GNUNET_YES == notify_ret) + { + msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END); + msg->size = htons (sizeof (*msg)); + transmit_queue_insert (tmit, msg, GNUNET_YES); + /* FIXME: wait for ACK before setting in_transmit to no */ + tmit->in_transmit = GNUNET_NO; + } +} + + +/** + * Request a modifier from a client to transmit. + * + * @param tmit Transmission handle. + */ +static void +transmit_mod (struct GNUNET_PSYC_TransmitHandle *tmit) +{ + uint16_t max_data_size = 0; + uint16_t data_size = 0; + char data[GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD] = ""; + struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) data; + int notify_ret = GNUNET_YES; + + switch (tmit->state) + { + case GNUNET_PSYC_MESSAGE_STATE_MODIFIER: + { + struct GNUNET_PSYC_MessageModifier *mod + = (struct GNUNET_PSYC_MessageModifier *) msg; + msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER); + msg->size = sizeof (struct GNUNET_PSYC_MessageModifier); + + if (NULL != tmit->notify_mod) + { + max_data_size = GNUNET_PSYC_MODIFIER_MAX_PAYLOAD; + data_size = max_data_size; + tmit->in_notify = GNUNET_YES; + notify_ret = tmit->notify_mod (tmit->notify_mod_cls, &data_size, &mod[1], + &mod->oper, &mod->value_size); + tmit->in_notify = GNUNET_NO; + } + + mod->name_size = strnlen ((char *) &mod[1], data_size) + 1; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "transmit_mod (ret: %d, size: %u + %u): %.*s\n", + notify_ret, mod->name_size, mod->value_size, data_size, &mod[1]); + if (mod->name_size < data_size) + { + tmit->mod_value_remaining + = mod->value_size - (data_size - mod->name_size); + mod->value_size = htonl (mod->value_size); + mod->name_size = htons (mod->name_size); + } + else if (0 < data_size) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got invalid modifier name.\n"); + notify_ret = GNUNET_SYSERR; + } + break; + } + case GNUNET_PSYC_MESSAGE_STATE_MOD_CONT: + { + msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT); + msg->size = sizeof (struct GNUNET_MessageHeader); + + if (NULL != tmit->notify_mod) + { + max_data_size = GNUNET_PSYC_MOD_CONT_MAX_PAYLOAD; + data_size = max_data_size; + tmit->in_notify = GNUNET_YES; + notify_ret = tmit->notify_mod (tmit->notify_mod_cls, + &data_size, &msg[1], NULL, NULL); + tmit->in_notify = GNUNET_NO; + } + tmit->mod_value_remaining -= data_size; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "transmit_mod (ret: %d, size: %u): %.*s\n", + notify_ret, data_size, data_size, &msg[1]); + break; + } + default: + GNUNET_assert (0); + } + + switch (notify_ret) + { + case GNUNET_NO: + if (0 == data_size) + { /* Transmission paused, nothing to send. */ + tmit->paused = GNUNET_YES; + return; + } + tmit->state + = (0 == tmit->mod_value_remaining) + ? GNUNET_PSYC_MESSAGE_STATE_MODIFIER + : GNUNET_PSYC_MESSAGE_STATE_MOD_CONT; + break; + + case GNUNET_YES: /* End of modifiers. */ + GNUNET_assert (0 == tmit->mod_value_remaining); + break; + + default: + LOG (GNUNET_ERROR_TYPE_ERROR, + "TransmitNotifyModifier callback returned with error.\n"); + + tmit->state = GNUNET_PSYC_MESSAGE_STATE_CANCEL; + msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL); + msg->size = htons (sizeof (*msg)); + transmit_queue_insert (tmit, msg, GNUNET_YES); + tmit->in_transmit = GNUNET_NO; + return; + } + + if (0 < data_size) + { + GNUNET_assert (data_size <= max_data_size); + msg->size = htons (msg->size + data_size); + transmit_queue_insert (tmit, msg, GNUNET_NO); + } + + if (GNUNET_YES == notify_ret) + { + tmit->state = GNUNET_PSYC_MESSAGE_STATE_DATA; + if (0 == tmit->acks_pending) + transmit_data (tmit); + } + else + { + transmit_mod (tmit); + } +} + + +int +transmit_notify_env (void *cls, uint16_t *data_size, void *data, uint8_t *oper, + uint32_t *full_value_size) + +{ + struct GNUNET_PSYC_TransmitHandle *tmit = cls; + uint16_t name_size = 0; + uint32_t value_size = 0; + const char *value = NULL; + + if (NULL != oper) + { /* New modifier */ + if (NULL != tmit->mod) + tmit->mod = tmit->mod->next; + if (NULL == tmit->mod) + { /* No more modifiers, continue with data */ + *data_size = 0; + return GNUNET_YES; + } + + GNUNET_assert (tmit->mod->value_size < UINT32_MAX); + *full_value_size = tmit->mod->value_size; + *oper = tmit->mod->oper; + name_size = strlen (tmit->mod->name) + 1; + + if (name_size + tmit->mod->value_size <= *data_size) + { + value_size = tmit->mod->value_size; + *data_size = name_size + value_size; + } + else /* full modifier does not fit in data, continuation needed */ + { + value_size = *data_size - name_size; + tmit->mod_value = tmit->mod->value + value_size; + } + + memcpy (data, tmit->mod->name, name_size); + memcpy ((char *)data + name_size, tmit->mod->value, value_size); + return GNUNET_NO; + } + else + { /* Modifier continuation */ + GNUNET_assert (NULL != tmit->mod_value && 0 < tmit->mod_value_remaining); + value = tmit->mod_value; + if (tmit->mod_value_remaining <= *data_size) + { + value_size = tmit->mod_value_remaining; + tmit->mod_value = NULL; + } + else + { + value_size = *data_size; + tmit->mod_value += value_size; + } + + if (*data_size < value_size) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Value in environment larger than buffer: %u < %zu\n", + *data_size, value_size); + *data_size = 0; + return GNUNET_NO; + } + + *data_size = value_size; + memcpy (data, value, value_size); + return (NULL == tmit->mod_value) ? GNUNET_YES : GNUNET_NO; + } +} + + +/** + * Transmit a message. + * + * @param tmit + * Transmission handle. + * @param method_name + * Which method should be invoked. + * @param env + * Environment for the message. + * Should stay available until the first call to notify_data. + * Can be NULL if there are no modifiers or @a notify_mod is + * provided instead. + * @param notify_mod + * Function to call to obtain modifiers. + * Can be NULL if there are no modifiers or @a env is provided instead. + * @param notify_data + * Function to call to obtain fragments of the data. + * @param notify_cls + * Closure for @a notify_mod and @a notify_data. + * @param flags + * Flags for the message being transmitted. + * + * @return #GNUNET_OK if the transmission was started. + * #GNUNET_SYSERR if another transmission is already going on. + */ +int +GNUNET_PSYC_transmit_message (struct GNUNET_PSYC_TransmitHandle *tmit, + const char *method_name, + const struct GNUNET_PSYC_Environment *env, + GNUNET_PSYC_TransmitNotifyModifier notify_mod, + GNUNET_PSYC_TransmitNotifyData notify_data, + void *notify_cls, + uint32_t flags) +{ + if (GNUNET_NO != tmit->in_transmit) + return GNUNET_SYSERR; + tmit->in_transmit = GNUNET_YES; + + size_t size = strlen (method_name) + 1; + struct GNUNET_PSYC_MessageMethod *pmeth; + tmit->msg = GNUNET_malloc (sizeof (*tmit->msg) + sizeof (*pmeth) + size); + tmit->msg->size = sizeof (*tmit->msg) + sizeof (*pmeth) + size; + + if (NULL != notify_mod) + { + tmit->notify_mod = notify_mod; + tmit->notify_mod_cls = notify_cls; + } + else + { + tmit->notify_mod = &transmit_notify_env; + tmit->notify_mod_cls = tmit; + if (NULL != env) + { + struct GNUNET_PSYC_Modifier mod = {}; + mod.next = GNUNET_PSYC_env_head (env); + tmit->mod = &mod; + + struct GNUNET_PSYC_Modifier *m = tmit->mod; + while (NULL != (m = m->next)) + { + if (m->oper != GNUNET_PSYC_OP_SET) + flags |= GNUNET_PSYC_MASTER_TRANSMIT_STATE_MODIFY; + } + } + else + { + tmit->mod = NULL; + } + } + + pmeth = (struct GNUNET_PSYC_MessageMethod *) &tmit->msg[1]; + pmeth->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD); + pmeth->header.size = htons (sizeof (*pmeth) + size); + pmeth->flags = htonl (flags); + memcpy (&pmeth[1], method_name, size); + + tmit->state = GNUNET_PSYC_MESSAGE_STATE_MODIFIER; + tmit->notify_data = notify_data; + tmit->notify_data_cls = notify_cls; + + transmit_mod (tmit); + return GNUNET_OK; +} + + +/** + * Resume transmission. + * + * @param tmit Transmission handle. + */ +void +GNUNET_PSYC_transmit_resume (struct GNUNET_PSYC_TransmitHandle *tmit) +{ + if (GNUNET_YES != tmit->in_transmit || GNUNET_NO != tmit->in_notify) + return; + + if (0 == tmit->acks_pending) + { + tmit->paused = GNUNET_NO; + transmit_data (tmit); + } +} + + +/** + * Abort transmission request. + * + * @param tmit Transmission handle. + */ +void +GNUNET_PSYC_transmit_cancel (struct GNUNET_PSYC_TransmitHandle *tmit) +{ + if (GNUNET_NO == tmit->in_transmit) + return; + + tmit->state = GNUNET_PSYC_MESSAGE_STATE_CANCEL; + tmit->in_transmit = GNUNET_NO; + tmit->paused = GNUNET_NO; + + /* FIXME */ + struct GNUNET_MessageHeader msg; + msg.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA); + msg.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL); + msg.size = htons (sizeof (msg)); + transmit_queue_insert (tmit, &msg, GNUNET_YES); +} + + +/** + * Got acknowledgement of a transmitted message part, continue transmission. + * + * @param tmit Transmission handle. + */ +void +GNUNET_PSYC_transmit_got_ack (struct GNUNET_PSYC_TransmitHandle *tmit) +{ + if (0 == tmit->acks_pending) + { + LOG (GNUNET_ERROR_TYPE_WARNING, "Ignoring extraneous message ACK\n"); + GNUNET_break (0); + return; + } + tmit->acks_pending--; + + switch (tmit->state) + { + case GNUNET_PSYC_MESSAGE_STATE_MODIFIER: + case GNUNET_PSYC_MESSAGE_STATE_MOD_CONT: + transmit_mod (tmit); + break; + + case GNUNET_PSYC_MESSAGE_STATE_DATA: + transmit_data (tmit); + break; + + case GNUNET_PSYC_MESSAGE_STATE_END: + case GNUNET_PSYC_MESSAGE_STATE_CANCEL: + break; + + default: + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Ignoring message ACK in state %u.\n", tmit->state); + } +} + + +/**** Receiving messages ****/ + + +/** + * Create handle for receiving messages. + */ +struct GNUNET_PSYC_ReceiveHandle * +GNUNET_PSYC_receive_create (GNUNET_PSYC_MessageCallback message_cb, + GNUNET_PSYC_MessagePartCallback message_part_cb, + void *cb_cls) +{ + struct GNUNET_PSYC_ReceiveHandle *recv = GNUNET_malloc (sizeof (*recv)); + recv->message_cb = message_cb; + recv->message_part_cb = message_part_cb; + recv->cb_cls = cb_cls; + return recv; +} + + +/** + * Destroy handle for receiving messages. + */ +void +GNUNET_PSYC_receive_destroy (struct GNUNET_PSYC_ReceiveHandle *recv) +{ + GNUNET_free (recv); +} + + +/** + * Reset stored data related to the last received message. + */ +void +GNUNET_PSYC_receive_reset (struct GNUNET_PSYC_ReceiveHandle *recv) +{ + recv->state = GNUNET_PSYC_MESSAGE_STATE_START; + recv->flags = 0; + recv->message_id = 0; + recv->mod_value_size = 0; + recv->mod_value_size_expected = 0; +} + + +static void +recv_error (struct GNUNET_PSYC_ReceiveHandle *recv) +{ + if (NULL != recv->message_part_cb) + recv->message_part_cb (recv->cb_cls, NULL, recv->message_id, recv->flags, + 0, NULL); + + if (NULL != recv->message_cb) + recv->message_cb (recv->cb_cls, recv->message_id, recv->flags, NULL); + + GNUNET_PSYC_receive_reset (recv); +} + + +/** + * Handle incoming PSYC message. + * + * @param recv Receive handle. + * @param msg The message. + * + * @return #GNUNET_OK on success, + * #GNUNET_SYSERR on receive error. + */ +int +GNUNET_PSYC_receive_message (struct GNUNET_PSYC_ReceiveHandle *recv, + const struct GNUNET_PSYC_MessageHeader *msg) +{ + uint16_t size = ntohs (msg->header.size); + uint32_t flags = ntohl (msg->flags); + uint64_t message_id; + + GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, + (struct GNUNET_MessageHeader *) msg); + + if (GNUNET_PSYC_MESSAGE_STATE_START == recv->state) + { + recv->message_id = GNUNET_ntohll (msg->message_id); + recv->flags = flags; + recv->slave_key = msg->slave_key; + recv->mod_value_size = 0; + recv->mod_value_size_expected = 0; + } + else if (GNUNET_ntohll (msg->message_id) != recv->message_id) + { + // FIXME + LOG (GNUNET_ERROR_TYPE_WARNING, + "Unexpected message ID. Got: %" PRIu64 ", expected: %" PRIu64 "\n", + GNUNET_ntohll (msg->message_id), recv->message_id); + GNUNET_break_op (0); + recv_error (recv); + return GNUNET_SYSERR; + } + else if (flags != recv->flags) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + "Unexpected message flags. Got: %lu, expected: %lu\n", + flags, recv->flags); + GNUNET_break_op (0); + recv_error (recv); + return GNUNET_SYSERR; + } + message_id = recv->message_id; + + uint16_t pos = 0, psize = 0, ptype, size_eq, size_min; + + for (pos = 0; sizeof (*msg) + pos < size; pos += psize) + { + const struct GNUNET_MessageHeader *pmsg + = (const struct GNUNET_MessageHeader *) ((char *) &msg[1] + pos); + psize = ntohs (pmsg->size); + ptype = ntohs (pmsg->type); + size_eq = size_min = 0; + + if (psize < sizeof (*pmsg) || sizeof (*msg) + pos + psize > size) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Dropping message of type %u with invalid size %u.\n", + ptype, psize); + recv_error (recv); + return GNUNET_SYSERR; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received message part of type %u and size %u from PSYC.\n", + ptype, psize); + GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, pmsg); + + switch (ptype) + { + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD: + size_min = sizeof (struct GNUNET_PSYC_MessageMethod); + break; + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: + size_min = sizeof (struct GNUNET_PSYC_MessageModifier); + break; + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT: + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA: + size_min = sizeof (struct GNUNET_MessageHeader); + break; + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END: + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL: + size_eq = sizeof (struct GNUNET_MessageHeader); + break; + default: + GNUNET_break_op (0); + recv_error (recv); + return GNUNET_SYSERR; + } + + if (! ((0 < size_eq && psize == size_eq) + || (0 < size_min && size_min <= psize))) + { + GNUNET_break_op (0); + recv_error (recv); + return GNUNET_SYSERR; + } + + switch (ptype) + { + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD: + { + struct GNUNET_PSYC_MessageMethod *meth + = (struct GNUNET_PSYC_MessageMethod *) pmsg; + + if (GNUNET_PSYC_MESSAGE_STATE_START != recv->state) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + "Dropping out of order message method (%u).\n", + recv->state); + /* It is normal to receive an incomplete message right after connecting, + * but should not happen later. + * FIXME: add a check for this condition. + */ + GNUNET_break_op (0); + recv_error (recv); + return GNUNET_SYSERR; + } + + if ('\0' != *((char *) meth + psize - 1)) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + "Dropping message with malformed method. " + "Message ID: %" PRIu64 "\n", recv->message_id); + GNUNET_break_op (0); + recv_error (recv); + return GNUNET_SYSERR; + } + recv->state = GNUNET_PSYC_MESSAGE_STATE_METHOD; + break; + } + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: + { + if (!(GNUNET_PSYC_MESSAGE_STATE_METHOD == recv->state + || GNUNET_PSYC_MESSAGE_STATE_MODIFIER == recv->state + || GNUNET_PSYC_MESSAGE_STATE_MOD_CONT == recv->state)) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + "Dropping out of order message modifier (%u).\n", + recv->state); + GNUNET_break_op (0); + recv_error (recv); + return GNUNET_SYSERR; + } + + struct GNUNET_PSYC_MessageModifier *mod + = (struct GNUNET_PSYC_MessageModifier *) pmsg; + + uint16_t name_size = ntohs (mod->name_size); + recv->mod_value_size_expected = ntohl (mod->value_size); + recv->mod_value_size = psize - sizeof (*mod) - name_size; + + if (psize < sizeof (*mod) + name_size + || '\0' != *((char *) &mod[1] + name_size - 1) + || recv->mod_value_size_expected < recv->mod_value_size) + { + LOG (GNUNET_ERROR_TYPE_WARNING, "Dropping malformed modifier.\n"); + GNUNET_break_op (0); + recv_error (recv); + return GNUNET_SYSERR; + } + recv->state = GNUNET_PSYC_MESSAGE_STATE_MODIFIER; + break; + } + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT: + { + recv->mod_value_size += psize - sizeof (*pmsg); + + if (!(GNUNET_PSYC_MESSAGE_STATE_MODIFIER == recv->state + || GNUNET_PSYC_MESSAGE_STATE_MOD_CONT == recv->state) + || recv->mod_value_size_expected < recv->mod_value_size) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + "Dropping out of order message modifier continuation " + "!(%u == %u || %u == %u) || %lu < %lu.\n", + GNUNET_PSYC_MESSAGE_STATE_MODIFIER, recv->state, + GNUNET_PSYC_MESSAGE_STATE_MOD_CONT, recv->state, + recv->mod_value_size_expected, recv->mod_value_size); + GNUNET_break_op (0); + recv_error (recv); + return GNUNET_SYSERR; + } + break; + } + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA: + { + if (recv->state < GNUNET_PSYC_MESSAGE_STATE_METHOD + || recv->mod_value_size_expected != recv->mod_value_size) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + "Dropping out of order message data fragment " + "(%u < %u || %lu != %lu).\n", + recv->state, GNUNET_PSYC_MESSAGE_STATE_METHOD, + recv->mod_value_size_expected, recv->mod_value_size); + + GNUNET_break_op (0); + recv_error (recv); + return GNUNET_SYSERR; + } + recv->state = GNUNET_PSYC_MESSAGE_STATE_DATA; + break; + } + } + + if (NULL != recv->message_part_cb) + recv->message_part_cb (recv->cb_cls, &recv->slave_key, + recv->message_id, recv->flags, + 0, // FIXME: data_offset + pmsg); + + switch (ptype) + { + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END: + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL: + GNUNET_PSYC_receive_reset (recv); + break; + } + } + + if (NULL != recv->message_cb) + recv->message_cb (recv->cb_cls, message_id, flags, msg); + return GNUNET_OK; +} + + +/** + * Check if @a data contains a series of valid message parts. + * + * @param data_size Size of @a data. + * @param data Data. + * @param[out] first_ptype Type of first message part. + * @param[out] last_ptype Type of last message part. + * + * @return Number of message parts found in @a data. + * or GNUNET_SYSERR if the message contains invalid parts. + */ +int +GNUNET_PSYC_receive_check_parts (uint16_t data_size, const char *data, + uint16_t *first_ptype, uint16_t *last_ptype) +{ + const struct GNUNET_MessageHeader *pmsg; + uint16_t parts = 0, ptype = 0, psize = 0, pos = 0; + if (NULL != first_ptype) + *first_ptype = 0; + if (NULL != last_ptype) + *last_ptype = 0; + + for (pos = 0; pos < data_size; pos += psize, parts++) + { + pmsg = (const struct GNUNET_MessageHeader *) (data + pos); + GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, pmsg); + psize = ntohs (pmsg->size); + ptype = ntohs (pmsg->type); + if (0 == parts && NULL != first_ptype) + *first_ptype = ptype; + if (NULL != last_ptype + && *last_ptype < GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END) + *last_ptype = ptype; + if (psize < sizeof (*pmsg) + || pos + psize > data_size + || ptype < GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD + || GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL < ptype) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Invalid message part of type %u and size %u.\n", + ptype, psize); + return GNUNET_SYSERR; + } + /** @todo FIXME: check message part order */ + } + return parts; +} + + +struct ParseMessageClosure +{ + struct GNUNET_PSYC_Environment *env; + const char **method_name; + const void **data; + uint16_t *data_size; + enum GNUNET_PSYC_MessageState msg_state; +}; + + +static void +parse_message_part_cb (void *cls, + const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key, + uint64_t message_id, uint32_t flags, uint64_t data_offset, + const struct GNUNET_MessageHeader *msg) +{ + struct ParseMessageClosure *pmc = cls; + if (NULL == msg) + { + pmc->msg_state = GNUNET_PSYC_MESSAGE_STATE_ERROR; + return; + } + + switch (ntohs (msg->type)) + { + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD: + { + struct GNUNET_PSYC_MessageMethod * + pmeth = (struct GNUNET_PSYC_MessageMethod *) msg; + *pmc->method_name = (const char *) &pmeth[1]; + pmc->msg_state = GNUNET_PSYC_MESSAGE_STATE_METHOD; + break; + } + + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: + { + struct GNUNET_PSYC_MessageModifier * + pmod = (struct GNUNET_PSYC_MessageModifier *) msg; + + const char *name = (const char *) &pmod[1]; + const void *value = name + ntohs (pmod->name_size); + GNUNET_PSYC_env_add (pmc->env, pmod->oper, name, value, + ntohl (pmod->value_size)); + pmc->msg_state = GNUNET_PSYC_MESSAGE_STATE_MODIFIER; + break; + } + + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA: + *pmc->data = &msg[1]; + *pmc->data_size = ntohs (msg->size) - sizeof (*msg); + pmc->msg_state = GNUNET_PSYC_MESSAGE_STATE_DATA; + break; + + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END: + pmc->msg_state = GNUNET_PSYC_MESSAGE_STATE_END; + break; + + default: + pmc->msg_state = GNUNET_PSYC_MESSAGE_STATE_ERROR; + } +} + + +/** + * Parse PSYC message. + * + * @param msg + * The PSYC message to parse. + * @param[out] method_name + * Pointer to the method name inside @a pmsg. + * @param env + * The environment for the message with a list of modifiers. + * @param[out] data + * Pointer to data inside @a pmsg. + * @param[out] data_size + * Size of @data is written here. + * + * @return #GNUNET_OK on success, + * #GNUNET_SYSERR on parse error. + */ +int +GNUNET_PSYC_message_parse (const struct GNUNET_PSYC_MessageHeader *msg, + const char **method_name, + struct GNUNET_PSYC_Environment *env, + const void **data, + uint16_t *data_size) +{ + struct ParseMessageClosure cls; + cls.env = env; + cls.method_name = method_name; + cls.data = data; + cls.data_size = data_size; + + struct GNUNET_PSYC_ReceiveHandle * + recv = GNUNET_PSYC_receive_create (NULL, parse_message_part_cb, &cls); + int ret = GNUNET_PSYC_receive_message (recv, msg); + GNUNET_PSYC_receive_destroy (recv); + + if (GNUNET_OK != ret) + return GNUNET_SYSERR; + + return (GNUNET_PSYC_MESSAGE_STATE_END == cls.msg_state) + ? GNUNET_OK + : GNUNET_NO; +} + + +/** + * Initialize PSYC message header. + */ +void +GNUNET_PSYC_message_header_init (struct GNUNET_PSYC_MessageHeader *pmsg, + const struct GNUNET_MULTICAST_MessageHeader *mmsg, + uint32_t flags) +{ + uint16_t size = ntohs (mmsg->header.size); + uint16_t psize = sizeof (*pmsg) + size - sizeof (*mmsg); + + pmsg->header.size = htons (psize); + pmsg->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE); + pmsg->message_id = mmsg->message_id; + pmsg->fragment_offset = mmsg->fragment_offset; + pmsg->flags = htonl (flags); + + memcpy (&pmsg[1], &mmsg[1], size - sizeof (*mmsg)); +} + + +/** + * Create a new PSYC message header from a multicast message. + */ +struct GNUNET_PSYC_MessageHeader * +GNUNET_PSYC_message_header_create (const struct GNUNET_MULTICAST_MessageHeader *mmsg, + uint32_t flags) +{ + struct GNUNET_PSYC_MessageHeader *pmsg; + uint16_t size = ntohs (mmsg->header.size); + uint16_t psize = sizeof (*pmsg) + size - sizeof (*mmsg); + + pmsg = GNUNET_malloc (psize); + GNUNET_PSYC_message_header_init (pmsg, mmsg, flags); + return pmsg; +} + + +/** + * Create a new PSYC message header from a PSYC message. + */ +struct GNUNET_PSYC_MessageHeader * +GNUNET_PSYC_message_header_create_from_psyc (const struct GNUNET_PSYC_Message *msg) +{ + uint16_t msg_size = ntohs (msg->header.size); + struct GNUNET_PSYC_MessageHeader * + pmsg = GNUNET_malloc (sizeof (*pmsg) + msg_size - sizeof (*msg)); + pmsg->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE); + pmsg->header.size = htons (sizeof (*pmsg) + msg_size - sizeof (*msg)); + memcpy (&pmsg[1], &msg[1], msg_size - sizeof (*msg)); + return pmsg; +} diff --git a/src/psycutil/psyc_slicer.c b/src/psycutil/psyc_slicer.c @@ -0,0 +1,610 @@ +/* + * This file is part of GNUnet + * Copyright (C) 2013 Christian Grothoff (and other contributing authors) + * + * 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 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. + */ + +/** + * @author Gabor X Toth + * + * @file + * PSYC Slicer API + */ + +#include <inttypes.h> + +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_psyc_util_lib.h" + +#define LOG(kind,...) GNUNET_log_from (kind, "psyc-util-slicer",__VA_ARGS__) + + +/** + * Handle for a try-and-slice instance. + */ +struct GNUNET_PSYC_Slicer +{ + /** + * Method handlers: H(method_name) -> SlicerMethodCallbacks + */ + struct GNUNET_CONTAINER_MultiHashMap *method_handlers; + + /** + * Modifier handlers: H(modifier_name) -> SlicerModifierCallbacks + */ + struct GNUNET_CONTAINER_MultiHashMap *modifier_handlers; + + /** + * Currently being processed message part. + */ + const struct GNUNET_MessageHeader *msg; + + /** + * ID of currently being received message. + */ + uint64_t message_id; + + /** + * Method name of currently being received message. + */ + char *method_name; + + /** + * Name of currently processed modifier. + */ + char *mod_name; + + /** + * Value of currently processed modifier. + */ + char *mod_value; + + /** + * Public key of the nym the current message originates from. + */ + struct GNUNET_CRYPTO_EcdsaPublicKey nym_pub_key; + + /** + * Size of @a method_name (including terminating \0). + */ + uint16_t method_name_size; + + /** + * Size of @a modifier_name (including terminating \0). + */ + uint16_t mod_name_size; + + /** + * Size of modifier value fragment. + */ + uint16_t mod_value_size; + + /** + * Full size of modifier value. + */ + uint16_t mod_full_value_size; + + /** + * Remaining bytes from the value of the current modifier. + */ + uint16_t mod_value_remaining; + + /** + * Operator of currently processed modifier. + */ + uint8_t mod_oper; +}; + + +/** + * Callbacks for a slicer method handler. + */ +struct SlicerMethodCallbacks +{ + GNUNET_PSYC_MethodCallback method_cb; + GNUNET_PSYC_ModifierCallback modifier_cb; + GNUNET_PSYC_DataCallback data_cb; + GNUNET_PSYC_EndOfMessageCallback eom_cb; + void *cls; +}; + + +struct SlicerMethodRemoveClosure +{ + struct GNUNET_PSYC_Slicer *slicer; + struct SlicerMethodCallbacks rm_cbs; +}; + + +/** + * Callbacks for a slicer method handler. + */ +struct SlicerModifierCallbacks +{ + GNUNET_PSYC_ModifierCallback modifier_cb; + void *cls; +}; + + +struct SlicerModifierRemoveClosure +{ + struct GNUNET_PSYC_Slicer *slicer; + struct SlicerModifierCallbacks rm_cbs; +}; + + +/** + * Call a method handler for an incoming message part. + */ +int +slicer_method_handler_notify (void *cls, const struct GNUNET_HashCode *key, + void *value) +{ + struct GNUNET_PSYC_Slicer *slicer = cls; + const struct GNUNET_MessageHeader *msg = slicer->msg; + struct SlicerMethodCallbacks *cbs = value; + uint16_t ptype = ntohs (msg->type); + + switch (ptype) + { + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD: + { + if (NULL == cbs->method_cb) + break; + struct GNUNET_PSYC_MessageMethod * + meth = (struct GNUNET_PSYC_MessageMethod *) msg; + cbs->method_cb (cbs->cls, meth, slicer->message_id, + ntohl (meth->flags), + &slicer->nym_pub_key, + slicer->method_name); + break; + } + + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: + { + if (NULL == cbs->modifier_cb) + break; + struct GNUNET_PSYC_MessageModifier * + mod = (struct GNUNET_PSYC_MessageModifier *) msg; + cbs->modifier_cb (cbs->cls, &mod->header, slicer->message_id, + mod->oper, (const char *) &mod[1], + (const void *) &mod[1] + ntohs (mod->name_size), + ntohs (mod->header.size) - sizeof (*mod) - ntohs (mod->name_size), + ntohs (mod->value_size)); + break; + } + + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT: + { + if (NULL == cbs->modifier_cb) + break; + cbs->modifier_cb (cbs->cls, msg, slicer->message_id, + slicer->mod_oper, slicer->mod_name, &msg[1], + ntohs (msg->size) - sizeof (*msg), + slicer->mod_full_value_size); + break; + } + + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA: + { + if (NULL == cbs->data_cb) + break; + uint64_t data_offset = 0; // FIXME + cbs->data_cb (cbs->cls, msg, slicer->message_id, + data_offset, &msg[1], ntohs (msg->size) - sizeof (*msg)); + break; + } + + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END: + if (NULL == cbs->eom_cb) + break; + cbs->eom_cb (cbs->cls, msg, slicer->message_id, GNUNET_NO); + break; + + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL: + if (NULL == cbs->eom_cb) + break; + cbs->eom_cb (cbs->cls, msg, slicer->message_id, GNUNET_YES); + break; + } + return GNUNET_YES; +} + + +/** + * Call a method handler for an incoming message part. + */ +int +slicer_modifier_handler_notify (void *cls, const struct GNUNET_HashCode *key, + void *value) +{ + struct GNUNET_PSYC_Slicer *slicer = cls; + struct SlicerModifierCallbacks *cbs = value; + + cbs->modifier_cb (cbs->cls, slicer->msg, slicer->message_id, slicer->mod_oper, + slicer->mod_name, slicer->mod_value, + slicer->mod_value_size, slicer->mod_full_value_size); + return GNUNET_YES; +} + + +/** + * Process an incoming message part and call matching handlers. + * + * @param cls + * Closure. + * @param message_id + * ID of the message. + * @param flags + * Flags for the message. + * @see enum GNUNET_PSYC_MessageFlags + * @param msg + * The message part. as it arrived from the network. + */ +void +GNUNET_PSYC_slicer_message (void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_pub_key, + uint64_t message_id, uint32_t flags, uint64_t fragment_offset, + const struct GNUNET_MessageHeader *msg) +{ + struct GNUNET_PSYC_Slicer *slicer = cls; + slicer->nym_pub_key = *slave_pub_key; + + uint16_t ptype = ntohs (msg->type); + if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == ptype) + { + struct GNUNET_PSYC_MessageMethod * + meth = (struct GNUNET_PSYC_MessageMethod *) msg; + slicer->method_name_size = ntohs (meth->header.size) - sizeof (*meth); + slicer->method_name = GNUNET_malloc (slicer->method_name_size); + memcpy (slicer->method_name, &meth[1], slicer->method_name_size); + slicer->message_id = message_id; + } + else + { + GNUNET_assert (message_id == slicer->message_id); + } + + char *nym_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (slave_pub_key); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Slicer received message of type %u and size %u, " + "with ID %" PRIu64 " and method %s from %s\n", + ptype, ntohs (msg->size), message_id, slicer->method_name, nym_str); + GNUNET_free (nym_str); + + slicer->msg = msg; + + /* try-and-slice modifier */ + + switch (ptype) + { + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: + { + struct GNUNET_PSYC_MessageModifier * + mod = (struct GNUNET_PSYC_MessageModifier *) msg; + slicer->mod_oper = mod->oper; + slicer->mod_name_size = ntohs (mod->name_size); + slicer->mod_name = GNUNET_malloc (slicer->mod_name_size); + memcpy (slicer->mod_name, &mod[1], slicer->mod_name_size); + slicer->mod_value = (char *) &mod[1] + slicer->mod_name_size; + slicer->mod_full_value_size = ntohs (mod->value_size); + slicer->mod_value_remaining = slicer->mod_full_value_size; + slicer->mod_value_size + = ntohs (mod->header.size) - sizeof (*mod) - slicer->mod_name_size; + } + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT: + if (ptype == GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT) + { + slicer->mod_value = (char *) &msg[1]; + slicer->mod_value_size = ntohs (msg->size) - sizeof (*msg); + } + slicer->mod_value_remaining -= slicer->mod_value_size; + char *name = GNUNET_malloc (slicer->mod_name_size); + memcpy (name, slicer->mod_name, slicer->mod_name_size); + do + { + struct GNUNET_HashCode key; + uint16_t name_len = strlen (name); + GNUNET_CRYPTO_hash (name, name_len, &key); + GNUNET_CONTAINER_multihashmap_get_multiple (slicer->modifier_handlers, &key, + slicer_modifier_handler_notify, + slicer); + char *p = strrchr (name, '_'); + if (NULL == p) + break; + *p = '\0'; + } while (1); + GNUNET_free (name); + } + + /* try-and-slice method */ + + char *name = GNUNET_malloc (slicer->method_name_size); + memcpy (name, slicer->method_name, slicer->method_name_size); + do + { + struct GNUNET_HashCode key; + uint16_t name_len = strlen (name); + GNUNET_CRYPTO_hash (name, name_len, &key); + GNUNET_CONTAINER_multihashmap_get_multiple (slicer->method_handlers, &key, + slicer_method_handler_notify, + slicer); + char *p = strrchr (name, '_'); + if (NULL == p) + break; + *p = '\0'; + } while (1); + GNUNET_free (name); + + if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype) + GNUNET_free (slicer->method_name); + + if (0 == slicer->mod_value_remaining && NULL != slicer->mod_name) + { + GNUNET_free (slicer->mod_name); + slicer->mod_name = NULL; + slicer->mod_name_size = 0; + slicer->mod_value_size = 0; + slicer->mod_full_value_size = 0; + slicer->mod_oper = 0; + } + + slicer->msg = NULL; +} + + +/** + * Create a try-and-slice instance. + * + * A slicer processes incoming messages and notifies callbacks about matching + * methods or modifiers encountered. + * + * @return A new try-and-slice construct. + */ +struct GNUNET_PSYC_Slicer * +GNUNET_PSYC_slicer_create (void) +{ + struct GNUNET_PSYC_Slicer *slicer = GNUNET_malloc (sizeof (*slicer)); + slicer->method_handlers = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); + slicer->modifier_handlers = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); + return slicer; +} + + +/** + * Add a method to the try-and-slice instance. + * + * The callbacks are called for messages with a matching @a method_name prefix. + * + * @param slicer + * The try-and-slice instance to extend. + * @param method_name + * Name of the given method, use empty string to match all. + * @param method_cb + * Method handler invoked upon a matching message. + * @param modifier_cb + * Modifier handler, invoked after @a method_cb + * for each modifier in the message. + * @param data_cb + * Data handler, invoked after @a modifier_cb for each data fragment. + * @param eom_cb + * Invoked upon reaching the end of a matching message. + * @param cls + * Closure for the callbacks. + */ +void +GNUNET_PSYC_slicer_method_add (struct GNUNET_PSYC_Slicer *slicer, + const char *method_name, + GNUNET_PSYC_MethodCallback method_cb, + GNUNET_PSYC_ModifierCallback modifier_cb, + GNUNET_PSYC_DataCallback data_cb, + GNUNET_PSYC_EndOfMessageCallback eom_cb, + void *cls) +{ + struct GNUNET_HashCode key; + GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key); + + struct SlicerMethodCallbacks *cbs = GNUNET_malloc (sizeof (*cbs)); + cbs->method_cb = method_cb; + cbs->modifier_cb = modifier_cb; + cbs->data_cb = data_cb; + cbs->eom_cb = eom_cb; + cbs->cls = cls; + + GNUNET_CONTAINER_multihashmap_put (slicer->method_handlers, &key, cbs, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); +} + + +int +slicer_method_remove (void *cls, const struct GNUNET_HashCode *key, void *value) +{ + struct SlicerMethodRemoveClosure *rm_cls = cls; + struct GNUNET_PSYC_Slicer *slicer = rm_cls->slicer; + struct SlicerMethodCallbacks *rm_cbs = &rm_cls->rm_cbs; + struct SlicerMethodCallbacks *cbs = value; + + if (cbs->method_cb == rm_cbs->method_cb + && cbs->modifier_cb == rm_cbs->modifier_cb + && cbs->data_cb == rm_cbs->data_cb + && cbs->eom_cb == rm_cbs->eom_cb) + { + GNUNET_CONTAINER_multihashmap_remove (slicer->method_handlers, key, cbs); + GNUNET_free (cbs); + return GNUNET_NO; + } + return GNUNET_YES; +} + + +/** + * Remove a registered method from the try-and-slice instance. + * + * Removes one matching handler registered with the given + * @a method_name and callbacks. + * + * @param slicer + * The try-and-slice instance. + * @param method_name + * Name of the method to remove. + * @param method_cb + * Method handler. + * @param modifier_cb + * Modifier handler. + * @param data_cb + * Data handler. + * @param eom_cb + * End of message handler. + * + * @return #GNUNET_OK if a method handler was removed, + * #GNUNET_NO if no handler matched the given method name and callbacks. + */ +int +GNUNET_PSYC_slicer_method_remove (struct GNUNET_PSYC_Slicer *slicer, + const char *method_name, + GNUNET_PSYC_MethodCallback method_cb, + GNUNET_PSYC_ModifierCallback modifier_cb, + GNUNET_PSYC_DataCallback data_cb, + GNUNET_PSYC_EndOfMessageCallback eom_cb) +{ + struct GNUNET_HashCode key; + GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key); + + struct SlicerMethodRemoveClosure rm_cls; + rm_cls.slicer = slicer; + struct SlicerMethodCallbacks *rm_cbs = &rm_cls.rm_cbs; + rm_cbs->method_cb = method_cb; + rm_cbs->modifier_cb = modifier_cb; + rm_cbs->data_cb = data_cb; + rm_cbs->eom_cb = eom_cb; + + return + (GNUNET_SYSERR + == GNUNET_CONTAINER_multihashmap_get_multiple (slicer->method_handlers, &key, + slicer_method_remove, + &rm_cls)) + ? GNUNET_NO + : GNUNET_OK; +} + + +/** + * Watch a place for changed objects. + * + * @param slicer + * The try-and-slice instance. + * @param object_filter + * Object prefix to match. + * @param modifier_cb + * Function to call when encountering a state modifier. + * @param cls + * Closure for callback. + */ +void +GNUNET_PSYC_slicer_modifier_add (struct GNUNET_PSYC_Slicer *slicer, + const char *object_filter, + GNUNET_PSYC_ModifierCallback modifier_cb, + void *cls) +{ + struct SlicerModifierCallbacks *cbs = GNUNET_malloc (sizeof *cbs); + cbs->modifier_cb = modifier_cb; + cbs->cls = cls; + + struct GNUNET_HashCode key; + GNUNET_CRYPTO_hash (object_filter, strlen (object_filter), &key); + GNUNET_CONTAINER_multihashmap_put (slicer->modifier_handlers, &key, cbs, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); +} + + +int +slicer_modifier_remove (void *cls, const struct GNUNET_HashCode *key, void *value) +{ + struct SlicerModifierRemoveClosure *rm_cls = cls; + struct GNUNET_PSYC_Slicer *slicer = rm_cls->slicer; + struct SlicerModifierCallbacks *rm_cbs = &rm_cls->rm_cbs; + struct SlicerModifierCallbacks *cbs = value; + + if (cbs->modifier_cb == rm_cbs->modifier_cb) + { + GNUNET_CONTAINER_multihashmap_remove (slicer->modifier_handlers, key, cbs); + GNUNET_free (cbs); + return GNUNET_NO; + } + return GNUNET_YES; +} + + +/** + * Remove a registered modifier from the try-and-slice instance. + * + * Removes one matching handler registered with the given + * @a object_filter and @a modifier_cb. + * + * @param slicer + * The try-and-slice instance. + * @param object_filter + * Object prefix to match. + * @param modifier_cb + * Function to call when encountering a state modifier changes. + */ +int +GNUNET_PSYC_slicer_modifier_remove (struct GNUNET_PSYC_Slicer *slicer, + const char *object_filter, + GNUNET_PSYC_ModifierCallback modifier_cb) +{ + struct GNUNET_HashCode key; + GNUNET_CRYPTO_hash (object_filter, strlen (object_filter), &key); + + struct SlicerModifierRemoveClosure rm_cls; + rm_cls.slicer = slicer; + struct SlicerModifierCallbacks *rm_cbs = &rm_cls.rm_cbs; + rm_cbs->modifier_cb = modifier_cb; + + return + (GNUNET_SYSERR + == GNUNET_CONTAINER_multihashmap_get_multiple (slicer->modifier_handlers, &key, + slicer_modifier_remove, + &rm_cls)) + ? GNUNET_NO + : GNUNET_OK; + } + + +int +slicer_method_free (void *cls, const struct GNUNET_HashCode *key, void *value) +{ + struct SlicerMethodCallbacks *cbs = value; + GNUNET_free (cbs); + return GNUNET_YES; +} + + +/** + * Destroy a given try-and-slice instance. + * + * @param slicer + * Slicer to destroy + */ +void +GNUNET_PSYC_slicer_destroy (struct GNUNET_PSYC_Slicer *slicer) +{ + GNUNET_CONTAINER_multihashmap_iterate (slicer->method_handlers, + slicer_method_free, NULL); + GNUNET_CONTAINER_multihashmap_destroy (slicer->method_handlers); + GNUNET_free (slicer); +} diff --git a/src/psycutil/test_psyc_env.c b/src/psycutil/test_psyc_env.c @@ -0,0 +1,96 @@ +/* + * This file is part of GNUnet. + * Copyright (C) 2013 Christian Grothoff (and other contributing authors) + * + * 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 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. + */ + +/** + * @author Gabor X Toth + * + * @file + * Tests for the environment library. + */ + +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_testing_lib.h" +#include "gnunet_psyc_util_lib.h" + +struct GNUNET_PSYC_Modifier mods[] = { + { .oper = GNUNET_PSYC_OP_SET, + .name = "_foo", .value = "foo", .value_size = 3 }, + + { .oper = GNUNET_PSYC_OP_ASSIGN, + .name = "_foo_bar", .value = "foo bar", .value_size = 7 }, + + { .oper = GNUNET_PSYC_OP_AUGMENT, + .name = "_foo_bar_baz", .value = "foo bar baz", .value_size = 11 } +}; + +struct ItCls +{ + size_t n; +}; + +int +iterator (void *cls, enum GNUNET_PSYC_Operator oper, + const char *name, const char *value, uint32_t value_size) +{ + struct ItCls *it_cls = cls; + struct GNUNET_PSYC_Modifier *m = &mods[it_cls->n++]; + + GNUNET_assert (oper == m->oper); + GNUNET_assert (value_size == m->value_size); + GNUNET_assert (0 == memcmp (name, m->name, strlen (m->name))); + GNUNET_assert (0 == memcmp (value, m->value, m->value_size)); + + return GNUNET_YES; +} + +int +main (int argc, char *argv[]) +{ + GNUNET_log_setup ("test-env", "WARNING", NULL); + + struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create (); + GNUNET_assert (NULL != env); + int i, len = 3; + + for (i = 0; i < len; i++) + { + GNUNET_PSYC_env_add (env, mods[i].oper, mods[i].name, + mods[i].value, mods[i].value_size); + } + + struct ItCls it_cls = { .n = 0 }; + GNUNET_PSYC_env_iterate (env, iterator, &it_cls); + GNUNET_assert (len == it_cls.n); + + for (i = 0; i < len; i++) + { + enum GNUNET_PSYC_Operator oper; + const char *name; + const void *value; + size_t value_size; + GNUNET_PSYC_env_shift (env, &oper, &name, &value, &value_size); + GNUNET_assert (len - i - 1 == GNUNET_PSYC_env_get_count (env)); + } + + GNUNET_PSYC_env_destroy (env); + + return 0; +} diff --git a/src/social/Makefile.am b/src/social/Makefile.am @@ -24,7 +24,7 @@ libgnunetsocial_la_SOURCES = \ social_api.c social.h libgnunetsocial_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/env/libgnunetenv.la \ + $(top_builddir)/src/psycutil/libgnunetpsycutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetsocial_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ @@ -40,9 +40,8 @@ gnunet_service_social_SOURCES = \ gnunet_service_social_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ - $(top_builddir)/src/env/libgnunetenv.la \ + $(top_builddir)/src/psycutil/libgnunetpsycutil.la \ $(top_builddir)/src/psyc/libgnunetpsyc.la \ - $(top_builddir)/src/psycstore/libgnunetpsycutil.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/gns/libgnunetgns.la \ @@ -66,8 +65,7 @@ test_social_LDADD = \ libgnunetsocial.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/env/libgnunetenv.la \ - $(top_builddir)/src/psycstore/libgnunetpsycutil.la \ + $(top_builddir)/src/psycutil/libgnunetpsycutil.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/identity/libgnunetidentity.la diff --git a/src/social/gnunet-service-social.c b/src/social/gnunet-service-social.c @@ -734,7 +734,7 @@ psyc_recv_join_dcsn (void *cls, void psyc_recv_file (struct Place *plc, const struct GNUNET_PSYC_MessageHeader *msg, uint32_t flags, uint64_t message_id, uint64_t fragment_offset, - const char *method_name, struct GNUNET_ENV_Environment *env, + const char *method_name, struct GNUNET_PSYC_Environment *env, const void *data, uint16_t data_size) { if (plc->file_message_id != message_id) @@ -794,7 +794,7 @@ psyc_recv_message (void *cls, /* process message */ /* FIXME: use slicer */ const char *method_name = NULL; - struct GNUNET_ENV_Environment *env = GNUNET_ENV_environment_create (); + struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create (); const void *data = NULL; uint16_t data_size = 0; @@ -815,7 +815,7 @@ psyc_recv_message (void *cls, } } } - GNUNET_ENV_environment_destroy (env); + GNUNET_PSYC_env_destroy (env); place_send_msg (plc, &msg->header); } diff --git a/src/social/social.h b/src/social/social.h @@ -80,6 +80,19 @@ struct AppDetachRequest }; +struct HostRelayRequest +{ + /** + * Types: + * - GNUNET_MESSAGE_TYPE_SOCIAL_HOST_RELAY_START + * - GNUNET_MESSAGE_TYPE_SOCIAL_HOST_RELAY_STOP + */ + struct GNUNET_MessageHeader header; + + /* Followed by char *method_name */ +}; + + struct HostEnterRequest { /** @@ -207,6 +220,7 @@ struct ZoneAddNymRequest /* Followed by const char *name */ }; + /**** service -> library ****/ @@ -266,24 +280,6 @@ struct HostEnterAck { }; -#if REMOVE -struct NymEnterRequest -{ - /** - * Type: GNUNET_MESSAGE_TYPE_SOCIAL_NYM_ENTER - */ - struct GNUNET_MessageHeader header; - - /** - * Public key of the joining slave. - */ - struct GNUNET_CRYPTO_EcdsaPublicKey nym_key; - - /* Followed by struct GNUNET_MessageHeader join_request */ -}; -#endif - - GNUNET_NETWORK_STRUCT_END #endif diff --git a/src/social/social_api.c b/src/social/social_api.c @@ -19,9 +19,10 @@ */ /** - * @file social/social_api.c - * @brief Social service; implements social interactions using the PSYC service. * @author Gabor X Toth + * + * @file + * Social service; implements social interactions using the PSYC service. */ #include <inttypes.h> @@ -29,7 +30,6 @@ #include "platform.h" #include "gnunet_util_lib.h" -#include "gnunet_env_lib.h" #include "gnunet_psyc_service.h" #include "gnunet_psyc_util_lib.h" #include "gnunet_social_service.h" @@ -156,7 +156,7 @@ struct GNUNET_SOCIAL_Place /** * Slicer for processing incoming methods. */ - struct GNUNET_SOCIAL_Slicer *slicer; + struct GNUNET_PSYC_Slicer *slicer; /** * Message to send on reconnect. @@ -211,7 +211,7 @@ struct GNUNET_SOCIAL_Host /** * Slicer for processing incoming methods. */ - struct GNUNET_SOCIAL_Slicer *slicer; + struct GNUNET_PSYC_Slicer *slicer; GNUNET_SOCIAL_HostEnterCallback enter_cb; @@ -225,7 +225,7 @@ struct GNUNET_SOCIAL_Host void *cb_cls; struct GNUNET_SOCIAL_Nym *notice_place_leave_nym; - struct GNUNET_ENV_Environment *notice_place_leave_env; + struct GNUNET_PSYC_Environment *notice_place_leave_env; }; @@ -244,7 +244,7 @@ struct GNUNET_SOCIAL_Guest /** * Slicer for processing incoming methods. */ - struct GNUNET_SOCIAL_Slicer *slicer; + struct GNUNET_PSYC_Slicer *slicer; GNUNET_SOCIAL_GuestEnterCallback enter_cb; @@ -265,120 +265,6 @@ struct GNUNET_CONTAINER_MultiHashMap *nyms; /** - * Handle for a try-and-slice instance. - */ -struct GNUNET_SOCIAL_Slicer -{ - /** - * Method handlers: method_name -> SlicerMethodCallbacks - */ - struct GNUNET_CONTAINER_MultiHashMap *method_handlers; - - /** - * Modifier handlers: modifier name -> SlicerModifierCallbacks - */ - struct GNUNET_CONTAINER_MultiHashMap *modifier_handlers; - - /** - * Currently being processed message part. - */ - const struct GNUNET_MessageHeader *msg; - - /** - * ID of currently being received message. - */ - uint64_t message_id; - - /** - * Method name of currently being received message. - */ - char *method_name; - - /** - * Name of currently processed modifier. - */ - char *mod_name; - - /** - * Value of currently processed modifier. - */ - char *mod_value; - - /** - * Public key of the nym the current message originates from. - */ - struct GNUNET_CRYPTO_EcdsaPublicKey nym_key; - - /** - * Size of @a method_name (including terminating \0). - */ - uint16_t method_name_size; - - /** - * Size of @a modifier_name (including terminating \0). - */ - uint16_t mod_name_size; - - /** - * Size of modifier value fragment. - */ - uint16_t mod_value_size; - - /** - * Full size of modifier value. - */ - uint16_t mod_full_value_size; - - /** - * Remaining bytes from the value of the current modifier. - */ - uint16_t mod_value_remaining; - - /** - * Operator of currently processed modifier. - */ - uint8_t mod_oper; -}; - - -/** - * Callbacks for a slicer method handler. - */ -struct SlicerMethodCallbacks -{ - GNUNET_SOCIAL_MethodCallback method_cb; - GNUNET_SOCIAL_ModifierCallback modifier_cb; - GNUNET_SOCIAL_DataCallback data_cb; - GNUNET_SOCIAL_EndOfMessageCallback eom_cb; - void *cls; -}; - - -struct SlicerMethodRemoveClosure -{ - struct GNUNET_SOCIAL_Slicer *slicer; - struct SlicerMethodCallbacks rm_cbs; -}; - - -/** - * Callbacks for a slicer method handler. - */ -struct SlicerModifierCallbacks -{ - GNUNET_SOCIAL_ModifierCallback modifier_cb; - void *cls; -}; - - -struct SlicerModifierRemoveClosure -{ - struct GNUNET_SOCIAL_Slicer *slicer; - struct SlicerModifierCallbacks rm_cbs; -}; - - -/** * Handle for an announcement request. */ struct GNUNET_SOCIAL_Announcement @@ -535,20 +421,23 @@ host_recv_notice_place_leave_method (void *cls, const struct GNUNET_PSYC_MessageMethod *meth, uint64_t message_id, uint32_t flags, - const struct GNUNET_SOCIAL_Nym *nym, + const struct GNUNET_CRYPTO_EcdsaPublicKey *nym_pub_key, const char *method_name) { struct GNUNET_SOCIAL_Host *hst = cls; + if (0 == memcmp (&(struct GNUNET_CRYPTO_EcdsaPublicKey) {}, - &nym->pub_key, sizeof (nym->pub_key))) + nym_pub_key, sizeof (*nym_pub_key))) return; + struct GNUNET_SOCIAL_Nym *nym = nym_get_or_create (nym_pub_key); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Host received method for message ID %" PRIu64 " from nym %s: %s\n", message_id, GNUNET_h2s (&nym->pub_key_hash), method_name); hst->notice_place_leave_nym = (struct GNUNET_SOCIAL_Nym *) nym; - hst->notice_place_leave_env = GNUNET_ENV_environment_create (); + hst->notice_place_leave_env = GNUNET_PSYC_env_create (); char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&hst->notice_place_leave_nym->pub_key); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -561,7 +450,7 @@ static void host_recv_notice_place_leave_modifier (void *cls, const struct GNUNET_MessageHeader *msg, uint64_t message_id, - enum GNUNET_ENV_Operator oper, + enum GNUNET_PSYC_Operator oper, const char *name, const void *value, uint16_t value_size, @@ -581,8 +470,8 @@ host_recv_notice_place_leave_modifier (void *cls, || 0 == memcmp (name, "_nym_", sizeof ("_nym_") - 1)) return; - GNUNET_ENV_environment_add (hst->notice_place_leave_env, - GNUNET_ENV_OP_SET, name, value, value_size); + GNUNET_PSYC_env_add (hst->notice_place_leave_env, + GNUNET_PSYC_OP_SET, name, value, value_size); } @@ -607,482 +496,19 @@ host_recv_notice_place_leave_eom (void *cls, hst->farewell_cb (hst->cb_cls, hst->notice_place_leave_nym, hst->notice_place_leave_env); /* announce leaving guest to place */ - GNUNET_ENV_environment_add (hst->notice_place_leave_env, GNUNET_ENV_OP_SET, - "_nym", hst->notice_place_leave_nym, - sizeof (*hst->notice_place_leave_nym)); + GNUNET_PSYC_env_add (hst->notice_place_leave_env, GNUNET_PSYC_OP_SET, + "_nym", hst->notice_place_leave_nym, + sizeof (*hst->notice_place_leave_nym)); GNUNET_SOCIAL_host_announce (hst, "_notice_place_leave", hst->notice_place_leave_env, NULL, NULL, GNUNET_SOCIAL_ANNOUNCE_NONE); nym_destroy (hst->notice_place_leave_nym); } - GNUNET_ENV_environment_destroy (hst->notice_place_leave_env); + GNUNET_PSYC_env_destroy (hst->notice_place_leave_env); hst->notice_place_leave_env = NULL; } -/*** SLICER ***/ - -/** - * Call a method handler for an incoming message part. - */ -int -slicer_method_handler_notify (void *cls, const struct GNUNET_HashCode *key, - void *value) -{ - struct GNUNET_SOCIAL_Slicer *slicer = cls; - const struct GNUNET_MessageHeader *msg = slicer->msg; - struct SlicerMethodCallbacks *cbs = value; - uint16_t ptype = ntohs (msg->type); - - switch (ptype) - { - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD: - { - if (NULL == cbs->method_cb) - break; - struct GNUNET_PSYC_MessageMethod * - meth = (struct GNUNET_PSYC_MessageMethod *) msg; - cbs->method_cb (cbs->cls, meth, slicer->message_id, - ntohl (meth->flags), - nym_get_or_create (&slicer->nym_key), - slicer->method_name); - break; - } - - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: - { - if (NULL == cbs->modifier_cb) - break; - struct GNUNET_PSYC_MessageModifier * - mod = (struct GNUNET_PSYC_MessageModifier *) msg; - cbs->modifier_cb (cbs->cls, &mod->header, slicer->message_id, - mod->oper, (const char *) &mod[1], - (const void *) &mod[1] + ntohs (mod->name_size), - ntohs (mod->header.size) - sizeof (*mod) - ntohs (mod->name_size), - ntohs (mod->value_size)); - break; - } - - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT: - { - if (NULL == cbs->modifier_cb) - break; - cbs->modifier_cb (cbs->cls, msg, slicer->message_id, - slicer->mod_oper, slicer->mod_name, &msg[1], - ntohs (msg->size) - sizeof (*msg), - slicer->mod_full_value_size); - break; - } - - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA: - { - if (NULL == cbs->data_cb) - break; - uint64_t data_offset = 0; // FIXME - cbs->data_cb (cbs->cls, msg, slicer->message_id, - data_offset, &msg[1], ntohs (msg->size) - sizeof (*msg)); - break; - } - - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END: - if (NULL == cbs->eom_cb) - break; - cbs->eom_cb (cbs->cls, msg, slicer->message_id, GNUNET_NO); - break; - - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL: - if (NULL == cbs->eom_cb) - break; - cbs->eom_cb (cbs->cls, msg, slicer->message_id, GNUNET_YES); - break; - } - return GNUNET_YES; -} - - -/** - * Call a method handler for an incoming message part. - */ -int -slicer_modifier_handler_notify (void *cls, const struct GNUNET_HashCode *key, - void *value) -{ - struct GNUNET_SOCIAL_Slicer *slicer = cls; - struct SlicerModifierCallbacks *cbs = value; - - cbs->modifier_cb (cbs->cls, slicer->msg, slicer->message_id, slicer->mod_oper, - slicer->mod_name, slicer->mod_value, - slicer->mod_value_size, slicer->mod_full_value_size); - return GNUNET_YES; -} - - -/** - * Process an incoming message part and call matching handlers. - * - * @param cls - * Closure. - * @param message_id - * ID of the message. - * @param flags - * Flags for the message. - * @see enum GNUNET_PSYC_MessageFlags - * @param msg - * The message part. as it arrived from the network. - */ -static void -slicer_message (void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key, - uint64_t message_id, uint32_t flags, uint64_t fragment_offset, - const struct GNUNET_MessageHeader *msg) -{ - struct GNUNET_SOCIAL_Slicer *slicer = cls; - slicer->nym_key = *slave_key; - - uint16_t ptype = ntohs (msg->type); - if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == ptype) - { - struct GNUNET_PSYC_MessageMethod * - meth = (struct GNUNET_PSYC_MessageMethod *) msg; - slicer->method_name_size = ntohs (meth->header.size) - sizeof (*meth); - slicer->method_name = GNUNET_malloc (slicer->method_name_size); - memcpy (slicer->method_name, &meth[1], slicer->method_name_size); - slicer->message_id = message_id; - } - else - { - GNUNET_assert (message_id == slicer->message_id); - } - - char *nym_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (slave_key); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Slicer received message of type %u and size %u, " - "with ID %" PRIu64 " and method %s from %s\n", - ptype, ntohs (msg->size), message_id, slicer->method_name, nym_str); - GNUNET_free (nym_str); - - slicer->msg = msg; - - /* try-and-slice modifier */ - - switch (ptype) - { - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: - { - struct GNUNET_PSYC_MessageModifier * - mod = (struct GNUNET_PSYC_MessageModifier *) msg; - slicer->mod_oper = mod->oper; - slicer->mod_name_size = ntohs (mod->name_size); - slicer->mod_name = GNUNET_malloc (slicer->mod_name_size); - memcpy (slicer->mod_name, &mod[1], slicer->mod_name_size); - slicer->mod_value = (char *) &mod[1] + slicer->mod_name_size; - slicer->mod_full_value_size = ntohs (mod->value_size); - slicer->mod_value_remaining = slicer->mod_full_value_size; - slicer->mod_value_size - = ntohs (mod->header.size) - sizeof (*mod) - slicer->mod_name_size; - } - case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT: - if (ptype == GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT) - { - slicer->mod_value = (char *) &msg[1]; - slicer->mod_value_size = ntohs (msg->size) - sizeof (*msg); - } - slicer->mod_value_remaining -= slicer->mod_value_size; - char *name = GNUNET_malloc (slicer->mod_name_size); - memcpy (name, slicer->mod_name, slicer->mod_name_size); - do - { - struct GNUNET_HashCode key; - uint16_t name_len = strlen (name); - GNUNET_CRYPTO_hash (name, name_len, &key); - GNUNET_CONTAINER_multihashmap_get_multiple (slicer->modifier_handlers, &key, - slicer_modifier_handler_notify, - slicer); - char *p = strrchr (name, '_'); - if (NULL == p) - break; - *p = '\0'; - } while (1); - GNUNET_free (name); - } - - /* try-and-slice method */ - - char *name = GNUNET_malloc (slicer->method_name_size); - memcpy (name, slicer->method_name, slicer->method_name_size); - do - { - struct GNUNET_HashCode key; - uint16_t name_len = strlen (name); - GNUNET_CRYPTO_hash (name, name_len, &key); - GNUNET_CONTAINER_multihashmap_get_multiple (slicer->method_handlers, &key, - slicer_method_handler_notify, - slicer); - char *p = strrchr (name, '_'); - if (NULL == p) - break; - *p = '\0'; - } while (1); - GNUNET_free (name); - - if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype) - GNUNET_free (slicer->method_name); - - if (0 == slicer->mod_value_remaining && NULL != slicer->mod_name) - { - GNUNET_free (slicer->mod_name); - slicer->mod_name = NULL; - slicer->mod_name_size = 0; - slicer->mod_value_size = 0; - slicer->mod_full_value_size = 0; - slicer->mod_oper = 0; - } - - slicer->msg = NULL; -} - - -/** - * Create a try-and-slice instance. - * - * A slicer processes incoming messages and notifies callbacks about matching - * methods or modifiers encountered. - * - * @return A new try-and-slice construct. - */ -struct GNUNET_SOCIAL_Slicer * -GNUNET_SOCIAL_slicer_create (void) -{ - struct GNUNET_SOCIAL_Slicer *slicer = GNUNET_malloc (sizeof (*slicer)); - slicer->method_handlers = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); - slicer->modifier_handlers = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); - return slicer; -} - - -/** - * Add a method to the try-and-slice instance. - * - * The callbacks are called for messages with a matching @a method_name prefix. - * - * @param slicer - * The try-and-slice instance to extend. - * @param method_name - * Name of the given method, use empty string to match all. - * @param method_cb - * Method handler invoked upon a matching message. - * @param modifier_cb - * Modifier handler, invoked after @a method_cb - * for each modifier in the message. - * @param data_cb - * Data handler, invoked after @a modifier_cb for each data fragment. - * @param eom_cb - * Invoked upon reaching the end of a matching message. - * @param cls - * Closure for the callbacks. - */ -void -GNUNET_SOCIAL_slicer_method_add (struct GNUNET_SOCIAL_Slicer *slicer, - const char *method_name, - GNUNET_SOCIAL_MethodCallback method_cb, - GNUNET_SOCIAL_ModifierCallback modifier_cb, - GNUNET_SOCIAL_DataCallback data_cb, - GNUNET_SOCIAL_EndOfMessageCallback eom_cb, - void *cls) -{ - struct GNUNET_HashCode key; - GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key); - - struct SlicerMethodCallbacks *cbs = GNUNET_malloc (sizeof (*cbs)); - cbs->method_cb = method_cb; - cbs->modifier_cb = modifier_cb; - cbs->data_cb = data_cb; - cbs->eom_cb = eom_cb; - cbs->cls = cls; - - GNUNET_CONTAINER_multihashmap_put (slicer->method_handlers, &key, cbs, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); -} - - -int -slicer_method_remove (void *cls, const struct GNUNET_HashCode *key, void *value) -{ - struct SlicerMethodRemoveClosure *rm_cls = cls; - struct GNUNET_SOCIAL_Slicer *slicer = rm_cls->slicer; - struct SlicerMethodCallbacks *rm_cbs = &rm_cls->rm_cbs; - struct SlicerMethodCallbacks *cbs = value; - - if (cbs->method_cb == rm_cbs->method_cb - && cbs->modifier_cb == rm_cbs->modifier_cb - && cbs->data_cb == rm_cbs->data_cb - && cbs->eom_cb == rm_cbs->eom_cb) - { - GNUNET_CONTAINER_multihashmap_remove (slicer->method_handlers, key, cbs); - GNUNET_free (cbs); - return GNUNET_NO; - } - return GNUNET_YES; -} - - -/** - * Remove a registered method from the try-and-slice instance. - * - * Removes one matching handler registered with the given - * @a method_name and callbacks. - * - * @param slicer - * The try-and-slice instance. - * @param method_name - * Name of the method to remove. - * @param method_cb - * Method handler. - * @param modifier_cb - * Modifier handler. - * @param data_cb - * Data handler. - * @param eom_cb - * End of message handler. - * - * @return #GNUNET_OK if a method handler was removed, - * #GNUNET_NO if no handler matched the given method name and callbacks. - */ -int -GNUNET_SOCIAL_slicer_method_remove (struct GNUNET_SOCIAL_Slicer *slicer, - const char *method_name, - GNUNET_SOCIAL_MethodCallback method_cb, - GNUNET_SOCIAL_ModifierCallback modifier_cb, - GNUNET_SOCIAL_DataCallback data_cb, - GNUNET_SOCIAL_EndOfMessageCallback eom_cb) -{ - struct GNUNET_HashCode key; - GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key); - - struct SlicerMethodRemoveClosure rm_cls; - rm_cls.slicer = slicer; - struct SlicerMethodCallbacks *rm_cbs = &rm_cls.rm_cbs; - rm_cbs->method_cb = method_cb; - rm_cbs->modifier_cb = modifier_cb; - rm_cbs->data_cb = data_cb; - rm_cbs->eom_cb = eom_cb; - - return - (GNUNET_SYSERR - == GNUNET_CONTAINER_multihashmap_get_multiple (slicer->method_handlers, &key, - slicer_method_remove, - &rm_cls)) - ? GNUNET_NO - : GNUNET_OK; -} - - -/** - * Watch a place for changed objects. - * - * @param slicer - * The try-and-slice instance. - * @param object_filter - * Object prefix to match. - * @param modifier_cb - * Function to call when encountering a state modifier. - * @param cls - * Closure for callback. - */ -void -GNUNET_SOCIAL_slicer_modifier_add (struct GNUNET_SOCIAL_Slicer *slicer, - const char *object_filter, - GNUNET_SOCIAL_ModifierCallback modifier_cb, - void *cls) -{ - struct SlicerModifierCallbacks *cbs = GNUNET_malloc (sizeof *cbs); - cbs->modifier_cb = modifier_cb; - cbs->cls = cls; - - struct GNUNET_HashCode key; - GNUNET_CRYPTO_hash (object_filter, strlen (object_filter), &key); - GNUNET_CONTAINER_multihashmap_put (slicer->modifier_handlers, &key, cbs, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); -} - - -int -slicer_modifier_remove (void *cls, const struct GNUNET_HashCode *key, void *value) -{ - struct SlicerModifierRemoveClosure *rm_cls = cls; - struct GNUNET_SOCIAL_Slicer *slicer = rm_cls->slicer; - struct SlicerModifierCallbacks *rm_cbs = &rm_cls->rm_cbs; - struct SlicerModifierCallbacks *cbs = value; - - if (cbs->modifier_cb == rm_cbs->modifier_cb) - { - GNUNET_CONTAINER_multihashmap_remove (slicer->modifier_handlers, key, cbs); - GNUNET_free (cbs); - return GNUNET_NO; - } - return GNUNET_YES; -} - - -/** - * Remove a registered modifier from the try-and-slice instance. - * - * Removes one matching handler registered with the given - * @a object_filter and @a modifier_cb. - * - * @param slicer - * The try-and-slice instance. - * @param object_filter - * Object prefix to match. - * @param modifier_cb - * Function to call when encountering a state modifier changes. - */ -int -GNUNET_SOCIAL_slicer_modifier_remove (struct GNUNET_SOCIAL_Slicer *slicer, - const char *object_filter, - GNUNET_SOCIAL_ModifierCallback modifier_cb) -{ - struct GNUNET_HashCode key; - GNUNET_CRYPTO_hash (object_filter, strlen (object_filter), &key); - - struct SlicerModifierRemoveClosure rm_cls; - rm_cls.slicer = slicer; - struct SlicerModifierCallbacks *rm_cbs = &rm_cls.rm_cbs; - rm_cbs->modifier_cb = modifier_cb; - - return - (GNUNET_SYSERR - == GNUNET_CONTAINER_multihashmap_get_multiple (slicer->modifier_handlers, &key, - slicer_modifier_remove, - &rm_cls)) - ? GNUNET_NO - : GNUNET_OK; - } - - -int -slicer_method_free (void *cls, const struct GNUNET_HashCode *key, void *value) -{ - struct SlicerMethodCallbacks *cbs = value; - GNUNET_free (cbs); - return GNUNET_YES; -} - - -/** - * Destroy a given try-and-slice instance. - * - * @param slicer - * Slicer to destroy - */ -void -GNUNET_SOCIAL_slicer_destroy (struct GNUNET_SOCIAL_Slicer *slicer) -{ - GNUNET_CONTAINER_multihashmap_iterate (slicer->method_handlers, - slicer_method_free, NULL); - GNUNET_CONTAINER_multihashmap_destroy (slicer->method_handlers); - GNUNET_free (slicer); -} - /*** CLIENT ***/ @@ -1405,7 +831,7 @@ host_recv_enter_request (void *cls, return; const char *method_name = NULL; - struct GNUNET_ENV_Environment *env = NULL; + struct GNUNET_PSYC_Environment *env = NULL; struct GNUNET_PSYC_MessageHeader *entry_pmsg = NULL; const void *data = NULL; uint16_t data_size = 0; @@ -1423,7 +849,7 @@ host_recv_enter_request (void *cls, "Received join_msg of type %u and size %u.\n", ntohs (join_msg->header.type), ntohs (join_msg->header.size)); - env = GNUNET_ENV_environment_create (); + env = GNUNET_PSYC_env_create (); entry_pmsg = GNUNET_PSYC_message_header_create_from_psyc (join_msg); if (GNUNET_OK != GNUNET_PSYC_message_parse (entry_pmsg, &method_name, env, &data, &data_size)) @@ -1444,7 +870,7 @@ host_recv_enter_request (void *cls, } while (0); if (NULL != env) - GNUNET_ENV_environment_destroy (env); + GNUNET_PSYC_env_destroy (env); if (NULL != entry_pmsg) GNUNET_free (entry_pmsg); } @@ -1693,7 +1119,7 @@ host_cleanup (void *cls) } if (NULL != hst->slicer) { - GNUNET_SOCIAL_slicer_destroy (hst->slicer); + GNUNET_PSYC_slicer_destroy (hst->slicer); hst->slicer = NULL; } GNUNET_free (hst); @@ -1743,7 +1169,7 @@ struct GNUNET_SOCIAL_Host * GNUNET_SOCIAL_host_enter (const struct GNUNET_SOCIAL_App *app, const struct GNUNET_SOCIAL_Ego *ego, enum GNUNET_PSYC_Policy policy, - struct GNUNET_SOCIAL_Slicer *slicer, + struct GNUNET_PSYC_Slicer *slicer, GNUNET_SOCIAL_HostEnterCallback enter_cb, GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb, GNUNET_SOCIAL_FarewellCallback farewell_cb, @@ -1765,14 +1191,14 @@ GNUNET_SOCIAL_host_enter (const struct GNUNET_SOCIAL_App *app, GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, hst, sizeof (*plc)); plc->tmit = GNUNET_PSYC_transmit_create (plc->client); - plc->recv = GNUNET_PSYC_receive_create (NULL, slicer_message, plc->slicer); + plc->recv = GNUNET_PSYC_receive_create (NULL, GNUNET_PSYC_slicer_message, plc->slicer); - hst->slicer = GNUNET_SOCIAL_slicer_create (); - GNUNET_SOCIAL_slicer_method_add (hst->slicer, "_notice_place_leave", - host_recv_notice_place_leave_method, - host_recv_notice_place_leave_modifier, - NULL, host_recv_notice_place_leave_eom, hst); - hst->recv = GNUNET_PSYC_receive_create (NULL, slicer_message, hst->slicer); + hst->slicer = GNUNET_PSYC_slicer_create (); + GNUNET_PSYC_slicer_method_add (hst->slicer, "_notice_place_leave", + host_recv_notice_place_leave_method, + host_recv_notice_place_leave_modifier, + NULL, host_recv_notice_place_leave_eom, hst); + hst->recv = GNUNET_PSYC_receive_create (NULL, GNUNET_PSYC_slicer_message, hst->slicer); uint16_t app_id_size = strlen (app->id) + 1; struct HostEnterRequest *hreq = GNUNET_malloc (sizeof (*hreq) + app_id_size); @@ -1810,7 +1236,7 @@ GNUNET_SOCIAL_host_enter (const struct GNUNET_SOCIAL_App *app, */ struct GNUNET_SOCIAL_Host * GNUNET_SOCIAL_host_enter_reconnect (struct GNUNET_SOCIAL_HostConnection *hconn, - struct GNUNET_SOCIAL_Slicer *slicer, + struct GNUNET_PSYC_Slicer *slicer, GNUNET_SOCIAL_HostEnterCallback enter_cb, GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb, GNUNET_SOCIAL_FarewellCallback farewell_cb, @@ -1837,14 +1263,14 @@ GNUNET_SOCIAL_host_enter_reconnect (struct GNUNET_SOCIAL_HostConnection *hconn, GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, hst, sizeof (*plc)); plc->tmit = GNUNET_PSYC_transmit_create (plc->client); - plc->recv = GNUNET_PSYC_receive_create (NULL, slicer_message, plc->slicer); + plc->recv = GNUNET_PSYC_receive_create (NULL, GNUNET_PSYC_slicer_message, plc->slicer); - hst->slicer = GNUNET_SOCIAL_slicer_create (); - GNUNET_SOCIAL_slicer_method_add (hst->slicer, "_notice_place_leave", - host_recv_notice_place_leave_method, - host_recv_notice_place_leave_modifier, - NULL, host_recv_notice_place_leave_eom, hst); - hst->recv = GNUNET_PSYC_receive_create (NULL, slicer_message, hst->slicer); + hst->slicer = GNUNET_PSYC_slicer_create (); + GNUNET_PSYC_slicer_method_add (hst->slicer, "_notice_place_leave", + host_recv_notice_place_leave_method, + host_recv_notice_place_leave_modifier, + NULL, host_recv_notice_place_leave_eom, hst); + hst->recv = GNUNET_PSYC_receive_create (NULL, GNUNET_PSYC_slicer_message, hst->slicer); hreq->header.size = htons (sizeof (*hreq) + app_id_size); hreq->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER); @@ -1926,12 +1352,12 @@ GNUNET_SOCIAL_host_entry_decision (struct GNUNET_SOCIAL_Host *hst, void GNUNET_SOCIAL_host_eject (struct GNUNET_SOCIAL_Host *hst, const struct GNUNET_SOCIAL_Nym *nym, - struct GNUNET_ENV_Environment *env) + struct GNUNET_PSYC_Environment *env) { if (NULL == env) - env = GNUNET_ENV_environment_create (); - GNUNET_ENV_environment_add (env, GNUNET_ENV_OP_SET, - "_nym", &nym->pub_key, sizeof (nym->pub_key)); + env = GNUNET_PSYC_env_create (); + GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_SET, + "_nym", &nym->pub_key, sizeof (nym->pub_key)); GNUNET_SOCIAL_host_announce (hst, "_notice_place_leave", env, NULL, NULL, GNUNET_SOCIAL_ANNOUNCE_NONE); } @@ -2033,7 +1459,7 @@ GNUNET_SOCIAL_nym_get_pub_key_hash (const struct GNUNET_SOCIAL_Nym *nym) struct GNUNET_SOCIAL_Announcement * GNUNET_SOCIAL_host_announce (struct GNUNET_SOCIAL_Host *hst, const char *method_name, - const struct GNUNET_ENV_Environment *env, + const struct GNUNET_PSYC_Environment *env, GNUNET_PSYC_TransmitNotifyData notify_data, void *notify_data_cls, enum GNUNET_SOCIAL_AnnounceFlags flags) @@ -2152,7 +1578,7 @@ GNUNET_SOCIAL_host_disconnect (struct GNUNET_SOCIAL_Host *hst, */ void GNUNET_SOCIAL_host_leave (struct GNUNET_SOCIAL_Host *hst, - const struct GNUNET_ENV_Environment *env, + const struct GNUNET_PSYC_Environment *env, GNUNET_ContinuationCallback disconnect_cb, void *cls) { @@ -2242,7 +1668,7 @@ GNUNET_SOCIAL_guest_enter (const struct GNUNET_SOCIAL_App *app, uint32_t relay_count, const struct GNUNET_PeerIdentity *relays, const struct GNUNET_PSYC_Message *entry_msg, - struct GNUNET_SOCIAL_Slicer *slicer, + struct GNUNET_PSYC_Slicer *slicer, GNUNET_SOCIAL_GuestEnterCallback local_enter_cb, GNUNET_SOCIAL_EntryDecisionCallback entry_dcsn_cb, void *cls) @@ -2264,7 +1690,7 @@ GNUNET_SOCIAL_guest_enter (const struct GNUNET_SOCIAL_App *app, GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, gst, sizeof (*plc)); plc->tmit = GNUNET_PSYC_transmit_create (plc->client); - plc->recv = GNUNET_PSYC_receive_create (NULL, slicer_message, plc->slicer); + plc->recv = GNUNET_PSYC_receive_create (NULL, GNUNET_PSYC_slicer_message, plc->slicer); struct GuestEnterRequest * greq = guest_enter_request_create (app->id, &ego->pub_key, &plc->pub_key, @@ -2307,7 +1733,7 @@ GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_SOCIAL_App *app, const char *gns_name, const char *password, const struct GNUNET_PSYC_Message *join_msg, - struct GNUNET_SOCIAL_Slicer *slicer, + struct GNUNET_PSYC_Slicer *slicer, GNUNET_SOCIAL_GuestEnterCallback local_enter_cb, GNUNET_SOCIAL_EntryDecisionCallback entry_decision_cb, void *cls) @@ -2356,7 +1782,7 @@ GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_SOCIAL_App *app, GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, gst, sizeof (*plc)); plc->tmit = GNUNET_PSYC_transmit_create (plc->client); - plc->recv = GNUNET_PSYC_receive_create (NULL, slicer_message, plc->slicer); + plc->recv = GNUNET_PSYC_receive_create (NULL, GNUNET_PSYC_slicer_message, plc->slicer); plc->connect_msg = &greq->header; place_send_connect_msg (plc); @@ -2385,7 +1811,7 @@ GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_SOCIAL_App *app, struct GNUNET_SOCIAL_Guest * GNUNET_SOCIAL_guest_enter_reconnect (struct GNUNET_SOCIAL_GuestConnection *gconn, enum GNUNET_PSYC_SlaveJoinFlags flags, - struct GNUNET_SOCIAL_Slicer *slicer, + struct GNUNET_PSYC_Slicer *slicer, GNUNET_SOCIAL_GuestEnterCallback local_enter_cb, void *cls) { @@ -2416,7 +1842,7 @@ GNUNET_SOCIAL_guest_enter_reconnect (struct GNUNET_SOCIAL_GuestConnection *gconn GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, gst, sizeof (*plc)); plc->tmit = GNUNET_PSYC_transmit_create (plc->client); - plc->recv = GNUNET_PSYC_receive_create (NULL, slicer_message, plc->slicer); + plc->recv = GNUNET_PSYC_receive_create (NULL, GNUNET_PSYC_slicer_message, plc->slicer); plc->connect_msg = &greq->header; place_send_connect_msg (plc); @@ -2448,7 +1874,7 @@ GNUNET_SOCIAL_guest_enter_reconnect (struct GNUNET_SOCIAL_GuestConnection *gconn struct GNUNET_SOCIAL_TalkRequest * GNUNET_SOCIAL_guest_talk (struct GNUNET_SOCIAL_Guest *gst, const char *method_name, - const struct GNUNET_ENV_Environment *env, + const struct GNUNET_PSYC_Environment *env, GNUNET_PSYC_TransmitNotifyData notify_data, void *notify_data_cls, enum GNUNET_SOCIAL_TalkFlags flags) @@ -2526,7 +1952,7 @@ GNUNET_SOCIAL_guest_disconnect (struct GNUNET_SOCIAL_Guest *gst, */ void GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Guest *gst, - struct GNUNET_ENV_Environment *env, + struct GNUNET_PSYC_Environment *env, GNUNET_ContinuationCallback disconnect_cb, void *cls) { @@ -2575,14 +2001,14 @@ place_history_replay (struct GNUNET_SOCIAL_Place *plc, uint64_t message_limit, const char *method_prefix, uint32_t flags, - struct GNUNET_SOCIAL_Slicer *slicer, + struct GNUNET_PSYC_Slicer *slicer, GNUNET_ResultCallback result_cb, void *cls) { struct GNUNET_PSYC_HistoryRequestMessage *req; struct GNUNET_SOCIAL_HistoryRequest *hist = GNUNET_malloc (sizeof (*hist)); hist->plc = plc; - hist->recv = GNUNET_PSYC_receive_create (NULL, slicer_message, slicer); + hist->recv = GNUNET_PSYC_receive_create (NULL, GNUNET_PSYC_slicer_message, slicer); hist->result_cb = result_cb; hist->cls = cls; hist->op_id = GNUNET_CLIENT_MANAGER_op_add (plc->client, @@ -2638,7 +2064,7 @@ GNUNET_SOCIAL_place_history_replay (struct GNUNET_SOCIAL_Place *plc, uint64_t end_message_id, const char *method_prefix, uint32_t flags, - struct GNUNET_SOCIAL_Slicer *slicer, + struct GNUNET_PSYC_Slicer *slicer, GNUNET_ResultCallback result_cb, void *cls) { @@ -2674,7 +2100,7 @@ GNUNET_SOCIAL_place_history_replay_latest (struct GNUNET_SOCIAL_Place *plc, uint64_t message_limit, const char *method_prefix, uint32_t flags, - struct GNUNET_SOCIAL_Slicer *slicer, + struct GNUNET_PSYC_Slicer *slicer, GNUNET_ResultCallback result_cb, void *cls) { diff --git a/src/social/test_social.c b/src/social/test_social.c @@ -30,7 +30,6 @@ #include "gnunet_common.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" -#include "gnunet_env_lib.h" #include "gnunet_psyc_util_lib.h" #include "gnunet_social_service.h" #include "gnunet_core_service.h" @@ -75,8 +74,8 @@ struct GNUNET_HashCode place_pub_hash; struct GNUNET_CRYPTO_EcdsaPublicKey guest_pub_key; struct GNUNET_CRYPTO_EcdsaPublicKey host_pub_key; -struct GNUNET_SOCIAL_Slicer *host_slicer; -struct GNUNET_SOCIAL_Slicer *guest_slicer; +struct GNUNET_PSYC_Slicer *host_slicer; +struct GNUNET_PSYC_Slicer *guest_slicer; struct GNUNET_SOCIAL_Host *hst; struct GNUNET_SOCIAL_Guest *gst; @@ -90,7 +89,7 @@ struct GuestEnterMessage { struct GNUNET_PSYC_Message *msg; const char *method_name; - struct GNUNET_ENV_Environment *env; + struct GNUNET_PSYC_Environment *env; void *data; uint16_t data_size; } guest_enter_msg; @@ -99,7 +98,7 @@ struct TransmitClosure { struct GNUNET_SOCIAL_Announcement *host_ann; struct GNUNET_SOCIAL_TalkRequest *guest_talk; - struct GNUNET_ENV_Environment *env; + struct GNUNET_PSYC_Environment *env; char *data[16]; uint8_t data_delay[16]; uint8_t data_count; @@ -156,7 +155,7 @@ static void host_answer_door (void *cls, struct GNUNET_SOCIAL_Nym *nym, const char *method_name, - struct GNUNET_ENV_Environment *env, + struct GNUNET_PSYC_Environment *env, size_t data_size, const void *data); @@ -199,13 +198,13 @@ cleanup () if (NULL != guest_slicer) { - GNUNET_SOCIAL_slicer_destroy (guest_slicer); + GNUNET_PSYC_slicer_destroy (guest_slicer); guest_slicer = NULL; } if (NULL != host_slicer) { - GNUNET_SOCIAL_slicer_destroy (host_slicer); + GNUNET_PSYC_slicer_destroy (host_slicer); host_slicer = NULL; } @@ -292,7 +291,7 @@ notify_data (void *cls, uint16_t *data_size, void *data) struct TransmitClosure *tmit = cls; if (NULL != tmit->env) { - GNUNET_ENV_environment_destroy (tmit->env); + GNUNET_PSYC_env_destroy (tmit->env); tmit->env = NULL; } if (0 == tmit->data_count) @@ -355,7 +354,7 @@ schedule_host_leave (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) static void host_farewell2 (void *cls, const struct GNUNET_SOCIAL_Nym *nym, - struct GNUNET_ENV_Environment *env) + struct GNUNET_PSYC_Environment *env) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Nym left the place again.\n"); @@ -526,7 +525,7 @@ zone_add_place () static void host_farewell (void *cls, const struct GNUNET_SOCIAL_Nym *nym, - struct GNUNET_ENV_Environment *env) + struct GNUNET_PSYC_Environment *env) { const struct GNUNET_CRYPTO_EcdsaPublicKey * nym_key = GNUNET_SOCIAL_nym_get_pub_key (nym); @@ -536,7 +535,7 @@ host_farewell (void *cls, "Farewell: nym %s (%s) has left the place.\n", GNUNET_h2s (GNUNET_SOCIAL_nym_get_pub_key_hash (nym)), str); GNUNET_free (str); - GNUNET_assert (1 == GNUNET_ENV_environment_get_count (env)); + GNUNET_assert (1 == GNUNET_PSYC_env_get_count (env)); if (0 != memcmp (&guest_pub_key, nym_key, sizeof (*nym_key))) { str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&guest_pub_key); @@ -565,11 +564,11 @@ guest_leave() else test = TEST_GUEST_LEAVE2; - struct GNUNET_ENV_Environment *env = GNUNET_ENV_environment_create (); - GNUNET_ENV_environment_add (env, GNUNET_ENV_OP_SET, - "_message", DATA2ARG ("Leaving.")); + struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create (); + GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_SET, + "_message", DATA2ARG ("Leaving.")); GNUNET_SOCIAL_guest_leave (gst, env, &guest_left, NULL); - GNUNET_ENV_environment_destroy (env); + GNUNET_PSYC_env_destroy (env); gst = NULL; gst_plc = NULL; } @@ -723,7 +722,7 @@ guest_recv_method (void *cls, const struct GNUNET_PSYC_MessageMethod *meth, uint64_t message_id, uint32_t flags, - const struct GNUNET_SOCIAL_Nym *nym, + const struct GNUNET_CRYPTO_EcdsaPublicKey *nym_pub_key, const char *method_name) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -738,7 +737,7 @@ static void guest_recv_modifier (void *cls, const struct GNUNET_MessageHeader *msg, uint64_t message_id, - enum GNUNET_ENV_Operator oper, + enum GNUNET_PSYC_Operator oper, const char *name, const void *value, uint16_t value_size, @@ -755,7 +754,7 @@ static void guest_recv_mod_foo_bar (void *cls, const struct GNUNET_MessageHeader *msg, uint64_t message_id, - enum GNUNET_ENV_Operator oper, + enum GNUNET_PSYC_Operator oper, const char *name, const void *value, uint16_t value_size, @@ -833,7 +832,7 @@ host_recv_method (void *cls, const struct GNUNET_PSYC_MessageMethod *meth, uint64_t message_id, uint32_t flags, - const struct GNUNET_SOCIAL_Nym *nym, + const struct GNUNET_CRYPTO_EcdsaPublicKey *nym_pub_key, const char *method_name) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -848,7 +847,7 @@ static void host_recv_modifier (void *cls, const struct GNUNET_MessageHeader *msg, uint64_t message_id, - enum GNUNET_ENV_Operator oper, + enum GNUNET_PSYC_Operator oper, const char *name, const void *value, uint16_t value_size, @@ -924,11 +923,11 @@ guest_talk () test = TEST_GUEST_TALK; tmit = (struct TransmitClosure) {}; - tmit.env = GNUNET_ENV_environment_create (); - GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN, - "_bar_foo", DATA2ARG ("one two three")); - GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN, - "_bar_baz", DATA2ARG ("four five")); + tmit.env = GNUNET_PSYC_env_create (); + GNUNET_PSYC_env_add (tmit.env, GNUNET_PSYC_OP_ASSIGN, + "_bar_foo", DATA2ARG ("one two three")); + GNUNET_PSYC_env_add (tmit.env, GNUNET_PSYC_OP_ASSIGN, + "_bar_baz", DATA2ARG ("four five")); tmit.data[0] = "zzz xxx yyy"; tmit.data[1] = "zyx wvu tsr qpo"; tmit.data_delay[1] = 1; @@ -951,13 +950,13 @@ host_announce () "Test #%u: Host announcement.\n", test); tmit = (struct TransmitClosure) {}; - tmit.env = GNUNET_ENV_environment_create (); - GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN, - "_foo", DATA2ARG ("bar baz")); - GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN, - "_foo_bar", DATA2ARG ("foo bar")); - GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN, - "_foo_bar_baz", DATA2ARG ("foo bar baz")); + tmit.env = GNUNET_PSYC_env_create (); + GNUNET_PSYC_env_add (tmit.env, GNUNET_PSYC_OP_ASSIGN, + "_foo", DATA2ARG ("bar baz")); + GNUNET_PSYC_env_add (tmit.env, GNUNET_PSYC_OP_ASSIGN, + "_foo_bar", DATA2ARG ("foo bar")); + GNUNET_PSYC_env_add (tmit.env, GNUNET_PSYC_OP_ASSIGN, + "_foo_bar_baz", DATA2ARG ("foo bar baz")); tmit.data[0] = "aaa bbb ccc"; tmit.data[1] = "abc def ghi jkl"; tmit.data_delay[1] = 1; @@ -976,8 +975,8 @@ static void host_announce2 () { GNUNET_assert (2 == mod_foo_bar_rcls.n); - GNUNET_SOCIAL_slicer_modifier_remove (guest_slicer, "_foo_bar", - guest_recv_mod_foo_bar); + GNUNET_PSYC_slicer_modifier_remove (guest_slicer, "_foo_bar", + guest_recv_mod_foo_bar); test = TEST_HOST_ANNOUNCE2; @@ -985,13 +984,13 @@ host_announce2 () "Test #%u: Host announcement 2.\n", test); tmit = (struct TransmitClosure) {}; - tmit.env = GNUNET_ENV_environment_create (); - GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN, - "_foo2", DATA2ARG ("BAR BAZ")); - GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN, - "_foo2_bar", DATA2ARG ("FOO BAR")); - GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN, - "_foo2_bar", DATA2ARG ("FOO BAR BAZ")); + tmit.env = GNUNET_PSYC_env_create (); + GNUNET_PSYC_env_add (tmit.env, GNUNET_PSYC_OP_ASSIGN, + "_foo2", DATA2ARG ("BAR BAZ")); + GNUNET_PSYC_env_add (tmit.env, GNUNET_PSYC_OP_ASSIGN, + "_foo2_bar", DATA2ARG ("FOO BAR")); + GNUNET_PSYC_env_add (tmit.env, GNUNET_PSYC_OP_ASSIGN, + "_foo2_bar", DATA2ARG ("FOO BAR BAZ")); tmit.data[0] = "AAA BBB CCC"; tmit.data[1] = "ABC DEF GHI JKL"; tmit.data[2] = "TESTING ONE TWO THREE"; @@ -1015,7 +1014,7 @@ guest_recv_entry_decision (void *cls, if (NULL != entry_msg) { - struct GNUNET_ENV_Environment *env = GNUNET_ENV_environment_create (); + struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create (); const char *method_name = NULL; const void *data = NULL; uint16_t data_size = 0; @@ -1057,7 +1056,7 @@ static void host_answer_door (void *cls, struct GNUNET_SOCIAL_Nym *nym, const char *method_name, - struct GNUNET_ENV_Environment *env, + struct GNUNET_PSYC_Environment *env, size_t data_size, const void *data) { @@ -1113,11 +1112,11 @@ guest_enter () struct GuestEnterMessage *emsg = &guest_enter_msg; emsg->method_name = "_request_enter"; - emsg->env = GNUNET_ENV_environment_create (); - GNUNET_ENV_environment_add (emsg->env, GNUNET_ENV_OP_ASSIGN, - "_abc", "abc def", 7); - GNUNET_ENV_environment_add (emsg->env, GNUNET_ENV_OP_ASSIGN, - "_abc_def", "abc def ghi", 11); + emsg->env = GNUNET_PSYC_env_create (); + GNUNET_PSYC_env_add (emsg->env, GNUNET_PSYC_OP_ASSIGN, + "_abc", "abc def", 7); + GNUNET_PSYC_env_add (emsg->env, GNUNET_PSYC_OP_ASSIGN, + "_abc_def", "abc def ghi", 11); emsg->data = "let me in"; emsg->data_size = strlen (emsg->data) + 1; emsg->msg = GNUNET_PSYC_message_create (emsg->method_name, emsg->env, @@ -1142,11 +1141,11 @@ guest_enter_by_name () struct GuestEnterMessage *emsg = &guest_enter_msg; emsg->method_name = "_request_enter"; - emsg->env = GNUNET_ENV_environment_create (); - GNUNET_ENV_environment_add (emsg->env, GNUNET_ENV_OP_ASSIGN, - "_abc", "abc def", 7); - GNUNET_ENV_environment_add (emsg->env, GNUNET_ENV_OP_ASSIGN, - "_abc_def", "abc def ghi", 11); + emsg->env = GNUNET_PSYC_env_create (); + GNUNET_PSYC_env_add (emsg->env, GNUNET_PSYC_OP_ASSIGN, + "_abc", "abc def", 7); + GNUNET_PSYC_env_add (emsg->env, GNUNET_PSYC_OP_ASSIGN, + "_abc_def", "abc def ghi", 11); emsg->data = "let me in"; emsg->data_size = strlen (emsg->data) + 1; emsg->msg = GNUNET_PSYC_message_create (emsg->method_name, emsg->env, @@ -1175,12 +1174,12 @@ guest_init () { guest_pub_key = *(GNUNET_SOCIAL_ego_get_pub_key (guest_ego)); - guest_slicer = GNUNET_SOCIAL_slicer_create (); - GNUNET_SOCIAL_slicer_method_add (guest_slicer, "", - guest_recv_method, guest_recv_modifier, - guest_recv_data, guest_recv_eom, NULL); - GNUNET_SOCIAL_slicer_modifier_add (guest_slicer, "_foo_bar", - guest_recv_mod_foo_bar, &mod_foo_bar_rcls); + guest_slicer = GNUNET_PSYC_slicer_create (); + GNUNET_PSYC_slicer_method_add (guest_slicer, "", + guest_recv_method, guest_recv_modifier, + guest_recv_data, guest_recv_eom, NULL); + GNUNET_PSYC_slicer_modifier_add (guest_slicer, "_foo_bar", + guest_recv_mod_foo_bar, &mod_foo_bar_rcls); test = TEST_HOST_ANSWER_DOOR_ADMIT; GNUNET_SOCIAL_zone_add_nym (app, guest_ego, "host", &host_pub_key, @@ -1224,10 +1223,10 @@ host_entered (void *cls, int result, static void host_enter () { - host_slicer = GNUNET_SOCIAL_slicer_create (); - GNUNET_SOCIAL_slicer_method_add (host_slicer, "", - &host_recv_method, &host_recv_modifier, - &host_recv_data, &host_recv_eom, NULL); + host_slicer = GNUNET_PSYC_slicer_create (); + GNUNET_PSYC_slicer_method_add (host_slicer, "", + &host_recv_method, &host_recv_modifier, + &host_recv_data, &host_recv_eom, NULL); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Entering to place as host.\n"); test = TEST_HOST_ENTER;