aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabor X Toth <*@tg-x.net>2016-01-06 12:28:47 +0000
committerGabor X Toth <*@tg-x.net>2016-01-06 12:28:47 +0000
commit80d2de6cdc4d253c7fbc6a4bc067d856aab9cca9 (patch)
tree86e33af618c53b82afd0cb4855d7da595fcd5acd
parent7d1dfe26d99376a341bb150eb89ba717bb883077 (diff)
psyc/social: local join flag; social service: leave place, save _file
-rw-r--r--src/include/gnunet_psyc_service.h14
-rw-r--r--src/include/gnunet_social_service.h138
-rw-r--r--src/psyc/gnunet-service-psyc.c34
-rw-r--r--src/psyc/psyc.h4
-rw-r--r--src/psyc/psyc_api.c9
-rw-r--r--src/psyc/test_psyc.c4
-rw-r--r--src/psycstore/psyc_util_lib.c7
-rw-r--r--src/social/gnunet-service-social.c179
-rw-r--r--src/social/social.conf.in2
-rw-r--r--src/social/social.h4
-rw-r--r--src/social/social_api.c55
-rw-r--r--src/social/test_social.c15
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);