X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Finclude%2Fgnunet_psyc_service.h;h=91dcd0b07ad741ae42410ac5057eb8a349b5f2fb;hb=27c12911f4f2aba2d90099270d70de846e83854f;hp=1dd8317403f88c88a3a3b2bbe6f7c3cbc86af5d4;hpb=f9d1691fd19c974d35f57164298dd2a580c83315;p=oweals%2Fgnunet.git diff --git a/src/include/gnunet_psyc_service.h b/src/include/gnunet_psyc_service.h index 1dd831740..91dcd0b07 100644 --- a/src/include/gnunet_psyc_service.h +++ b/src/include/gnunet_psyc_service.h @@ -28,31 +28,32 @@ * and this API deliberately exposes as little as possible * of the actual data stream format to the application! * @author Christian Grothoff + * @author Gabor X Toth * * NOTE: * - this API does not know about psyc's "root" and "places"; * there is no 'root' in GNUnet-Psyc as we're decentralized; - * 'places' and 'persons' are combined within the same + * 'places' and 'persons' are combined within the same * abstraction, that of a "channel". Channels are identified - * and accessed in this API using a public/private key. - * Higher-level applications should use NAMES within GADS - * to obtain public keys, and the distinction between + * and accessed in this API using a public/private key. + * Higher-level applications should use NAMES within GNS + * to obtain public keys, and the distinction between * 'places' and 'persons' can then be made with the help * of the naming system (and/or conventions). * Channels are (as in PSYC) organized into a hierarchy; each - * channel owner (the one with the private key) is then - * the operator of the multicast group (its Origin in + * channel master (the one with the private key) is then + * the operator of the multicast group (its Origin in * the terminology of the multicast API). * - The API supports passing large amounts of data using * 'streaming' for the argument passed to a method. State * and variables must fit into memory and cannot be streamed - * (thus, no passing of 4 GB of data in a variable; + * (thus, no passing of 4 GB of data in a variable; * once we implement this, we might want to create a - * #define for the maximum size of a variable). + * @c \#define for the maximum size of a variable). * - PSYC defines standard variables, methods, etc. This * library deliberately abstracts over all of these; a - * higher-level API should combine the naming system (GADS) - * and standard methods (message, join, leave, warn, + * higher-level API should combine the naming system (GNS) + * and standard methods (message, join, part, warn, * fail, error) and variables (action, color, time, * tag, etc.). However, this API does take over the * routing variables, specifically 'context' (channel), @@ -60,11 +61,11 @@ * the target is either everyone in the group or the * origin, and never just a single member of the group; * for such individual messages, an application needs to - * construct an 'inbox' channel where the owner (only) + * construct an 'inbox' channel where the master (only) * receives messages (but never forwards; private responses * would be transmitted by joining the senders 'inbox' * channel -- or a inbox#bob subchannel). The - * goal for all of this is to keep the abstractions in this + * goal for all of this is to keep the abstractions in this * API minimal: interaction with multicast, try \& slice, * state/variable/channel management. Higher-level * operations belong elsewhere (so maybe this API should @@ -85,6 +86,7 @@ extern "C" #endif #include "gnunet_util_lib.h" +#include "gnunet_env_lib.h" #include "gnunet_multicast_service.h" @@ -95,419 +97,699 @@ extern "C" /** - * Method called from PSYC upon receiving a message indicating a call - * to a 'method'. + * Policy flags for a channel. + */ +enum GNUNET_PSYC_ChannelFlags +{ + /** + * Admission must be confirmed by the master. + */ + GNUNET_PSYC_CHANNEL_ADMISSION_CONTROL = 1 << 0, + + /** + * Past messages are only available to slaves who were admitted at the time + * they were sent to the channel. + */ + GNUNET_PSYC_CHANNEL_RESTRICTED_HISTORY = 1 << 1, +}; + +/** + * PSYC channel policies. + */ +enum GNUNET_PSYC_Policy +{ + /** + * Anyone can join the channel, without announcing his presence; + * all messages are always public and can be distributed freely. + * Joins may be announced, but this is not required. + */ + GNUNET_PSYC_CHANNEL_ANONYMOUS = 0, + + /** + * The master must approve membership to the channel, messages must only be + * distributed to current channel slaves. This includes the channel + * state as well as transient messages. + */ + GNUNET_PSYC_CHANNEL_PRIVATE + = GNUNET_PSYC_CHANNEL_ADMISSION_CONTROL + | GNUNET_PSYC_CHANNEL_RESTRICTED_HISTORY, + +#if IDEAS_FOR_FUTURE + /** + * Anyone can freely join the channel (no approval required); + * however, messages must only be distributed to current channel + * slaves, so the master must still acknowledge that the slave + * joined before transient messages are delivered. As approval is + * guaranteed, the presistent channel state can be synchronized freely + * immediately, prior to master confirmation. + */ + GNUNET_PSYC_CHANNEL_OPEN + = GNUNET_PSYC_CHANNEL_RESTRICTED_HISTORY, + + /** + * The master must approve joins to the channel, but past messages can be + * freely distributed to slaves. + */ + GNUNET_PSYC_CHANNEL_CLOSED + = GNUNET_PSYC_CHANNEL_ADMISSION_CONTROL, +, +#endif + +}; + + +enum GNUNET_PSYC_MessageFlags +{ + /** + * First fragment of a message. + */ + GNUNET_PSYC_MESSAGE_FIRST_FRAGMENT = 1 << 0, + + /** + * Last fragment of a message. + */ + GNUNET_PSYC_MESSAGE_LAST_FRAGMENT = 1 << 1, + + /** + * OR'ed flags if message is not fragmented. + */ + GNUNET_PSYC_MESSAGE_NOT_FRAGMENTED + = GNUNET_PSYC_MESSAGE_FIRST_FRAGMENT + | GNUNET_PSYC_MESSAGE_LAST_FRAGMENT, + + /** + * Historic message, retrieved from PSYCstore. + */ + GNUNET_PSYC_MESSAGE_HISTORIC = 1 << 30 +}; + + +/** + * M + */ +struct GNUNET_PSYC_MessageMethod +{ + /** + * Type: GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD + */ + struct GNUNET_MessageHeader header; + + uint32_t reserved GNUNET_PACKED; + + /** + * Number of modifiers in the message. + */ + uint32_t mod_count GNUNET_PACKED; + + /** + * OR'ed GNUNET_PSYC_MasterTransmitFlags + */ + uint32_t flags GNUNET_PACKED; + + /** + * Sending slave's public key. + * NULL if the message is from the master, or when transmitting a message. + */ + struct GNUNET_CRYPTO_EddsaPublicKey slave_key; + + /* Followed by NUL-terminated method name. */ +}; + + +struct GNUNET_PSYC_MessageModifier +{ + /** + * Type: GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER + */ + struct GNUNET_MessageHeader header; + + /** + * Size of value. + */ + uint32_t value_size GNUNET_PACKED; + + /** + * Size of name, including NUL terminator. + */ + uint16_t name_size GNUNET_PACKED; + + /** + * enum GNUNET_ENV_Operator + */ + uint8_t oper; + + /* Followed by NUL-terminated name, then the value. */ +}; + + +enum GNUNET_PSYC_DataStatus +{ + /** + * To be continued. + */ + GNUNET_PSYC_DATA_CONT = 0, + + /** + * Reached the end of message. + */ + GNUNET_PSYC_DATA_END = 1, + + /** + * Cancelled before the end. + */ + GNUNET_PSYC_DATA_CANCEL = 2 +}; + + +struct GNUNET_PSYC_MessageData +{ + /** + * Type: GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA + */ + struct GNUNET_MessageHeader header; + + /** + * enum GNUNET_PSYC_DataStatus + */ + uint8_t status; +}; + +/** + * Handle that identifies a join request. * - * @param cls closure - * @param full_method_name original method name from PSYC (may be more - * specific than the registered method name due to try-and-slice matching) - * @param sender who transmitted the message (origin, except for messages - * from one of the members to the origin) - * @param message_id unique message counter for this message; - * (unique only in combination with the given sender for - * this channel) - * @param group_generation group generation counter for this message - * (always zero for messages from members to channel owner) - * @param data_size number of bytes in 'data' - * @param data data stream given to the method (might not be zero-terminated - * if data is binary) + * Used to match calls to #GNUNET_PSYC_JoinCallback to the + * corresponding calls to GNUNET_PSYC_join_decision(). */ -typedef int (*GNUNET_PSYC_Method)(void *cls, - const char *full_method_name, - const struct GNUNET_PeerIdentity *sender, - uint64_t message_id, - uint64_t group_generation, - size_t data_size, - const char *data); +struct GNUNET_PSYC_JoinHandle; /** - * Handle for the channel of a PSYC group. + * Method called from PSYC upon receiving a message indicating a call to a + * @e method. + * + * @param cls Closure. + * @param slave_key Who transmitted the message. + * - NULL for multicast messages from the master. + * - The sending slave's public key for unicast requests from one of the + * slaves to the master. + * @param message_id Unique message counter for this message. + * Unique only in combination with the given sender for this channel. + * @param method_name Method name from PSYC. + * @param modifier_count Number of elements in the @a modifiers array. + * @param modifiers State modifiers and transient variables for the message. + * @param data_offset Byte offset of @a data in the overall data of the method. + * @param data Data stream given to the method (might not be zero-terminated + * if data is binary). + * @param data_size Number of bytes in @a data. + * @param frag Fragmentation status for the data. */ -struct GNUNET_PSYC_Channel; +typedef int +(*GNUNET_PSYC_Method) (void *cls, + const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, + uint64_t message_id, + const char *method_name, + size_t modifier_count, + const struct GNUNET_ENV_Modifier *modifiers, + uint64_t data_offset, + const void *data, + size_t data_size, + enum GNUNET_PSYC_MessageFlags flags); /** - * Start a PSYC channel. Will create a multicast group identified by - * the given public key. Messages recevied from group members will be - * given to the respective handler methods. If a new member wants to - * join a group, the "join" method handler will be invoked; the join - * handler must then generate a "join" message to approve the joining - * of the new member. The channel can also change group membership - * without explicit requests. Note that PSYC doesn't itself "understand" - * join or leave messages, the respective methods must call other - * PSYC functions to inform PSYC about the meaning of the respective - * events. - * - * @param cfg configuration to use (to connect to PSYC service) - * @param parent parent channel, NULL for top-level channels - * @param name name of the channel, only important if this is a subchannel - * @param method_count number of methods in 'methods' array - * @param methods functions to invoke on messages received from members, - * typcially at least contains functions for 'join' and 'leave'. - * @param priv_key ECC key that will be used to sign messages for this - * PSYC session; public key is used to identify the - * PSYC group; FIXME: we'll likely want to use - * NOT the p521 curve here, but a cheaper one in the future - * Note that end-users will usually not use the private key - * directly, but rather look it up in GADS for groups - * managed by other users, or select a file with the private - * key(s) when setting up their own channels - * @param join_policy what is the membership policy of the group? - * Used to automate group management decisions. - * @return handle for the channel, NULL on error + * Method called from PSYC upon receiving a join request. + * + * @param cls Closure. + * @param slave requesting to join. + * @param method_name Method name in the join request. + * @param variable_count Number of elements in the @a variables array. + * @param variables Transient variables for the join request. + * @param data Data stream given to the method (might not be zero-terminated + * if data is binary). + * @param data_size Number of bytes in @a data. + * @param jh Join handle to use with GNUNET_PSYC_join_decision() */ -struct GNUNET_PSYC_Channel * -GNUNET_PSYC_channel_start (const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_PSYC_Channel *parent, - const char *name, - unsigned int method_count, - const struct GNUNET_PSYC_Method *methods, - const struct GNUNET_CRYPTO_EccPrivateKey *priv_key, - enum GNUNET_MULTICAST_JoinPolicy join_policy); - - -/** - * Possible operations on PSYC state (persistent) and variables (per message). - */ -enum GNUNET_PSYC_Operator - { - /** - * Replace the full state with the new value ("="). - */ - GNUNET_PSYC_SOT_SET_STATE = 0, - - /** - * Delete the complete entry from the state (given data must be - * empty). Equivalent to 'SET' with emtpy data, but more - * explicit ("="); - */ - GNUNET_PSYC_SOT_DELETE = 0, - - /** - * Set the value of a variable to a new value (":"). - */ - GNUNET_PSYC_SOT_SET_VARIABLE, - - /** - * Add the given value to the set of values in the state ("+"). - */ - GNUNET_PSYC_SOT_ADD_STATE, - - /** - * Remove the given value from the set of values in the state ("-"). - */ - GNUNET_PSYC_SOT_REMOVE_STATE - - }; - - -/** - * Update channel state or variables. The state of a channel must fit - * into the memory of each member (and the channel); large values that - * require streaming must only be passed as the stream arguments to - * methods. State updates might not be transmitted to group members - * until the next call to 'GNUNET_PSYC_channel_broadcast_call_method'. - * Variable updates must be given just before the call to the - * respective method that needs the variables. - * - * @param channel handle to the PSYC group / channel - * @param full_state_name name of the field in the channel state to change - * @param type kind of update operation (add, remove, replace, delete) - * @param data_size number of bytes in data - * @param data new state value - * @return GNUNET_OK on success, GNUNET_SYSERR on internal error - * (i.e. state too large) - */ -int -GNUNET_PSYC_channel_update (struct GNUNET_PSYC_Channel *channel, - const char *full_state_name, - enum GNUNET_PSYC_Operator type, - size_t data_size, - const void *data); - - -/** - * Function called to provide data for a transmission via PSYC. Note - * that returning GNUNET_OK or GNUNET_SYSERR (but not GNUNET_NO) +typedef int +(*GNUNET_PSYC_JoinCallback) (void *cls, + const struct GNUNET_CRYPTO_EddsaPublicKey + *slave_key, + const char *method_name, + size_t variable_count, + const struct GNUNET_ENV_Modifier *variables, + const void *data, + size_t data_size, + struct GNUNET_PSYC_JoinHandle *jh); + + +/** + * Function to call with the decision made for a join request. + * + * Must be called once and only once in response to an invocation of the + * #GNUNET_PSYC_JoinCallback. + * + * @param jh Join request handle. + * @param is_admitted #GNUNET_YES if joining is approved, + * #GNUNET_NO if it is disapproved. + * @param relay_count Number of relays given. + * @param relays Array of suggested peers that might be useful relays to use + * when joining the multicast group (essentially a list of peers that + * are already part of the multicast group and might thus be willing + * to help with routing). If empty, only this local peer (which must + * be the multicast origin) is a good candidate for building the + * multicast tree. Note that it is unnecessary to specify our own + * peer identity in this array. + * @param method_name Method name for the message transmitted with the response. + * @param env Environment containing transient variables for the message, + * or NULL. + * @param data Data of the message. + * @param data_size Size of @a data. + */ +void +GNUNET_PSYC_join_decision (struct GNUNET_PSYC_JoinHandle *jh, + int is_admitted, + uint32_t relay_count, + const struct GNUNET_PeerIdentity *relays, + const char *method_name, + const struct GNUNET_ENV_Environment *env, + const void *data, + size_t data_size); + + +/** + * Handle for the master of a PSYC channel. + */ +struct GNUNET_PSYC_Master; + + +/** + * Function called after the channel master started. + * + * @param cls Closure. + * @param last_message_id Last message ID sent to the channel. + */ +typedef void +(*GNUNET_PSYC_MasterStartCallback) (void *cls, uint64_t max_message_id); + + +/** + * Start a PSYC master channel. + * + * Will start a multicast group identified by the given ECC key. Messages + * received from group members will be given to the respective handler methods. + * If a new member wants to join a group, the "join" method handler will be + * invoked; the join handler must then generate a "join" message to approve the + * joining of the new member. The channel can also change group membership + * without explicit requests. Note that PSYC doesn't itself "understand" join + * or part messages, the respective methods must call other PSYC functions to + * inform PSYC about the meaning of the respective events. + * + * @param cfg Configuration to use (to connect to PSYC service). + * @param channel_key ECC key that will be used to sign messages for this + * PSYC session. The public key is used to identify the PSYC channel. + * Note that end-users will usually not use the private key directly, but + * rather look it up in GNS for places managed by other users, or select + * a file with the private key(s) when setting up their own channels + * FIXME: we'll likely want to use NOT the p521 curve here, but a cheaper + * one in the future. + * @param policy Channel policy specifying join and history restrictions. + * Used to automate join decisions. + * @param method Function to invoke on messages received from slaves. + * @param join_cb Function to invoke when a peer wants to join. + * @param master_started_cb Function to invoke after the channel master started. + * @param cls Closure for @a method and @a join_cb. + * @return Handle for the channel master, NULL on error. + */ +struct GNUNET_PSYC_Master * +GNUNET_PSYC_master_start (const struct GNUNET_CONFIGURATION_Handle *cfg, + const struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key, + enum GNUNET_PSYC_Policy policy, + GNUNET_PSYC_Method method, + GNUNET_PSYC_JoinCallback join_cb, + GNUNET_PSYC_MasterStartCallback master_started_cb, + void *cls); + + +/** + * Function called to provide data for a transmission via PSYC. + * + * Note that returning #GNUNET_OK or #GNUNET_SYSERR (but not #GNUNET_NO) * invalidates the respective transmission handle. * - * @param cls closure - * @param message_id set to the unique message ID that was generated for - * this message - * @param group_generation set to the group generation used for this - * message - * @param data_size initially set to the number of bytes available in 'data', - * should be set to the number of bytes written to data (IN/OUT) - * @param data where to write the body of the message to give to the method; - * function must copy at most '*data_size' bytes to 'data'. - * @return GNUNET_SYSERR on error (fatal, aborts transmission) - * GNUNET_NO on success, if more data is to be transmitted later - * (should be used if 'data_size' was not big enough to take all the data) - * GNUNET_OK if this completes the transmission (all data supplied) + * @param cls Closure. + * @param[in,out] data_size Initially set to the number of bytes available in + * @a data, should be set to the number of bytes written to data. + * @param[out] data Where to write the body of the message to give to the + * method. The function must copy at most @a data_size bytes to @a data. + * @return #GNUNET_SYSERR on error (fatal, aborts transmission) + * #GNUNET_NO on success, if more data is to be transmitted later. + * Should be used if @a data_size was not big enough to take all the + * data. If 0 is returned in @a data_size the transmission is paused, + * and can be resumed with GNUNET_PSYC_master_transmit_resume(). + * #GNUNET_YES if this completes the transmission (all data supplied) + */ +typedef int +(*GNUNET_PSYC_MasterTransmitNotify) (void *cls, + size_t *data_size, + void *data); + + +/** + * Flags for transmitting messages to a channel by the master. */ -typedef int (*GNUNET_PSYC_ChannelReadyNotify)(void *cls, - uint64_t message_id, - uint64_t group_generation, - size_t *data_size, - char *data); +enum GNUNET_PSYC_MasterTransmitFlags +{ + GNUNET_PSYC_MASTER_TRANSMIT_NONE = 0, + /** + * Whether this message should reset the channel state, + * i.e. remove all previously stored state variables. + */ + GNUNET_PSYC_MASTER_TRANSMIT_RESET_STATE = 1 << 0, + + /** + * Whether we need to increment the group generation counter after + * transmitting this message. + */ + GNUNET_PSYC_MASTER_TRANSMIT_INC_GROUP_GEN = 1 << 1, + + /** + * Add PSYC header variable with the hash of the current channel state. + */ + GNUNET_PSYC_MASTER_TRANSMIT_ADD_STATE_HASH = 1 << 2 +}; /** * Handle for a pending PSYC transmission operation. */ -struct GNUNET_PSYC_ChannelTransmitHandle; +struct GNUNET_PSYC_MasterTransmitHandle; + + +/** + * Send a message to call a method to all members in the PSYC channel. + * + * @param master Handle to the PSYC channel. + * @param method_name Which method should be invoked. + * @param env Environment containing state operations and transient variables + * for the message, or NULL. + * @param notify Function to call to obtain the arguments. + * @param notify_cls Closure for @a notify. + * @param flags Flags for the message being transmitted. + * @return Transmission handle, NULL on error (i.e. more than one request queued). + */ +struct GNUNET_PSYC_MasterTransmitHandle * +GNUNET_PSYC_master_transmit (struct GNUNET_PSYC_Master *master, + const char *method_name, + const struct GNUNET_ENV_Environment *env, + GNUNET_PSYC_MasterTransmitNotify notify, + void *notify_cls, + enum GNUNET_PSYC_MasterTransmitFlags flags); /** - * Send a message to call a method to all members in the PSYC channel - * (and all parent channels if this is a subchannel). + * Resume transmission to the channel. * - * @param channel handle to the PSYC multicast group - * @param increment_group_generation GNUNET_YES if we need to increment - * the group generation counter after transmitting this message - * @param full_method_name which method should be invoked - * @param notify function to call to obtain the arguments - * @param notify_cls closure for 'notify' - * @return transmission handle, NULL on error (i.e. more than one request queued) + * @param th Handle of the request that is being resumed. */ -struct GNUNET_PSYC_ChannelTransmitHandle * -GNUNET_PSYC_channel_notify_transmit_ready (struct GNUNET_PSYC_Channel *channel, - int increment_group_generation, - const char *full_method_name, - GNUNET_PSYC_ChannelReadyNotify notify, - void *notify_cls); +void +GNUNET_PSYC_master_transmit_resume (struct GNUNET_PSYC_MasterTransmitHandle *th); /** * Abort transmission request to channel. * - * @param th handle of the request that is being aborted + * @param th Handle of the request that is being aborted. */ void -GNUNET_PSYC_channel_notify_transmit_ready_cancel (struct GNUNET_PSYC_ChannelTransmitHandle *th); +GNUNET_PSYC_master_transmit_cancel (struct GNUNET_PSYC_MasterTransmitHandle *th); /** - * End a PSYC channel. Note that subchannels MUST be ended before - * their parents. + * Stop a PSYC master channel. * - * @param channel PSYC channel to terminate + * @param master PSYC channel master to stop. */ void -GNUNET_PSYC_channel_end (struct GNUNET_PSYC_Channel *channel); +GNUNET_PSYC_master_stop (struct GNUNET_PSYC_Master *master); /** - * Handle to access PSYC group operations for all members. + * Handle for a PSYC channel slave. */ -struct GNUNET_PSYC_Group; +struct GNUNET_PSYC_Slave; /** - * Convert 'channel' to a 'group' handle to access the 'group' APIs. - * - * @param channel channel handle - * @return group handle, valid for as long as 'channel' is valid - */ -struct GNUNET_PSYC_Group * -GNUNET_PSYC_channel_get_group (struct GNUNET_PSYC_Channel *channel); + * Function called after the slave joined. + * + * @param cls Closure. + * @param max_message_id Last message ID sent to the channel. + */ +typedef void +(*GNUNET_PSYC_SlaveJoinCallback) (void *cls, uint64_t max_message_id); /** - * Add a member to the group. Note that this will NOT generate any - * PSYC traffic, it will merely update the local data base to modify - * how we react to 'membership test' queries. The channel still needs to - * explicitly transmit a 'join' message to notify other group members - * and they then also must still call this function in their respective - * methods handling the 'join' message. This way, how 'join' and 'leave' - * operations are exactly implemented is still up to the application; - * for example, there might be a 'leave_all' method to kick out everyone. + * Join a PSYC channel. * - * Note that group members are explicitly trusted to execute such - * methods correctly; not doing so correctly will result in either - * denying members access or offering access to group data to - * non-members. + * The entity joining is always the local peer. The user must immediately use + * the GNUNET_PSYC_slave_transmit() functions to transmit a @e join_msg to the + * channel; if the join request succeeds, the channel state (and @e recent + * method calls) will be replayed to the joining member. There is no explicit + * notification on failure (as the channel may simply take days to approve, + * and disapproval is simply being ignored). * - * @param group group handle - * @param member which peer to add - * @param message_id message ID for the message that changed the membership - * @param group_generation the generation ID where the change went into effect + * @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 + * 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 + * as relays and used to join the group at. + * @param method Function to invoke on messages received from the channel, + * typically at least contains functions for @e join and @e part. + * @param join_cb function invoked once we have joined with the current + * message ID of the channel + * @param slave_joined_cb Function to invoke when a peer wants to join. + * @param cls Closure for @a method_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. + * @return Handle for the slave, NULL on error. */ -void -GNUNET_PSYC_group_member_admit (struct GNUNET_PSYC_Group *group, - const struct GNUNET_PeerIdentity *member, - uint64_t message_id, - uint64_t group_generation); +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_EddsaPrivateKey *slave_key, + const struct GNUNET_PeerIdentity *origin, + uint32_t relay_count, + const struct GNUNET_PeerIdentity *relays, + GNUNET_PSYC_Method method, + GNUNET_PSYC_JoinCallback join_cb, + GNUNET_PSYC_SlaveJoinCallback slave_joined_cb, + void *cls, + const char *method_name, + const struct GNUNET_ENV_Environment *env, + const void *data, + uint16_t data_size); /** - * Remove a member from the group. Note that this will NOT generate any - * PSYC traffic, it will merely update the local data base to modify - * how we react to 'membership test' queries. The channel still needs to - * explicitly transmit a 'leave' message to notify other group members - * and they then also must still call this function in their respective - * methods handling the 'leave' message. This way, how 'join' and 'leave' - * operations are exactly implemented is still up to the application; - * for example, there might be a 'leave_all' message to kick out everyone. + * Part a PSYC channel. * - * Note that group members are explicitly trusted to perform these - * operations correctly; not doing so correctly will result in either - * denying members access or offering access to group data to - * non-members. + * Will terminate the connection to the PSYC service. Polite clients should + * first explicitly send a part request (via GNUNET_PSYC_slave_transmit()). * - * @param group group handle - * @param member which peer to remove - * @param message_id message ID for the message that changed the membership - * @param group_generation the generation ID where the change went into effect + * @param slave Slave handle. */ void -GNUNET_PSYC_group_member_kick (struct GNUNET_PSYC_Group *group, - const struct GNUNET_PeerIdentity *member, - uint64_t message_id, - uint64_t group_generation); +GNUNET_PSYC_slave_part (struct GNUNET_PSYC_Slave *slave); /** - * Function called to inform a member about state changes for a - * channel. Note that (for sets) only the delta is communicated, not - * the full state. + * Function called to provide data for a transmission to the channel master + * (a.k.a. the @e host of the channel). + * + * Note that returning #GNUNET_OK or #GNUNET_SYSERR (but not #GNUNET_NO) + * invalidates the respective transmission handle. * - * @param cls closure - * @param full_state_name full name of the state - * @param type how to interpret the change - * @param state_value information about the new state + * @param cls Closure. + * @param[in,out] data_size Initially set to the number of bytes available in + * @a data, should be set to the number of bytes written to data + * (IN/OUT). + * @param[out] data Where to write the body of the message to give to the method; + * function must copy at most @a *data_size bytes to @a data. + * @return #GNUNET_SYSERR on error (fatal, aborts transmission). + * #GNUNET_NO on success, if more data is to be transmitted later. + * #GNUNET_YES if this completes the transmission (all data supplied). */ -typedef void (*GNUNET_PSYC_StateCallback)(void *cls, - const char *full_state_name, - enum GNUNET_PSYC_Operator type, - const struct GNUNET_PSYC_Argument *state_value); +typedef int +(*GNUNET_PSYC_SlaveTransmitNotify) (void *cls, + size_t *data_size, + char *data); /** - * Descriptor for an event handler handling PSYC state updates. + * Flags for transmitting messages to the channel master by a slave. */ -struct GNUNET_PSYC_StateHandler +enum GNUNET_PSYC_SlaveTransmitFlags { + GNUNET_PSYC_SLAVE_TRANSMIT_NONE = 0 +}; - /** - * Name of the state this handler calls about, used in try-and-slice matching. - */ - const char *state_name; - /** - * Function to call whenever the respective state changes. - */ - GNUNET_PSYC_StateCallback event_handler; +/** + * Handle for a pending PSYC transmission operation. + */ +struct GNUNET_PSYC_SlaveTransmitHandle; - /** - * Closure for the 'event_handler' function. - */ - void *event_handler_cls; - /** - * Description of the kind of state that the handler expects to see. - * Non-matching state updates will be ignored (but logged). Note - * that the state_types of all states with the same state name - * prefix should be identical. For state types, the - * 'GNUNET_PSYC_AF_STREAMABLE' and 'GNUNET_PSYC_AF_SET_STREAMABLE' - * flags must never be set (as the channel state should be small - * enough to (easily) fit into the memory of all PSYC members). - */ - struct GNUNET_PSYC_ArgumentDescriptor state_type; +/** + * Request a message to be sent to the channel master. + * + * @param slave Slave handle. + * @param method_name Which (PSYC) method should be invoked (on host). + * @param env Environment containing transient variables for the message, or NULL. + * @param notify Function to call when we are allowed to transmit (to get data). + * @param notify_cls Closure for @a notify. + * @param flags Flags for the message being transmitted. + * @return Transmission handle, NULL on error (i.e. more than one request queued). + */ +struct GNUNET_PSYC_SlaveTransmitHandle * +GNUNET_PSYC_slave_transmit (struct GNUNET_PSYC_Slave *slave, + const char *method_name, + const struct GNUNET_ENV_Environment *env, + GNUNET_PSYC_SlaveTransmitNotify notify, + void *notify_cls, + enum GNUNET_PSYC_SlaveTransmitFlags flags); -}; + +/** + * Resume transmission to the master. + * + * @param th Handle of the request that is being resumed. + */ +void +GNUNET_PSYC_slave_transmit_resume (struct GNUNET_PSYC_MasterTransmitHandle *th); + + +/** + * Abort transmission request to master. + * + * @param th Handle of the request that is being aborted. + */ +void +GNUNET_PSYC_slave_transmit_cancel (struct GNUNET_PSYC_SlaveTransmitHandle *th); /** - * Join a PSYC group. The entity joining is always the local peer. - * This will send a 'join_msg' to the channel; if it succeeds, the - * channel state (and 'recent' method calls) will be replayed to the - * joining member and the 'join' method will be invoked to show that - * we joined successfully. There is no explicit notification on - * failure (as the channel may simply take days to approve, and - * disapproval is simply being ignored). - * - * @param cfg configuration to use - * @param pub_key ECC key that identifies the channel we wish to join - * @param method_count number of methods in 'methods' array - * @param methods functions to invoke on messages received from the channel, - * typcially at least contains functions for 'join' and 'leave'. - * @param state_count number of state handlers - * @param state_handlers array of state event handlers - * @param join_msg which method should we invoke on the channel controller - * to try to join the channel (i.e. "join") - * @param join_cb method to invoke on channel to obtain arguments - * for a join method invocation; - * use NULL to send nothing (useful for anonymous groups that permit anyone); - * arguments to give to join method, must not include streaming args - * @param join_cb_cls closure for 'join_cb' - * @return handle for the member, NULL on error - */ -struct GNUNET_PSYC_Member * -GNUNET_PSYC_member_join (const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_CRYPTO_EccPublicKey *pub_key, - unsigned int method_count, - const struct GNUNET_PSYC_Method *methods, - unsigned int state_count, - struct GNUNET_PSYC_StateHandler *state_handlers, - const char *join_method, - const struct GNUNET_PSYC_ChannelReadyNotify join_cb, - void *join_cb_cls); - - -/** - * Function called to provide data for a transmission to the channel - * owner (aka the 'host' of the channel). Note that returning - * GNUNET_OK or GNUNET_SYSERR (but not GNUNET_NO) invalidates the - * respective transmission handle. - * - * @param cls closure - * @param data_size initially set to the number of bytes available in 'data', - * should be set to the number of bytes written to data (IN/OUT) - * @param data where to write the body of the message to give to the method; - * function must copy at most '*data_size' bytes to 'data'. - * @return GNUNET_SYSERR on error (fatal, aborts transmission) - * GNUNET_NO on success, if more data is to be transmitted later - * GNUNET_OK if this completes the transmission (all data supplied) - */ -typedef int (*GNUNET_PSYC_HostReadyNotify)(void *cls, - size_t *data_size, - char *data); + * Handle to access PSYC channel operations for both the master and slaves. + */ +struct GNUNET_PSYC_Channel; /** - * Handle for a pending PSYC transmission operation. + * Convert a channel @a master to a @e channel handle to access the @e channel + * APIs. + * + * @param master Channel master handle. + * @return Channel handle, valid for as long as @a master is valid. */ -struct GNUNET_PSYC_HostTransmitHandle; +struct GNUNET_PSYC_Channel * +GNUNET_PSYC_master_get_channel (struct GNUNET_PSYC_Master *master); /** - * Request a message to be send to the channel. + * Convert @a slave to a @e channel handle to access the @e channel APIs. * - * @param member membership handle - * @param request_data which method should be invoked on channel (and how) - * @param method_name which method should be invoked - * @param argc number of arguments the method takes (size of 'ads' array) - * @param ads description of the arguments the method takes - * @param notify function to call to obtain the arguments - * @param notify_cls closure for 'notify' - * @return transmission handle, NULL on error (i.e. more than one request queued) + * @param slave Slave handle. + * @return Channel handle, valid for as long as @a slave is valid. */ -struct GNUNET_PSYC_HostTransmitHandle * -GNUNET_PSYC_member_send_to_host (struct GNUNET_PSYC_Member *member, - const char *method_name, - GNUNET_PSYC_HostReadyNotify notify, - void *notify_cls); +struct GNUNET_PSYC_Channel * +GNUNET_PSYC_slave_get_channel (struct GNUNET_PSYC_Slave *slave); /** - * Abort transmission request to host. + * Add a slave to the channel's membership list. + * + * Note that this will NOT generate any PSYC traffic, it will merely update the + * local database to modify how we react to membership test queries. + * The channel master still needs to explicitly transmit a @e join message to + * notify other channel members and they then also must still call this function + * in their respective methods handling the @e join message. This way, how @e + * join and @e part operations are exactly implemented is still up to the + * application; for example, there might be a @e part_all method to kick out + * everyone. + * + * Note that channel slaves are explicitly trusted to execute such methods + * correctly; not doing so correctly will result in either denying other slaves + * access or offering access to channel data to non-members. * - * @param th handle of the request that is being aborted + * @param channel Channel handle. + * @param slave_key Identity of channel slave to add. + * @param announced_at ID of the message that announced the membership change. + * @param effective_since Addition of slave is in effect since this message ID. */ void -GNUNET_PSYC_member_send_to_host_cancel (struct GNUNET_PSYC_HostTransmitHandle *th); +GNUNET_PSYC_channel_slave_add (struct GNUNET_PSYC_Channel *channel, + const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, + uint64_t announced_at, + uint64_t effective_since); + + +/** + * Remove a slave from the channel's membership list. + * + * Note that this will NOT generate any PSYC traffic, it will merely update the + * local database to modify how we react to membership test queries. + * The channel master still needs to explicitly transmit a @e part message to + * notify other channel members and they then also must still call this function + * in their respective methods handling the @e part message. This way, how + * @e join and @e part operations are exactly implemented is still up to the + * application; for example, there might be a @e part_all message to kick out + * everyone. + * + * Note that channel members are explicitly trusted to perform these + * operations correctly; not doing so correctly will result in either + * denying members access or offering access to channel data to + * non-members. + * + * @param channel Channel handle. + * @param slave_key Identity of channel slave to remove. + * @param announced_at ID of the message that announced the membership change. + */ +void +GNUNET_PSYC_channel_slave_remove (struct GNUNET_PSYC_Channel *channel, + const struct GNUNET_CRYPTO_EddsaPublicKey + *slave_key, + uint64_t announced_at); + + +/** + * Function called to inform a member about stored state values for a channel. + * + * @param cls Closure. + * @param name Name of the state variable. A NULL value indicates that there + * are no more state variables to be returned. + * @param value Value of the state variable. + * @param value_size Number of bytes in @a value. + */ +typedef void +(*GNUNET_PSYC_StateCallback) (void *cls, + const char *name, + const void *value, + size_t value_size); + + +/** + * Function called when a requested operation has finished. + * + * @param cls Closure. + */ +typedef void +(*GNUNET_PSYC_FinishCallback) (void *cls); /** @@ -517,100 +799,105 @@ struct GNUNET_PSYC_Story; /** - * Request to be told the message history of the channel. Historic - * messages (but NOT the state at the time) will be replayed (given to - * the normal method handlers) if available and if access is - * permitted. + * Request to be told the message history of the channel. + * + * Historic messages (but NOT the state at the time) will be replayed (given to + * the normal method handlers) if available and if access is permitted. * - * @param member which channel should be replayed? - * @param start earliest interesting point in history - * @param end last (exclusive) interesting point in history - * @param finish_cb function to call when the requested story has been fully + * To get the latest message, use 0 for both the start and end message ID. + * + * @param channel Which channel should be replayed? + * @param start_message_id Earliest interesting point in history. + * @param end_message_id Last (exclusive) interesting point in history. + * @param method Function to invoke on messages received from the story. + * @param finish_cb Function to call when the requested story has been fully * told (counting message IDs might not suffice, as some messages - * might be secret and thus the listener would not know the story is + * might be secret and thus the listener would not know the story is * finished without being told explicitly); once this function * has been called, the client must not call - * 'GNUNET_PSYC_member_story_tell_cancel' anymore - * @param finish_cb_cls closure to finish_cb - * @return handle to cancel story telling operation + * GNUNET_PSYC_channel_story_tell_cancel() anymore. + * @param cls Closure for the callbacks. + * @return Handle to cancel story telling operation. */ struct GNUNET_PSYC_Story * -GNUNET_PSYC_member_story_tell (struct GNUNET_PSYC_Member *member, - uint64_t start, - uint64_t end, - void (*finish_cb)(void *), - void *finish_cb_cls); +GNUNET_PSYC_channel_story_tell (struct GNUNET_PSYC_Channel *channel, + uint64_t start_message_id, + uint64_t end_message_id, + GNUNET_PSYC_Method method, + GNUNET_PSYC_FinishCallback *finish_cb, + void *cls); /** - * Abort story telling. This function must not be called from within - * method handlers (as given to 'GNUNET_PSYC_member_join') of the - * member. + * Abort story telling. + * + * This function must not be called from within method handlers (as given to + * GNUNET_PSYC_slave_join()) of the slave. * - * @param story story telling operation to stop + * @param story Story telling operation to stop. */ void -GNUNET_PSYC_member_story_tell_cancel (struct GNUNET_PSYC_Story *story); +GNUNET_PSYC_channel_story_tell_cancel (struct GNUNET_PSYC_Story *story); /** - * Call the given state callback on all matching states in the channel - * state. The callback is invoked synchronously on all matching - * states (as the state is fully replicated in the library in this - * process; channel states should be small, large data is to be passed - * as streaming data to methods). + * Handle for a state query operation. + */ +struct GNUNET_PSYC_StateQuery; + + +/** + * Retrieve the best matching channel state variable. * - * @param member membership handle - * @param state_name name of the state to query (full name - * might be longer, this is only the prefix that must match) - * @param cb function to call on the matching state values - * @param cb_cls closure for 'cb' - * @return message ID for which the state was returned (last seen - * message ID) + * If the requested variable name is not present in the state, the nearest + * less-specific name is matched; for example, requesting "_a_b" will match "_a" + * if "_a_b" does not exist. + * + * @param channel Channel handle. + * @param full_name Full name of the requested variable, the actual variable + * returned might have a shorter name.. + * @param cb Function called once when a matching state variable is found. + * Not called if there's no matching state variable. + * @param cb_cls Closure for the callbacks. + * @return Handle that can be used to cancel the query operation. */ -uint64_t -GNUNET_PSYC_member_state_get (struct GNUNET_PSYC_Member *member, - const char *state_name, - GNUNET_PSYC_StateCallback cb, - void *cb_cls); +struct GNUNET_PSYC_StateQuery * +GNUNET_PSYC_channel_state_get (struct GNUNET_PSYC_Channel *channel, + const char *full_name, + GNUNET_PSYC_StateCallback cb, + void *cb_cls); /** - * Obtain the current value of a variable. This function should only - * be called during a GNUNET_PSYC_Method invocation (and even then - * only if the origin is the state owner), as variables are only valid - * for the duration of a method invocation. If this function is - * called outside of the scope of such a method invocation, it will - * return NULL. + * Return all channel state variables whose name matches a given prefix. + * + * A name matches if it starts with the given @a name_prefix, thus requesting + * the empty prefix ("") will match all values; requesting "_a_b" will also + * return values stored under "_a_b_c". * - * FIXME: do variables have a hierarchy as well? If so, - * we should document the lookup semantics. + * The @a state_cb is invoked on all matching state variables asynchronously, as + * the state is stored in and retrieved from the PSYCstore, * - * @param member membership handle - * @param variable_name name of the variable to query - * @param return_value_size set to number of bytes in variable, - * needed as variables might contain binary data and - * might also not be 0-terminated; set to 0 on errors - * @return NULL on error, pointer to variable state otherwise + * @param channel Channel handle. + * @param name_prefix Prefix of the state variable name to match. + * @param cb Function to call with the matching state variables. + * @param cb_cls Closure for the callbacks. + * @return Handle that can be used to cancel the query operation. */ -const char * -GNUNET_PSYC_member_variable_get (struct GNUNET_PSYC_Member *member, - const char *variable_name, - size_t *return_value_size); +struct GNUNET_PSYC_StateQuery * +GNUNET_PSYC_channel_state_get_prefix (struct GNUNET_PSYC_Channel *channel, + const char *name_prefix, + GNUNET_PSYC_StateCallback cb, + void *cb_cls); /** - * Leave a multicast group. Will terminate the connection to the PSYC - * service. Polite clients should first explicitly send a 'leave' - * request (via 'GNUNET_PSYC_member_send_to_host'). This function - * must not be called on a 'member' that was obtained from - * GNUNET_PSYC_channel_get_group. + * Cancel a state query operation. * - * @param member membership handle + * @param query Handle for the operation to cancel. */ void -GNUNET_PSYC_member_leave (struct GNUNET_PSYC_Member *member); - +GNUNET_PSYC_channel_state_get_cancel (struct GNUNET_PSYC_StateQuery *query); #if 0 /* keep Emacsens' auto-indent happy */