diff options
author | Gabor X Toth <*@tg-x.net> | 2016-01-06 12:28:47 +0000 |
---|---|---|
committer | Gabor X Toth <*@tg-x.net> | 2016-01-06 12:28:47 +0000 |
commit | 80d2de6cdc4d253c7fbc6a4bc067d856aab9cca9 (patch) | |
tree | 86e33af618c53b82afd0cb4855d7da595fcd5acd | |
parent | 7d1dfe26d99376a341bb150eb89ba717bb883077 (diff) |
psyc/social: local join flag; social service: leave place, save _file
-rw-r--r-- | src/include/gnunet_psyc_service.h | 14 | ||||
-rw-r--r-- | src/include/gnunet_social_service.h | 138 | ||||
-rw-r--r-- | src/psyc/gnunet-service-psyc.c | 34 | ||||
-rw-r--r-- | src/psyc/psyc.h | 4 | ||||
-rw-r--r-- | src/psyc/psyc_api.c | 9 | ||||
-rw-r--r-- | src/psyc/test_psyc.c | 4 | ||||
-rw-r--r-- | src/psycstore/psyc_util_lib.c | 7 | ||||
-rw-r--r-- | src/social/gnunet-service-social.c | 179 | ||||
-rw-r--r-- | src/social/social.conf.in | 2 | ||||
-rw-r--r-- | src/social/social.h | 4 | ||||
-rw-r--r-- | src/social/social_api.c | 55 | ||||
-rw-r--r-- | src/social/test_social.c | 15 |
12 files changed, 392 insertions, 73 deletions
diff --git a/src/include/gnunet_psyc_service.h b/src/include/gnunet_psyc_service.h index 80404f8373..2bbe8cdd66 100644 --- a/src/include/gnunet_psyc_service.h +++ b/src/include/gnunet_psyc_service.h @@ -887,6 +887,19 @@ typedef void int is_admitted, const struct GNUNET_PSYC_Message *join_msg); +/** + * Flags for GNUNET_PSYC_slave_join() + */ +enum GNUNET_PSYC_SlaveJoinFlags +{ + GNUNET_PSYC_SLAVE_JOIN_NONE = 0, + + /** + * Local join for history access, no network connection is established. + */ + GNUNET_PSYC_SLAVE_JOIN_LOCAL = 1, +}; + /** * Join a PSYC channel. @@ -926,6 +939,7 @@ 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_EcdsaPrivateKey *slave_key, + enum GNUNET_PSYC_SlaveJoinFlags flags, const struct GNUNET_PeerIdentity *origin, uint32_t relay_count, const struct GNUNET_PeerIdentity *relays, diff --git a/src/include/gnunet_social_service.h b/src/include/gnunet_social_service.h index 47062fdafd..bde3dbcebd 100644 --- a/src/include/gnunet_social_service.h +++ b/src/include/gnunet_social_service.h @@ -119,22 +119,66 @@ typedef void /** - * Notification about a place entered. + * Entry status of a place. + */ +enum GNUNET_SOCIAL_PlaceState +{ + /** + * Place was once entered but left since. + */ + GNUNET_SOCIAL_PLACE_STATE_ARCHIVED = 0, + /** + * Place is entered but not subscribed. + */ + GNUNET_SOCIAL_PLACE_STATE_ENTERED = 1, + /** + * Place is entered and subscribed. + */ + GNUNET_SOCIAL_PLACE_STATE_SUBSCRIBED = 2, +}; + + +/** + * Notification about a home. + * + * @param cls + * Closure. + * @param hconn + * Host connection, to be used with GNUNET_SOCIAL_host_enter_reconnect() + * @param ego + * Ego used to enter the place. + * @param place_pub_key + * Public key of the place. + * @param place_state + * @see enum GNUNET_SOCIAL_PlaceState */ typedef void (*GNUNET_SOCIAL_AppHostPlaceCallback) (void *cls, struct GNUNET_SOCIAL_HostConnection *hconn, struct GNUNET_SOCIAL_Ego *ego, - const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key); + const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key, + enum GNUNET_SOCIAL_PlaceState place_state); /** -h * Notification about a place entered. + * Notification about a place. + * + * @param cls + * Closure. + * @param gconn + * Guest connection, to be used with GNUNET_SOCIAL_guest_enter_reconnect() + * @param ego + * Ego used to enter the place. + * @param place_pub_key + * Public key of the place. + * @param place_state + * @see enum GNUNET_SOCIAL_PlaceState */ typedef void (*GNUNET_SOCIAL_AppGuestPlaceCallback) (void *cls, struct GNUNET_SOCIAL_GuestConnection *gconn, struct GNUNET_SOCIAL_Ego *ego, - const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key); + const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key, + enum GNUNET_SOCIAL_PlaceState place_state); /** @@ -719,6 +763,47 @@ GNUNET_SOCIAL_host_announce_cancel (struct GNUNET_SOCIAL_Announcement *a); /** + * Allow relaying messages from guests matching a given @a method_prefix. + * + * @param host + * The host. + * @param method_prefix + * Method prefix to allow. + */ +void +GNUNET_SOCIAL_host_relay_allow_method (struct GNUNET_SOCIAL_Host *host, + const char *method_prefix); + + +/** + * Allow relaying changes to objects of the place. + * + * Only applies to messages with an allowed method name. + * @see GNUNET_SCOIAL_host_relay_allow_method() + * + * @param host + * The host. + * @param object_prefix + * Object prefix to allow modifying. + */ +void +GNUNET_SOCIAL_host_relay_allow_method (struct GNUNET_SOCIAL_Host *host, + const char *object_prefix); + + +/** + * Stop relaying messages from guests. + * + * Remove all allowed relay rules. + * + * + * + */ +void +GNUNET_SOCIAL_host_relay_stop (struct GNUNET_SOCIAL_Host *host); + + +/** * Obtain handle for a hosted place. * * The returned handle can be used to access the place API. @@ -824,17 +909,30 @@ typedef void /** * Request entry to a place as a guest. * - * @param cfg Configuration to contact the social service. - * @param ego Identity of the guest. - * @param crypto_address Public key of the place to enter. - * @param origin Peer identity of the origin of the underlying multicast group. - * @param relay_count Number of elements in the @a relays array. - * @param relays Relays for the underlying multicast group. - * @param method_name Method name for the message. - * @param env Environment containing variables for the message, or NULL. - * @param data Payload for the message to give to the enter callback. - * @param data_size Number of bytes in @a data. - * @param slicer Slicer to use for processing incoming requests from guests. + * @param app + * Application handle. + * @param ego + * Identity of the guest. + * @param place_pub_key + * Public key of the place to enter. + * @param flags + * Flags for the entry. + * @param origin + * Peer identity of the origin of the underlying multicast group. + * @param relay_count + * Number of elements in the @a relays array. + * @param relays + * Relays for the underlying multicast group. + * @param method_name + * Method name for the message. + * @param env + * Environment containing variables for the message, or NULL. + * @param data + * Payload for the message to give to the enter callback. + * @param data_size + * Number of bytes in @a data. + * @param slicer + * Slicer to use for processing incoming requests from guests. * * @return NULL on errors, otherwise handle for the guest. */ @@ -842,21 +940,22 @@ struct GNUNET_SOCIAL_Guest * GNUNET_SOCIAL_guest_enter (const struct GNUNET_SOCIAL_App *app, const struct GNUNET_SOCIAL_Ego *ego, const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key, + enum GNUNET_PSYC_SlaveJoinFlags flags, const struct GNUNET_PeerIdentity *origin, uint32_t relay_count, const struct GNUNET_PeerIdentity *relays, const struct GNUNET_PSYC_Message *entry_msg, struct GNUNET_SOCIAL_Slicer *slicer, GNUNET_SOCIAL_GuestEnterCallback local_enter_cb, - GNUNET_SOCIAL_EntryDecisionCallback entry_decision_cb, + GNUNET_SOCIAL_EntryDecisionCallback entry_dcsn_cb, void *cls); /** * Request entry to a place by name as a guest. * - * @param cfg - * Configuration to contact the social service. + * @param app + * Application handle. * @param ego * Identity of the guest. * @param gns_name @@ -896,6 +995,8 @@ GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_SOCIAL_App *app, * @param gconn * Guest connection handle. * @see GNUNET_SOCIAL_app_connect() & GNUNET_SOCIAL_AppGuestPlaceCallback() + * @param flags + * Flags for the entry. * @param slicer * Slicer to use for processing incoming requests from guests. * @param local_enter_cb @@ -907,6 +1008,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, GNUNET_SOCIAL_GuestEnterCallback local_enter_cb, void *cls); diff --git a/src/psyc/gnunet-service-psyc.c b/src/psyc/gnunet-service-psyc.c index e710b41a53..e9727c4858 100644 --- a/src/psyc/gnunet-service-psyc.c +++ b/src/psyc/gnunet-service-psyc.c @@ -409,6 +409,11 @@ struct Slave * Maximum request ID for this channel. */ uint64_t max_request_id; + + /** + * Join flags. + */ + enum GNUNET_PSYC_SlaveJoinFlags join_flags; }; @@ -812,7 +817,8 @@ mcast_recv_join_decision (void *cls, int is_admitted, client_send_msg (chn, &dcsn->header); - if (GNUNET_YES == is_admitted) + if (GNUNET_YES == is_admitted + && ! (GNUNET_PSYC_SLAVE_JOIN_LOCAL & slv->join_flags)) { chn->is_ready = GNUNET_YES; } @@ -1189,11 +1195,15 @@ fragment_queue_insert (struct Channel *chn, * Send fragments of a message in order to client, after all modifiers arrived * from multicast. * - * @param chn Channel. - * @param msg_id ID of the message @a fragq belongs to. - * @param fragq Fragment queue of the message. - * @param drop Drop message without delivering to client? - * #GNUNET_YES or #GNUNET_NO. + * @param chn + * Channel. + * @param msg_id + * ID of the message @a fragq belongs to. + * @param fragq + * Fragment queue of the message. + * @param drop + * Drop message without delivering to client? + * #GNUNET_YES or #GNUNET_NO. */ static void fragment_queue_run (struct Channel *chn, uint64_t msg_id, @@ -1739,7 +1749,7 @@ client_recv_slave_join (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_CRYPTO_ecdsa_key_get_public (&req->slave_key, &slv_pub_key); GNUNET_CRYPTO_hash (&slv_pub_key, sizeof (slv_pub_key), &slv_pub_key_hash); - GNUNET_CRYPTO_hash (&req->channel_key, sizeof (req->channel_key), &pub_key_hash); + GNUNET_CRYPTO_hash (&req->channel_pub_key, sizeof (req->channel_pub_key), &pub_key_hash); struct GNUNET_CONTAINER_MultiHashMap * chn_slv = GNUNET_CONTAINER_multihashmap_get (channel_slaves, &pub_key_hash); @@ -1758,6 +1768,7 @@ client_recv_slave_join (void *cls, struct GNUNET_SERVER_Client *client, slv->pub_key_hash = slv_pub_key_hash; slv->origin = req->origin; slv->relay_count = ntohl (req->relay_count); + slv->join_flags = ntohl (req->flags); const struct GNUNET_PeerIdentity * relays = (const struct GNUNET_PeerIdentity *) &req[1]; @@ -1791,7 +1802,7 @@ client_recv_slave_join (void *cls, struct GNUNET_SERVER_Client *client, chn = &slv->chn; chn->is_master = GNUNET_NO; - chn->pub_key = req->channel_key; + chn->pub_key = req->channel_pub_key; chn->pub_key_hash = pub_key_hash; channel_init (chn); @@ -1822,7 +1833,12 @@ client_recv_slave_join (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_SERVER_notification_context_unicast (nc, client, &res.header, GNUNET_NO); - if (NULL == slv->member) + if (GNUNET_PSYC_SLAVE_JOIN_LOCAL & slv->join_flags) + { + mcast_recv_join_decision (slv, GNUNET_YES, + NULL, 0, NULL, NULL); + } + else if (NULL == slv->member) { slv->member = GNUNET_MULTICAST_member_join (cfg, &chn->pub_key, &slv->priv_key, diff --git a/src/psyc/psyc.h b/src/psyc/psyc.h index f89d170a5d..cc7475df78 100644 --- a/src/psyc/psyc.h +++ b/src/psyc/psyc.h @@ -93,12 +93,14 @@ struct SlaveJoinRequest uint32_t relay_count GNUNET_PACKED; - struct GNUNET_CRYPTO_EddsaPublicKey channel_key; + struct GNUNET_CRYPTO_EddsaPublicKey channel_pub_key; struct GNUNET_CRYPTO_EcdsaPrivateKey slave_key; struct GNUNET_PeerIdentity origin; + uint32_t flags GNUNET_PACKED; + /* Followed by struct GNUNET_PeerIdentity relays[relay_count] */ /* Followed by struct GNUNET_MessageHeader join_msg */ diff --git a/src/psyc/psyc_api.c b/src/psyc/psyc_api.c index 9392deeef8..8152fc47f7 100644 --- a/src/psyc/psyc_api.c +++ b/src/psyc/psyc_api.c @@ -847,7 +847,8 @@ GNUNET_PSYC_master_get_channel (struct GNUNET_PSYC_Master *master) * notification on failure (as the channel may simply take days to approve, * and disapproval is simply being ignored). * - * @param cfg Configuration to use. + * @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 @@ -873,8 +874,9 @@ GNUNET_PSYC_master_get_channel (struct GNUNET_PSYC_Master *master) */ 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, uint32_t relay_count, const struct GNUNET_PeerIdentity *relays, @@ -898,10 +900,11 @@ GNUNET_PSYC_slave_join (const struct GNUNET_CONFIGURATION_Handle *cfg, req = GNUNET_malloc (sizeof (*req) + relay_size + join_msg_size); req->header.size = htons (sizeof (*req) + relay_size + join_msg_size); req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN); - req->channel_key = *channel_key; + req->channel_pub_key = *channel_pub_key; req->slave_key = *slave_key; req->origin = *origin; req->relay_count = htonl (relay_count); + req->flags = htonl (flags); if (0 < relay_size) memcpy (&req[1], relays, relay_size); diff --git a/src/psyc/test_psyc.c b/src/psyc/test_psyc.c index 1ce9074d57..f167e26974 100644 --- a/src/psyc/test_psyc.c +++ b/src/psyc/test_psyc.c @@ -843,7 +843,9 @@ slave_join (int t) struct GNUNET_PSYC_Message * join_msg = GNUNET_PSYC_message_create ("_request_join", env, "some data", 9); - slv = GNUNET_PSYC_slave_join (cfg, &channel_pub_key, slave_key, &origin, 0, NULL, + slv = GNUNET_PSYC_slave_join (cfg, &channel_pub_key, slave_key, + GNUNET_PSYC_SLAVE_JOIN_NONE, + &origin, 0, NULL, &slave_message_cb, &slave_message_part_cb, &slave_connect_cb, &join_decision_cb, NULL, join_msg); diff --git a/src/psycstore/psyc_util_lib.c b/src/psycstore/psyc_util_lib.c index 9e6b1b7700..e87d6106d3 100644 --- a/src/psycstore/psyc_util_lib.c +++ b/src/psycstore/psyc_util_lib.c @@ -1264,12 +1264,15 @@ GNUNET_PSYC_message_parse (const struct GNUNET_PSYC_MessageHeader *msg, struct GNUNET_PSYC_ReceiveHandle * recv = GNUNET_PSYC_receive_create (NULL, parse_message_part_cb, &cls); - GNUNET_PSYC_receive_message (recv, msg); + 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_SYSERR; + : GNUNET_NO; } diff --git a/src/social/gnunet-service-social.c b/src/social/gnunet-service-social.c index b7cf1f8567..ec4b18d0b8 100644 --- a/src/social/gnunet-service-social.c +++ b/src/social/gnunet-service-social.c @@ -95,6 +95,12 @@ static struct GNUNET_CONTAINER_MultiHashMap *places; static struct GNUNET_CONTAINER_MultiHashMap *apps_places; /** + * Application subscriptions per place. + * H(place_pub_key) -> H(app_id) + */ +static struct GNUNET_CONTAINER_MultiHashMap *places_apps; + +/** * Connected applications. * H(app_id) -> struct Application */ @@ -108,7 +114,7 @@ static struct GNUNET_CONTAINER_MultiHashMap *egos; /** * Directory for storing social data. - * Default: ~/.local/share/gnunet/social + * Default: $GNUNET_DATA_HOME/social */ static char *dir_social; @@ -223,6 +229,11 @@ struct Place */ struct GNUNET_HashCode ego_pub_hash; + uint64_t file_message_id; + uint64_t file_fragment_offset; + uint64_t file_size; + uint64_t file_offset; + /** * Last message ID received for the place. * 0 if there is no such message. @@ -326,6 +337,10 @@ struct Guest */ struct GNUNET_PSYC_JoinDecisionMessage *join_dcsn; + /** + * Join flags for the PSYC service. + */ + enum GNUNET_PSYC_SlaveJoinFlags join_flags; }; @@ -713,6 +728,51 @@ psyc_recv_join_dcsn (void *cls, place_send_msg (&gst->plc, &dcsn->header); } +/** + * Save _file data to disk. + */ +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 void *data, uint16_t data_size) +{ + if (plc->file_message_id != message_id) + { + if (0 != fragment_offset) + { + /* unexpected message ID */ + GNUNET_break (0); + return; + } + + /* new file */ + plc->file_offset = 0; + } + + struct GNUNET_CRYPTO_HashAsciiEncoded place_pub_hash_ascii; + memcpy (&place_pub_hash_ascii.encoding, + GNUNET_h2s_full (&plc->pub_key_hash), sizeof (place_pub_hash_ascii)); + + char *filename = NULL; + GNUNET_asprintf (&filename, "%s%c%s%c%s%c%" PRIu64, + dir_social, DIR_SEPARATOR, + "files", DIR_SEPARATOR, + place_pub_hash_ascii.encoding, DIR_SEPARATOR, + message_id); + GNUNET_DISK_directory_create_for_file (filename); + struct GNUNET_DISK_FileHandle * + fh = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE, + GNUNET_DISK_PERM_USER_READ + | GNUNET_DISK_PERM_USER_WRITE); + GNUNET_free (filename); + + GNUNET_DISK_file_seek (fh, plc->file_offset, GNUNET_DISK_SEEK_SET); + GNUNET_DISK_file_write (fh, data, data_size); + GNUNET_DISK_file_close (fh); + plc->file_offset += data_size; +} + /** * Called when a PSYC master or slave receives a message. @@ -731,9 +791,33 @@ psyc_recv_message (void *cls, plc, ntohs (msg->header.size), str); GNUNET_free (str); - place_send_msg (plc, &msg->header); + /* process message */ + /* FIXME: use slicer */ + const char *method_name = NULL; + struct GNUNET_ENV_Environment *env = GNUNET_ENV_environment_create (); + const void *data = NULL; + uint16_t data_size = 0; + + if (GNUNET_SYSERR == GNUNET_PSYC_message_parse (msg, &method_name, env, &data, &data_size)) + { + GNUNET_break (0); + } + else + { + char *method_found = strstr (method_name, "_file"); + if (method_name == method_found) + { + method_found += strlen ("_file"); + if (('\0' == *method_found) || ('_' == *method_found)) + { + psyc_recv_file (plc, msg, flags, message_id, GNUNET_ntohll (msg->fragment_offset), + method_name, env, data, data_size); + } + } + } + GNUNET_ENV_environment_destroy (env); - /* FIXME: further processing */ + place_send_msg (plc, &msg->header); } @@ -838,13 +922,39 @@ app_place_add (const char *app_id, if (GNUNET_SYSERR == place_add (ereq)) return GNUNET_SYSERR; - if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (app_places, &ego_place_pub_hash, - NULL, 0)) + if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (app_places, &ego_place_pub_hash, NULL, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) { GNUNET_break (0); return GNUNET_SYSERR; } + struct GNUNET_HashCode place_pub_hash; + GNUNET_CRYPTO_hash (&ereq->place_pub_key, sizeof (ereq->place_pub_key), &place_pub_hash); + + struct GNUNET_CONTAINER_MultiHashMap * + place_apps = GNUNET_CONTAINER_multihashmap_get (places_apps, &place_pub_hash); + if (NULL == place_apps) + { + place_apps = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); + if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (places_apps, &place_pub_hash, place_apps, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) + { + GNUNET_break (0); + } + } + + + size_t app_id_size = strlen (app_id); + void *app_id_value = GNUNET_malloc (app_id_size); + memcpy (app_id_value, app_id, app_id_size); + + if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (place_apps, &app_id_hash, app_id_value, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) + { + GNUNET_break (0); + } + return GNUNET_OK; } @@ -948,6 +1058,19 @@ app_place_remove (const char *app_id, if (NULL != app_places) GNUNET_CONTAINER_multihashmap_remove (app_places, &place_pub_hash, NULL); + struct GNUNET_CONTAINER_MultiHashMap * + place_apps = GNUNET_CONTAINER_multihashmap_get (places_apps, &place_pub_hash); + if (NULL != place_apps) + { + void *app_id_value = GNUNET_CONTAINER_multihashmap_get (place_apps, &app_id_hash); + if (NULL != app_id_value) + { + GNUNET_free (app_id_value); + GNUNET_CONTAINER_multihashmap_remove_all (place_apps, &app_id_hash); + } + } + + int ret = unlink (app_place_filename); GNUNET_free (app_place_filename); if (0 != ret) @@ -1187,6 +1310,8 @@ guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst) memcpy (gst->relays, relays, relay_size); } + gst->join_flags = ntohl (greq->flags); + struct Place *plc = &gst->plc; place_init (plc); plc->is_host = GNUNET_NO; @@ -1208,9 +1333,12 @@ guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst) GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); gst->slave = GNUNET_PSYC_slave_join (cfg, &plc->pub_key, &plc->ego_key, - &gst->origin, gst->relay_count, gst->relays, - &psyc_recv_message, NULL, &psyc_slave_connected, - &psyc_recv_join_dcsn, gst, join_msg); + gst->join_flags, &gst->origin, + gst->relay_count, gst->relays, + &psyc_recv_message, NULL, + &psyc_slave_connected, + &psyc_recv_join_dcsn, + gst, join_msg); gst->plc.channel = GNUNET_PSYC_slave_get_channel (gst->slave); ret = GNUNET_YES; } @@ -1442,6 +1570,8 @@ app_notify_place (struct GNUNET_MessageHeader *msg, struct AppPlaceMessage amsg; amsg.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_APP_PLACE); amsg.header.size = htons (sizeof (amsg)); + // FIXME: also notify about not entered places + amsg.place_state = GNUNET_SOCIAL_PLACE_STATE_ENTERED; switch (ntohs (msg->type)) { @@ -1492,7 +1622,7 @@ app_notify_ego (struct Ego *ego, struct GNUNET_SERVER_Client *client) int -app_place_entry (void *cls, const struct GNUNET_HashCode *key, void *value) +app_place_entry_notify (void *cls, const struct GNUNET_HashCode *key, void *value) { struct GNUNET_MessageHeader * msg = GNUNET_CONTAINER_multihashmap_get (places, key); @@ -1539,7 +1669,7 @@ client_recv_app_connect (void *cls, struct GNUNET_SERVER_Client *client, struct GNUNET_CONTAINER_MultiHashMap * app_places = GNUNET_CONTAINER_multihashmap_get (apps_places, &app_id_hash); if (NULL != app_places) - GNUNET_CONTAINER_multihashmap_iterate (app_places, app_place_entry, client); + GNUNET_CONTAINER_multihashmap_iterate (app_places, app_place_entry_notify, client); struct ClientListItem *cli = GNUNET_new (struct ClientListItem); cli->client = client; @@ -1585,6 +1715,14 @@ client_recv_app_detach (void *cls, struct GNUNET_SERVER_Client *client, } +int +app_places_entry_remove (void *cls, const struct GNUNET_HashCode *key, void *value) +{ + app_place_remove (value, cls); + return GNUNET_YES; +} + + /** * Handle application detach request. */ @@ -1597,8 +1735,18 @@ client_recv_place_leave (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_assert (NULL != ctx); struct Place *plc = ctx->plc; - /* Disconnect all clients connected to the place */ + /* FIXME: remove all app subscriptions and leave this place */ + + struct GNUNET_CONTAINER_MultiHashMap * + place_apps = GNUNET_CONTAINER_multihashmap_get (places_apps, &plc->pub_key_hash); + if (NULL != place_apps) + { + GNUNET_CONTAINER_multihashmap_iterate (place_apps, app_places_entry_remove, &plc->pub_key); + } + /* FIXME: disconnect from the network, but keep local connection for history access */ + + /* Disconnect all clients connected to the place */ struct ClientListItem *cli = plc->clients_head, *next; while (NULL != cli) { @@ -2832,7 +2980,7 @@ file_ego_place_load (void *cls, const char *place_filename) * * @param dir_ego * Data directory of an application ego. - * e.g. ~/.local/share/gnunet/social/apps/$app_id/$ego_pub_hash_str/ + * $GNUNET_DATA_HOME/social/apps/$app_id/$ego_pub_hash_str/ */ int scan_app_ego_dir (void *cls, const char *dir_ego) @@ -2851,7 +2999,7 @@ scan_app_ego_dir (void *cls, const char *dir_ego) * * @param dir_app * Data directory of an application. - * e.g. ~/.local/share/gnunet/social/apps/$app_id/ + * $GNUNET_DATA_HOME/social/apps/$app_id/ */ int scan_app_dir (void *cls, const char *dir_app) @@ -2941,6 +3089,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, apps = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); places = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO); apps_places = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO); + places_apps = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO); core = GNUNET_CORE_connect (cfg, NULL, core_connected, NULL, NULL, NULL, GNUNET_NO, NULL, GNUNET_NO, NULL); @@ -2950,11 +3099,11 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, stats = GNUNET_STATISTICS_create ("social", cfg); if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (cfg, "social", "SOCIAL_DATA_DIR", + GNUNET_CONFIGURATION_get_value_filename (cfg, "social", "DATA_HOME", &dir_social)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "social", "SOCIAL_DATA_DIR"); + "social", "DATA_HOME"); GNUNET_break (0); return; } diff --git a/src/social/social.conf.in b/src/social/social.conf.in index e52318bc32..9149b65a16 100644 --- a/src/social/social.conf.in +++ b/src/social/social.conf.in @@ -10,3 +10,5 @@ UNIX_MATCH_GID = YES HOSTNAME = localhost ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; + +DATA_HOME = $GNUNET_DATA_HOME/social diff --git a/src/social/social.h b/src/social/social.h index 651338c510..b797a89ace 100644 --- a/src/social/social.h +++ b/src/social/social.h @@ -114,6 +114,8 @@ struct GuestEnterRequest struct GNUNET_PeerIdentity origin; + uint32_t flags GNUNET_PACKED; + /* Followed by char *app_id */ /* Followed by struct GNUNET_PeerIdentity relays[relay_count] */ /* Followed by struct GNUNET_MessageHeader *join_msg */ @@ -236,6 +238,8 @@ struct AppPlaceMessage struct GNUNET_CRYPTO_EddsaPublicKey place_pub_key; uint8_t is_host; + + uint8_t place_state; }; diff --git a/src/social/social_api.c b/src/social/social_api.c index 6c85ba2948..3d5e9853ff 100644 --- a/src/social/social_api.c +++ b/src/social/social_api.c @@ -1558,14 +1558,14 @@ app_recv_place (void *cls, struct GNUNET_SOCIAL_HostConnection *hconn = GNUNET_malloc (sizeof (*hconn)); hconn->app = app; hconn->plc_msg = *pmsg; - app->host_cb (app->cb_cls, hconn, ego, &pmsg->place_pub_key); + app->host_cb (app->cb_cls, hconn, ego, &pmsg->place_pub_key, pmsg->place_state); } else { struct GNUNET_SOCIAL_GuestConnection *gconn = GNUNET_malloc (sizeof (*gconn)); gconn->app = app; gconn->plc_msg = *pmsg; - app->guest_cb (app->cb_cls, gconn, ego, &pmsg->place_pub_key); + app->guest_cb (app->cb_cls, gconn, ego, &pmsg->place_pub_key, pmsg->place_state); } } @@ -1717,8 +1717,8 @@ guest_cleanup (void *cls) * A place is created upon first entering, and it is active until permanently * left using GNUNET_SOCIAL_host_leave(). * - * @param cfg - * Configuration to contact the social service. + * @param app + * Application handle. * @param ego * Identity of the host. * @param place_key @@ -1808,7 +1808,7 @@ GNUNET_SOCIAL_host_enter (const struct GNUNET_SOCIAL_App *app, * * @return Handle for the host. */ -struct GNUNET_SOCIAL_Host * + struct GNUNET_SOCIAL_Host * GNUNET_SOCIAL_host_enter_reconnect (struct GNUNET_SOCIAL_HostConnection *hconn, struct GNUNET_SOCIAL_Slicer *slicer, GNUNET_SOCIAL_HostEnterCallback enter_cb, @@ -2202,20 +2202,34 @@ guest_enter_request_create (const char *app_id, return greq; } + /** * Request entry to a place as a guest. * - * @param cfg Configuration to contact the social service. - * @param ego Identity of the guest. - * @param crypto_address Public key of the place to enter. - * @param origin Peer identity of the origin of the underlying multicast group. - * @param relay_count Number of elements in the @a relays array. - * @param relays Relays for the underlying multicast group. - * @param method_name Method name for the message. - * @param env Environment containing variables for the message, or NULL. - * @param data Payload for the message to give to the enter callback. - * @param data_size Number of bytes in @a data. - * @param slicer Slicer to use for processing incoming requests from guests. + * @param app + * Application handle. + * @param ego + * Identity of the guest. + * @param place_pub_key + * Public key of the place to enter. + * @param flags + * Flags for the entry. + * @param origin + * Peer identity of the origin of the underlying multicast group. + * @param relay_count + * Number of elements in the @a relays array. + * @param relays + * Relays for the underlying multicast group. + * @param method_name + * Method name for the message. + * @param env + * Environment containing variables for the message, or NULL. + * @param data + * Payload for the message to give to the enter callback. + * @param data_size + * Number of bytes in @a data. + * @param slicer + * Slicer to use for processing incoming requests from guests. * * @return NULL on errors, otherwise handle for the guest. */ @@ -2223,6 +2237,7 @@ struct GNUNET_SOCIAL_Guest * GNUNET_SOCIAL_guest_enter (const struct GNUNET_SOCIAL_App *app, const struct GNUNET_SOCIAL_Ego *ego, const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key, + enum GNUNET_PSYC_SlaveJoinFlags flags, const struct GNUNET_PeerIdentity *origin, uint32_t relay_count, const struct GNUNET_PeerIdentity *relays, @@ -2263,8 +2278,8 @@ GNUNET_SOCIAL_guest_enter (const struct GNUNET_SOCIAL_App *app, /** * Request entry to a place by name as a guest. * - * @param cfg - * Configuration to contact the social service. + * @param app + * Application handle. * @param ego * Identity of the guest. * @param gns_name @@ -2356,6 +2371,8 @@ GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_SOCIAL_App *app, * @param gconn * Guest connection handle. * @see GNUNET_SOCIAL_app_connect() & GNUNET_SOCIAL_AppGuestPlaceCallback() + * @param flags + * Flags for the entry. * @param slicer * Slicer to use for processing incoming requests from guests. * @param local_enter_cb @@ -2367,6 +2384,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, GNUNET_SOCIAL_GuestEnterCallback local_enter_cb, void *cls) @@ -2381,6 +2399,7 @@ GNUNET_SOCIAL_guest_enter_reconnect (struct GNUNET_SOCIAL_GuestConnection *gconn greq->header.size = htons (greq_size); greq->ego_pub_key = gconn->plc_msg.ego_pub_key; greq->place_pub_key = gconn->plc_msg.place_pub_key; + greq->flags = htonl (flags); memcpy (&greq[1], gconn->app->id, app_id_size); diff --git a/src/social/test_social.c b/src/social/test_social.c index 38710cd1a0..1fb9cc5688 100644 --- a/src/social/test_social.c +++ b/src/social/test_social.c @@ -402,7 +402,8 @@ static void app_recv_host (void *cls, struct GNUNET_SOCIAL_HostConnection *hconn, struct GNUNET_SOCIAL_Ego *ego, - const struct GNUNET_CRYPTO_EddsaPublicKey *host_pub_key) + const struct GNUNET_CRYPTO_EddsaPublicKey *host_pub_key, + enum GNUNET_SOCIAL_PlaceState place_state) { struct GNUNET_HashCode host_pub_hash; GNUNET_CRYPTO_hash (host_pub_key, sizeof (*host_pub_key), &host_pub_hash); @@ -424,9 +425,10 @@ app_recv_host (void *cls, static void app_recv_guest (void *cls, - struct GNUNET_SOCIAL_GuestConnection *gconn, - struct GNUNET_SOCIAL_Ego *ego, - const struct GNUNET_CRYPTO_EddsaPublicKey *guest_pub_key) + struct GNUNET_SOCIAL_GuestConnection *gconn, + struct GNUNET_SOCIAL_Ego *ego, + const struct GNUNET_CRYPTO_EddsaPublicKey *guest_pub_key, + enum GNUNET_SOCIAL_PlaceState place_state) { struct GNUNET_HashCode guest_pub_hash; GNUNET_CRYPTO_hash (guest_pub_key, sizeof (*guest_pub_key), &guest_pub_hash); @@ -439,8 +441,8 @@ app_recv_guest (void *cls, { if (0 == memcmp (&place_pub_key, guest_pub_key, sizeof (*guest_pub_key))) { - gst = GNUNET_SOCIAL_guest_enter_reconnect (gconn, guest_slicer, - guest_reconnected, NULL); + gst = GNUNET_SOCIAL_guest_enter_reconnect (gconn, GNUNET_PSYC_SLAVE_JOIN_NONE, + guest_slicer, guest_reconnected, NULL); } } } @@ -1122,6 +1124,7 @@ guest_enter () emsg->data, emsg->data_size); gst = GNUNET_SOCIAL_guest_enter (app, guest_ego, &place_pub_key, + GNUNET_PSYC_SLAVE_JOIN_NONE, &this_peer, 0, NULL, emsg->msg, guest_slicer, guest_recv_local_enter, guest_recv_entry_decision, NULL); |