[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r36672 - in gnunet/src: include social
From: |
gnunet |
Subject: |
[GNUnet-SVN] r36672 - in gnunet/src: include social |
Date: |
Wed, 18 Nov 2015 23:13:28 +0100 |
Author: tg
Date: 2015-11-18 23:13:27 +0100 (Wed, 18 Nov 2015)
New Revision: 36672
Modified:
gnunet/src/include/gnunet_protocols.h
gnunet/src/include/gnunet_social_service.h
gnunet/src/social/gnunet-service-social.c
gnunet/src/social/social.h
gnunet/src/social/social_api.c
gnunet/src/social/test_social.c
Log:
social: store/load entered places & notify clients about them
Modified: gnunet/src/include/gnunet_protocols.h
===================================================================
--- gnunet/src/include/gnunet_protocols.h 2015-11-18 15:23:23 UTC (rev
36671)
+++ gnunet/src/include/gnunet_protocols.h 2015-11-18 22:13:27 UTC (rev
36672)
@@ -2616,6 +2616,10 @@
/** C->S->P: decision about an entry request */
#define GNUNET_MESSAGE_TYPE_SOCIAL_ENTRY_DECISION 846
+/** C->S: listen for places */
+#define GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LISTEN 850
+
+
/*******************************************************************************
* X-VINE DHT messages
******************************************************************************/
Modified: gnunet/src/include/gnunet_social_service.h
===================================================================
--- gnunet/src/include/gnunet_social_service.h 2015-11-18 15:23:23 UTC (rev
36671)
+++ gnunet/src/include/gnunet_social_service.h 2015-11-18 22:13:27 UTC (rev
36672)
@@ -35,6 +35,7 @@
#endif
#endif
+#include <stdint.h>
#include "gnunet_util_lib.h"
#include "gnunet_env_lib.h"
#include "gnunet_identity_service.h"
@@ -73,7 +74,6 @@
*/
struct GNUNET_SOCIAL_Slicer;
-
/**
* Function called upon receiving a message indicating a call to a @e method.
*
@@ -982,8 +982,8 @@
* Ego.
* @param name
* The name for the PKEY record to put in the zone.
- * @param pub_key
- * Public key to add.
+ * @param nym_pub_key
+ * Public key of nym to add.
* @param expiration_time
* Expiration time of the record, use 0 to remove the record.
* @param result_cb
@@ -995,12 +995,77 @@
GNUNET_SOCIAL_zone_add_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg,
const struct GNUNET_IDENTITY_Ego *ego,
const char *name,
- const struct GNUNET_CRYPTO_EcdsaPublicKey
*pub_key,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey
*nym_pub_key,
struct GNUNET_TIME_Absolute expiration_time,
GNUNET_NAMESTORE_ContinuationWithStatus result_cb,
void *result_cls);
+/**
+ * Handle for place notifications.
+ */
+struct GNUNET_SOCIAL_PlaceListenHandle;
+
+
+/**
+ * Notification about a place entered as host.
+ */
+typedef void
+(*GNUNET_SOCIAL_PlaceNotifyHostCallback) (void *cls,
+ const struct
GNUNET_CRYPTO_EddsaPrivateKey *place_key,
+ enum GNUNET_PSYC_Policy policy);
+
+
+/**
+ * Notification about a place entered as guest.
+ */
+typedef void
+(*GNUNET_SOCIAL_PlaceNotifyGuestCallback) (void *cls,
+ const struct
GNUNET_CRYPTO_EddsaPublicKey *place_key,
+ const struct GNUNET_PeerIdentity
*origin,
+ uint32_t relay_count,
+ const struct GNUNET_PeerIdentity
*relays,
+ const struct GNUNET_PSYC_Message
*entry_msg);
+
+
+/**
+ * Start listening for entered places as host or guest.
+ *
+ * The @notify_host and @notify_guest functions are
+ * initially called with the full list of entered places,
+ * then later each time a new place is entered.
+ *
+ * @param cfg
+ * Configuration.
+ * @param ego
+ * Listen for places of this ego.
+ * @param notify_host
+ * Function to notify about a place entered as host.
+ * @param notify_guest
+ * Function to notify about a place entered as guest..
+ * @param notify_cls
+ * Closure for the callbacks.
+ *
+ * @return Handle that can be used to stop listening.
+ */
+struct GNUNET_SOCIAL_PlaceListenHandle *
+GNUNET_SOCIAL_place_listen_start (const struct GNUNET_CONFIGURATION_Handle
*cfg,
+ const struct GNUNET_IDENTITY_Ego *ego,
+ GNUNET_SOCIAL_PlaceNotifyHostCallback
notify_host,
+ GNUNET_SOCIAL_PlaceNotifyGuestCallback
notify_guest,
+ void *notify_cls);
+
+
+/**
+ * Stop listening for entered places.
+ *
+ * @param h
+ * Listen handle.
+ */
+void
+GNUNET_SOCIAL_place_listen_stop (struct GNUNET_SOCIAL_PlaceListenHandle *h);
+
+
#if 0 /* keep Emacsens' auto-indent happy */
{
#endif
Modified: gnunet/src/social/gnunet-service-social.c
===================================================================
--- gnunet/src/social/gnunet-service-social.c 2015-11-18 15:23:23 UTC (rev
36671)
+++ gnunet/src/social/gnunet-service-social.c 2015-11-18 22:13:27 UTC (rev
36672)
@@ -54,24 +54,41 @@
/**
* All connected hosts.
- * Place's pub_key_hash -> struct Host
+ * H(place_pub_key) -> struct Host
*/
static struct GNUNET_CONTAINER_MultiHashMap *hosts;
/**
* All connected guests.
- * Place's pub_key_hash -> struct Guest
+ * H(place_pub_key) -> struct Guest
*/
static struct GNUNET_CONTAINER_MultiHashMap *guests;
/**
* Connected guests per place.
- * Place's pub_key_hash -> Guest's pub_key -> struct Guest
+ * H(place_pub_key) -> Guest's pub_key -> struct Guest
*/
static struct GNUNET_CONTAINER_MultiHashMap *place_guests;
+/**
+ * Places entered as host or guest.
+ * H(place_pub_key) -> struct HostEnterRequest OR struct GuestEnterRequest
+ */
+static struct GNUNET_CONTAINER_MultiHashMap *places_entered;
/**
+ * Place listener clients.
+ * H(ego_pub_key) -> struct PlaceListener
+ */
+static struct GNUNET_CONTAINER_MultiHashMap *place_listeners;
+
+/**
+ * Directory for storing places.
+ */
+static char *dir_places;
+
+
+/**
* Message fragment transmission queue.
*/
struct FragmentTransmitQueue
@@ -275,6 +292,9 @@
};
+/**
+ * Context for host/guest client.
+ */
struct Client
{
/**
@@ -287,9 +307,21 @@
* by this client.
*/
struct MessageTransmitQueue *tmit_msg;
+
+ /**
+ * Ego key for listener clients;
+ */
+ struct GNUNET_CRYPTO_EcdsaPrivateKey ego_key;
};
+struct PlaceListener
+{
+ struct ClientListItem *clients_head;
+ struct ClientListItem *clients_tail;
+};
+
+
struct OperationClosure
{
struct GNUNET_SERVER_Client *client;
@@ -419,6 +451,9 @@
}
struct Place *plc = ctx->plc;
+ if (NULL == plc)
+ return; // place listener client, nothing to do
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"%p Client (%s) disconnected from place %s\n",
plc, (GNUNET_YES == plc->is_host) ? "host" : "guest",
@@ -623,36 +658,144 @@
/**
- * Handle a connecting client entering a place as host.
+ * Add place to places_entered hash map.
+ *
+ * @param ego_pub_hash
+ * H(ego_pub_key)
+ * @param place_pub_hash
+ * H(place_pub_key)
+ * @param msg
+ * Entry message.
+ *
+ * @return Return value of GNUNET_CONTAINER_multihashmap_put ()
*/
+static int
+place_add (const struct GNUNET_HashCode *ego_pub_hash,
+ const struct GNUNET_HashCode *place_pub_hash,
+ const struct GNUNET_MessageHeader *msg)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Adding place to hashmap:\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ " ego_pub_hash = %s\n", GNUNET_h2s (ego_pub_hash));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ " place_pub_hash = %s\n", GNUNET_h2s (place_pub_hash));
+
+ struct GNUNET_CONTAINER_MultiHashMap *
+ ego_places = GNUNET_CONTAINER_multihashmap_get (places_entered,
ego_pub_hash);
+ if (NULL == ego_places)
+ {
+ ego_places = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
+ GNUNET_CONTAINER_multihashmap_put (places_entered, ego_pub_hash,
ego_places,
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+ }
+
+ struct GNUNET_MessageHeader *msg_old, *msg_new;
+ if (NULL != (msg_old = GNUNET_CONTAINER_multihashmap_get (ego_places,
place_pub_hash)))
+ {
+ GNUNET_free (msg_old);
+ GNUNET_CONTAINER_multihashmap_remove_all (ego_places, place_pub_hash);
+ }
+
+ uint16_t msg_size = ntohs (msg->size);
+ msg_new = GNUNET_malloc (msg_size);
+ memcpy (msg_new, msg, msg_size);
+ int ret = GNUNET_CONTAINER_multihashmap_put (ego_places, place_pub_hash,
msg_new,
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+ if (GNUNET_OK != ret)
+ GNUNET_break (0);
+ return ret;
+}
+
+
+/**
+ * Save place entry message to disk.
+ *
+ * @param ego_key
+ * Private key of ego.
+ * @param place_pub_hash
+ * Hash of public key of place.
+ * @param msg
+ * Entry message.
+ */
static void
-client_recv_host_enter (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *msg)
+place_save (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ego_key,
+ const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub,
+ const struct GNUNET_MessageHeader *msg)
{
- const struct HostEnterRequest *req
- = (const struct HostEnterRequest *) msg;
+ if (NULL == dir_places)
+ return;
- struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
- struct GNUNET_HashCode pub_key_hash;
+ struct GNUNET_HashCode place_pub_hash;
+ GNUNET_CRYPTO_hash (place_pub, sizeof (place_pub), &place_pub_hash);
- GNUNET_CRYPTO_eddsa_key_get_public (&req->place_key, &pub_key);
- GNUNET_CRYPTO_hash (&pub_key, sizeof (pub_key), &pub_key_hash);
+ struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub;
+ struct GNUNET_HashCode ego_pub_hash;
+ GNUNET_CRYPTO_ecdsa_key_get_public (ego_key, &ego_pub);
+ GNUNET_CRYPTO_hash (&ego_pub, sizeof (ego_pub), &ego_pub_hash);
- struct Host *
- hst = GNUNET_CONTAINER_multihashmap_get (hosts, &pub_key_hash);
- struct Place *plc;
+ place_add (&ego_pub_hash, &place_pub_hash, msg);
+ char *ego_pub_hash_str = GNUNET_malloc (sizeof (struct
GNUNET_CRYPTO_HashAsciiEncoded) + 1);
+ char *place_pub_hash_str = GNUNET_malloc (sizeof (struct
GNUNET_CRYPTO_HashAsciiEncoded) + 1);
+ memcpy (ego_pub_hash_str, GNUNET_h2s_full (&ego_pub_hash), sizeof (struct
GNUNET_CRYPTO_HashAsciiEncoded));
+ memcpy (place_pub_hash_str, GNUNET_h2s_full (&place_pub_hash), sizeof
(struct GNUNET_CRYPTO_HashAsciiEncoded));
+
+ char *filename = GNUNET_malloc (strlen (dir_places) + 1
+ + sizeof (struct
GNUNET_CRYPTO_HashAsciiEncoded) + 1
+ + sizeof (struct
GNUNET_CRYPTO_HashAsciiEncoded) + 1);
+ GNUNET_asprintf (&filename,
+ "%s%s%s%s%s",
+ dir_places, DIR_SEPARATOR_STR,
+ ego_pub_hash_str, DIR_SEPARATOR_STR,
+ place_pub_hash_str);
+
+ GNUNET_DISK_directory_create_for_file (filename);
+ if (GNUNET_DISK_fn_write (filename, msg, ntohs (msg->size),
+ GNUNET_DISK_PERM_USER_READ |
GNUNET_DISK_PERM_USER_WRITE) < 0)
+ {
+ GNUNET_break (0);
+ }
+
+ GNUNET_free (ego_pub_hash_str);
+ GNUNET_free (place_pub_hash_str);
+ GNUNET_free (filename);
+}
+
+
+/**
+ * Enter place as host.
+ *
+ * @param req
+ * Entry request.
+ * @param[out] ret_hst
+ * Returned Host struct.
+ *
+ * @return #GNUNET_YES if the host entered the place just now,
+ * #GNUNET_NO if the place is already entered.
+ */
+static int
+host_enter (const struct HostEnterRequest *hreq, struct Host **ret_hst)
+{
+ int ret = GNUNET_NO;
+ struct GNUNET_CRYPTO_EddsaPublicKey place_pub;
+ struct GNUNET_HashCode place_pub_hash;
+
+ GNUNET_CRYPTO_eddsa_key_get_public (&hreq->place_key, &place_pub);
+ GNUNET_CRYPTO_hash (&place_pub, sizeof (place_pub), &place_pub_hash);
+
+ struct Host *hst = GNUNET_CONTAINER_multihashmap_get (hosts,
&place_pub_hash);
if (NULL == hst)
{
hst = GNUNET_new (struct Host);
- hst->policy = ntohl (req->policy);
- hst->priv_key = req->place_key;
+ hst->policy = ntohl (hreq->policy);
+ hst->priv_key = hreq->place_key;
hst->join_reqs = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
- plc = &hst->plc;
+ struct Place *plc = &hst->plc;
plc->is_host = GNUNET_YES;
- plc->pub_key = pub_key;
- plc->pub_key_hash = pub_key_hash;
+ plc->pub_key = place_pub;
+ plc->pub_key_hash = place_pub_hash;
place_init (plc);
GNUNET_CONTAINER_multihashmap_put (hosts, &plc->pub_key_hash, plc,
@@ -662,11 +805,37 @@
&psyc_recv_join_request,
&psyc_recv_message, NULL, hst);
hst->plc.channel = GNUNET_PSYC_master_get_channel (hst->master);
+ ret = GNUNET_YES;
}
- else
+
+ if (NULL != ret_hst)
+ *ret_hst = hst;
+ return ret;
+}
+
+
+/**
+ * Handle a connecting client entering a place as host.
+ */
+static void
+client_recv_host_enter (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *msg)
+{
+ const struct HostEnterRequest *hreq
+ = (const struct HostEnterRequest *) msg;
+ struct Place *plc;
+ struct Host *hst;
+
+ switch (host_enter (hreq, &hst))
{
+ case GNUNET_YES:
plc = &hst->plc;
+ break;
+ case GNUNET_NO:
+ {
+ plc = &hst->plc;
+
struct GNUNET_PSYC_CountersResultMessage res;
res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK);
res.header.size = htons (sizeof (res));
@@ -676,8 +845,18 @@
GNUNET_SERVER_notification_context_add (nc, client);
GNUNET_SERVER_notification_context_unicast (nc, client, &res.header,
GNUNET_NO);
+ break;
}
+ case GNUNET_SYSERR:
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ struct GNUNET_CRYPTO_EddsaPublicKey place_pub;
+ GNUNET_CRYPTO_eddsa_key_get_public (&hreq->place_key, &place_pub);
+
+ place_save (&hreq->host_key, &place_pub, msg);
+
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"%p Client connected as host to place %s.\n",
hst, GNUNET_h2s (&plc->pub_key_hash));
@@ -694,74 +873,78 @@
/**
- * Handle a connecting client entering a place as guest.
+ * Enter place as guest.
+ *
+ * @param req
+ * Entry request.
+ * @param[out] ret_gst
+ * Returned Guest struct.
+ *
+ * @return #GNUNET_YES if the guest entered the place just now,
+ * #GNUNET_NO if the place is already entered.
*/
-static void
-client_recv_guest_enter (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *msg)
+static int
+guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst)
{
- const struct GuestEnterRequest *req
- = (const struct GuestEnterRequest *) msg;
- uint16_t req_size = ntohs (req->header.size);
+ int ret = GNUNET_NO;
+ uint16_t greq_size = ntohs (greq->header.size);
struct GNUNET_CRYPTO_EcdsaPublicKey gst_pub_key;
- struct GNUNET_HashCode pub_key_hash, gst_pub_key_hash;
-
- GNUNET_CRYPTO_ecdsa_key_get_public (&req->guest_key, &gst_pub_key);
+ struct GNUNET_HashCode place_pub_hash, gst_pub_key_hash;
+ GNUNET_CRYPTO_ecdsa_key_get_public (&greq->guest_key, &gst_pub_key);
GNUNET_CRYPTO_hash (&gst_pub_key, sizeof (gst_pub_key), &gst_pub_key_hash);
- GNUNET_CRYPTO_hash (&req->place_key, sizeof (req->place_key), &pub_key_hash);
+ GNUNET_CRYPTO_hash (&greq->place_key, sizeof (greq->place_key),
&place_pub_hash);
struct GNUNET_CONTAINER_MultiHashMap *
- plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests, &pub_key_hash);
+ plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests,
&place_pub_hash);
struct Guest *gst = NULL;
struct Place *plc;
if (NULL != plc_gst)
- {
gst = GNUNET_CONTAINER_multihashmap_get (plc_gst, &gst_pub_key_hash);
- }
+
if (NULL == gst || NULL == gst->slave)
{
gst = GNUNET_new (struct Guest);
- gst->priv_key = req->guest_key;
+ gst->priv_key = greq->guest_key;
gst->pub_key = gst_pub_key;
gst->pub_key_hash = gst_pub_key_hash;
- gst->origin = req->origin;
- gst->relay_count = ntohl (req->relay_count);
+ gst->origin = greq->origin;
+ gst->relay_count = ntohl (greq->relay_count);
- const struct GNUNET_PeerIdentity *
- relays = (const struct GNUNET_PeerIdentity *) &req[1];
+ const struct GNUNET_PeerIdentity *relays = NULL;
uint16_t relay_size = gst->relay_count * sizeof (*relays);
+ if (0 < relay_size)
+ relays = (const struct GNUNET_PeerIdentity *) &greq[1];
struct GNUNET_PSYC_Message *join_msg = NULL;
uint16_t join_msg_size = 0;
- if (sizeof (*req) + relay_size + sizeof (struct GNUNET_MessageHeader)
- <= req_size)
+ if (sizeof (*greq) + relay_size + sizeof (struct GNUNET_MessageHeader)
+ <= greq_size)
{
join_msg = (struct GNUNET_PSYC_Message *)
- (((char *) &req[1]) + relay_size);
+ (((char *) &greq[1]) + relay_size);
join_msg_size = ntohs (join_msg->header.size);
}
- if (sizeof (*req) + relay_size + join_msg_size != req_size)
+ if (sizeof (*greq) + relay_size + join_msg_size != greq_size)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"%u + %u + %u != %u\n",
- sizeof (*req), relay_size, join_msg_size, req_size);
+ sizeof (*greq), relay_size, join_msg_size, greq_size);
GNUNET_break (0);
- GNUNET_SERVER_client_disconnect (client);
GNUNET_free (gst);
- return;
+ return GNUNET_SYSERR;
}
if (0 < gst->relay_count)
{
gst->relays = GNUNET_malloc (relay_size);
- memcpy (gst->relays, &req[1], relay_size);
+ memcpy (gst->relays, &greq[1], relay_size);
}
plc = &gst->plc;
plc->is_host = GNUNET_NO;
- plc->pub_key = req->place_key;
- plc->pub_key_hash = pub_key_hash;
+ plc->pub_key = greq->place_key;
+ plc->pub_key_hash = place_pub_hash;
place_init (plc);
if (NULL == plc_gst)
@@ -771,9 +954,9 @@
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
}
(void) GNUNET_CONTAINER_multihashmap_put (plc_gst, &gst->pub_key_hash, gst,
-
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
(void) GNUNET_CONTAINER_multihashmap_put (guests, &plc->pub_key_hash, gst,
-
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
gst->slave
= GNUNET_PSYC_slave_join (cfg, &plc->pub_key, &gst->priv_key,
&gst->origin, gst->relay_count, gst->relays,
@@ -780,11 +963,37 @@
&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;
}
- else
+
+ if (NULL != ret_gst)
+ *ret_gst = gst;
+ return ret;
+}
+
+
+/**
+ * Handle a connecting client entering a place as guest.
+ */
+static void
+client_recv_guest_enter (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *msg)
+{
+ const struct GuestEnterRequest *
+ greq = (const struct GuestEnterRequest *) msg;
+ struct Guest *gst = NULL;
+ struct Place *plc = NULL;
+
+ switch (guest_enter (greq, &gst))
{
+ case GNUNET_YES:
plc = &gst->plc;
+ break;
+ case GNUNET_NO:
+ {
+ plc = &gst->plc;
+
struct GNUNET_PSYC_CountersResultMessage res;
res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK);
res.header.size = htons (sizeof (res));
@@ -801,11 +1010,18 @@
&gst->join_dcsn->header,
GNUNET_NO);
}
+ break;
}
+ case GNUNET_SYSERR:
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ place_save (&greq->guest_key, &greq->place_key, msg);
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"%p Client connected as guest to place %s.\n",
- gst, GNUNET_h2s (&plc->pub_key_hash));
+ gst, GNUNET_h2s (&gst->plc.pub_key_hash));
struct ClientListItem *cli = GNUNET_new (struct ClientListItem);
cli->client = client;
@@ -818,6 +1034,94 @@
}
+void
+place_notify (struct GNUNET_MessageHeader *msg,
+ struct GNUNET_SERVER_Client *client)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%p Sending place notification of type %u to client.\n",
+ client, ntohs (msg->type));
+
+ uint16_t msg_size = ntohs (msg->size);
+ struct GNUNET_CRYPTO_EcdsaPublicKey place_pub;
+
+ switch (ntohs (msg->type))
+ {
+ case GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER:
+ if (msg_size < sizeof (struct HostEnterRequest))
+ return;
+ struct HostEnterRequest *hreq = (struct HostEnterRequest *) msg;
+ GNUNET_CRYPTO_ecdsa_key_get_public (&hreq->host_key, &place_pub);
+ break;
+
+ case GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER:
+ if (msg_size < sizeof (struct GuestEnterRequest))
+ return;
+ struct GuestEnterRequest *greq = (struct GuestEnterRequest *) msg;
+ GNUNET_CRYPTO_ecdsa_key_get_public (&greq->guest_key, &place_pub);
+ break;
+
+ default:
+ return;
+ }
+
+ GNUNET_SERVER_notification_context_add (nc, client);
+ GNUNET_SERVER_notification_context_unicast (nc, client, msg,
+ GNUNET_NO);
+}
+
+
+int
+map_entry_place (void *cls, const struct GNUNET_HashCode *key, void *value)
+{
+ place_notify (value, cls);
+ return GNUNET_YES;
+}
+
+
+/**
+ * Handle a connecting client listening for entered places.
+ */
+static void
+client_recv_place_listen (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *msg)
+{
+ const struct PlaceListenRequest *req
+ = (const struct PlaceListenRequest *) msg;
+
+ struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub;
+ struct GNUNET_HashCode ego_pub_hash;
+
+ GNUNET_CRYPTO_ecdsa_key_get_public (&req->ego_key, &ego_pub);
+ GNUNET_CRYPTO_hash (&ego_pub, sizeof (ego_pub), &ego_pub_hash);
+
+ struct GNUNET_CONTAINER_MultiHashMap *
+ ego_places = GNUNET_CONTAINER_multihashmap_get (places_entered,
&ego_pub_hash);
+ if (NULL != ego_places)
+ GNUNET_CONTAINER_multihashmap_iterate (ego_places, map_entry_place,
client);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "%p Client connected to listen for entered places of ego %s.\n",
+ NULL, GNUNET_h2s (&ego_pub_hash));
+
+ struct ClientListItem *cli = GNUNET_new (struct ClientListItem);
+ cli->client = client;
+ struct PlaceListener *pl = GNUNET_CONTAINER_multihashmap_get
(place_listeners,
+ &ego_pub_hash);
+ if (NULL == pl) {
+ pl = GNUNET_malloc (sizeof (*pl));
+ (void) GNUNET_CONTAINER_multihashmap_put (place_listeners, &ego_pub_hash,
pl,
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+ }
+ GNUNET_CONTAINER_DLL_insert (pl->clients_head, pl->clients_tail, cli);
+
+ struct Client *ctx = GNUNET_new (struct Client);
+ ctx->ego_key = req->ego_key;
+ GNUNET_SERVER_client_set_user_context (client, ctx);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
struct JoinDecisionClosure
{
int32_t is_admitted;
@@ -1777,10 +2081,94 @@
{ &client_recv_state_get, NULL,
GNUNET_MESSAGE_TYPE_PSYC_STATE_GET_PREFIX, 0 },
+ { &client_recv_place_listen, NULL,
+ GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LISTEN, 0 },
+
{ NULL, NULL, 0, 0 }
};
+int
+file_place_load (void *cls, const char *filename)
+{
+ uint64_t fsize = 0;
+ if (GNUNET_OK !=
+ GNUNET_DISK_file_size (filename, &fsize, GNUNET_YES, GNUNET_YES)
+ || fsize < sizeof (struct HostEnterRequest))
+ return GNUNET_OK;
+
+ struct GNUNET_MessageHeader *msg = GNUNET_malloc (fsize);
+ ssize_t rsize = GNUNET_DISK_fn_read (filename, msg, fsize);
+ if (rsize < 0 || (size_t) rsize < sizeof (*msg))
+ return GNUNET_OK;
+
+ uint16_t msg_size = ntohs (msg->size);
+ struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub;
+ struct GNUNET_CRYPTO_EddsaPublicKey place_pub;
+
+ switch (ntohs (msg->type))
+ {
+ case GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER:
+ if (msg_size < sizeof (struct HostEnterRequest))
+ return GNUNET_OK;
+ struct HostEnterRequest *hreq = (struct HostEnterRequest *) msg;
+ GNUNET_CRYPTO_ecdsa_key_get_public (&hreq->host_key, &ego_pub);
+ GNUNET_CRYPTO_eddsa_key_get_public (&hreq->place_key, &place_pub);
+
+ host_enter (hreq, NULL);
+ break;
+
+ case GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER:
+ if (msg_size < sizeof (struct GuestEnterRequest))
+ return GNUNET_OK;
+ struct GuestEnterRequest *greq = (struct GuestEnterRequest *) msg;
+ GNUNET_CRYPTO_ecdsa_key_get_public (&greq->guest_key, &ego_pub);
+ place_pub = greq->place_key;
+
+ guest_enter (greq, NULL);
+ break;
+
+ default:
+ return GNUNET_OK;
+ }
+
+ struct GNUNET_HashCode ego_pub_hash, place_pub_hash;
+ GNUNET_CRYPTO_hash (&ego_pub, sizeof (ego_pub), &ego_pub_hash);
+ GNUNET_CRYPTO_hash (&place_pub, sizeof (place_pub), &place_pub_hash);
+
+ place_add (&ego_pub_hash, &place_pub_hash, msg);
+ return GNUNET_OK;
+}
+
+
+int
+load_places_of_ego (void *cls, const char *dir_ego)
+{
+ if (GNUNET_YES != GNUNET_DISK_directory_test (dir_ego, GNUNET_YES))
+ return GNUNET_OK;
+
+ GNUNET_DISK_directory_scan (dir_ego, file_place_load, NULL);
+ return GNUNET_OK;
+}
+
+
+void
+load_places ()
+{
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (cfg, "social", "PLACES_DIR",
+ &dir_places))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "social",
"PLACES_DIR");
+ GNUNET_break (0);
+ return;
+ }
+
+ places_entered = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO);
+ GNUNET_DISK_directory_scan (dir_places, load_places_of_ego, NULL);
+}
+
+
/**
* Initialize the PSYC service.
*
@@ -1797,6 +2185,9 @@
hosts = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
guests = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
place_guests = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
+ place_listeners = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
+ load_places ();
+
nc = GNUNET_SERVER_notification_context_create (server, 1);
GNUNET_SERVER_add_handlers (server, handlers);
GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
Modified: gnunet/src/social/social.h
===================================================================
--- gnunet/src/social/social.h 2015-11-18 15:23:23 UTC (rev 36671)
+++ gnunet/src/social/social.h 2015-11-18 22:13:27 UTC (rev 36672)
@@ -24,7 +24,7 @@
* @author Gabor X Toth
*/
-#ifndef SOCIAL_H
+#ifndef SOCIAL_H
#define SOCIAL_H
#include "platform.h"
@@ -85,9 +85,19 @@
};
+struct PlaceListenRequest
+{
+ /**
+ * Type: GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LISTEN
+ */
+ struct GNUNET_MessageHeader header;
+
+ struct GNUNET_CRYPTO_EcdsaPrivateKey ego_key;
+};
+
+
/**** service -> library ****/
-
#if REMOVE
struct NymEnterRequest
{
Modified: gnunet/src/social/social_api.c
===================================================================
--- gnunet/src/social/social_api.c 2015-11-18 15:23:23 UTC (rev 36671)
+++ gnunet/src/social/social_api.c 2015-11-18 22:13:27 UTC (rev 36672)
@@ -1,4 +1,4 @@
- /*
+/*
* This file is part of GNUnet
* Copyright (C) 2013 Christian Grothoff (and other contributing authors)
*
@@ -190,6 +190,19 @@
/**
+ * Handle for place notifications.
+ */
+struct GNUNET_SOCIAL_PlaceListenHandle
+{
+ struct GNUNET_SOCIAL_Place plc;
+
+ GNUNET_SOCIAL_PlaceNotifyHostCallback notify_host;
+ GNUNET_SOCIAL_PlaceNotifyGuestCallback notify_guest;
+ void *notify_cls;
+};
+
+
+/**
* Hash map of all nyms.
* pub_key_hash -> struct GNUNET_SOCIAL_Nym *
*/
@@ -1275,19 +1288,19 @@
char *str;
const struct GNUNET_PSYC_JoinRequestMessage *
req = (const struct GNUNET_PSYC_JoinRequestMessage *) msg;
- const struct GNUNET_PSYC_Message *entry_msg = NULL;
+ const struct GNUNET_PSYC_Message *join_msg = NULL;
do
{
- if (sizeof (*req) + sizeof (*entry_msg) <= ntohs (req->header.size))
+ if (sizeof (*req) + sizeof (*join_msg) <= ntohs (req->header.size))
{
- entry_msg = (struct GNUNET_PSYC_Message *) &req[1];
+ join_msg = (struct GNUNET_PSYC_Message *) &req[1];
LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Received entry_msg of type %u and size %u.\n",
- ntohs (entry_msg->header.type), ntohs (entry_msg->header.size));
+ "Received join_msg of type %u and size %u.\n",
+ ntohs (join_msg->header.type), ntohs (join_msg->header.size));
env = GNUNET_ENV_environment_create ();
- entry_pmsg = GNUNET_PSYC_message_header_create_from_psyc (entry_msg);
+ entry_pmsg = GNUNET_PSYC_message_header_create_from_psyc (join_msg);
if (GNUNET_OK != GNUNET_PSYC_message_parse (entry_pmsg, &method_name,
env,
&data, &data_size))
{
@@ -1350,6 +1363,56 @@
}
+static void
+notify_recv_place_host (void *cls,
+ struct GNUNET_CLIENT_MANAGER_Connection *client,
+ const struct GNUNET_MessageHeader *msg)
+{
+ struct GNUNET_SOCIAL_PlaceListenHandle *
+ pl = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*pl));
+ if (NULL == pl->notify_host)
+ return;
+
+ struct HostEnterRequest *
+ hreq = (struct HostEnterRequest *) msg;
+
+ pl->notify_host (pl->notify_cls, &hreq->place_key, ntohl (hreq->policy));
+}
+
+
+static void
+notify_recv_place_guest (void *cls,
+ struct GNUNET_CLIENT_MANAGER_Connection *client,
+ const struct GNUNET_MessageHeader *msg)
+{
+ struct GNUNET_SOCIAL_PlaceListenHandle *
+ pl = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*pl));
+ if (NULL == pl->notify_guest)
+ return;
+
+ struct GuestEnterRequest *
+ greq = (struct GuestEnterRequest *) msg;
+ uint16_t greq_size = ntohs (greq->header.size);
+
+ const struct GNUNET_PeerIdentity *relays = NULL;
+ uint16_t relay_count = ntohs (greq->relay_count);
+ uint16_t relay_size = relay_count * sizeof (*relays);
+ if (0 < relay_size)
+ relays = (const struct GNUNET_PeerIdentity *) &greq[1];
+ struct GNUNET_PSYC_Message *join_msg = NULL;
+
+ if (sizeof (*greq) + relay_size + sizeof (struct GNUNET_MessageHeader)
+ <= greq_size)
+ {
+ join_msg = (struct GNUNET_PSYC_Message *)
+ (((char *) &greq[1]) + relay_size);
+ }
+
+ pl->notify_guest (pl->notify_cls, &greq->place_key, &greq->origin,
+ relay_count, relays, join_msg);
+}
+
+
static struct GNUNET_CLIENT_MANAGER_MessageHandler host_handlers[] =
{
{ host_recv_enter_ack, NULL,
@@ -1426,6 +1489,21 @@
};
+
+static struct GNUNET_CLIENT_MANAGER_MessageHandler notify_handlers[] =
+{
+ { notify_recv_place_host, NULL,
+ GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER,
+ sizeof (struct HostEnterRequest), GNUNET_NO },
+
+ { notify_recv_place_guest, NULL,
+ GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER,
+ sizeof (struct GuestEnterRequest), GNUNET_YES },
+
+ { NULL, NULL, 0, 0, GNUNET_NO }
+};
+
+
static void
place_cleanup (struct GNUNET_SOCIAL_Place *plc)
{
@@ -1533,13 +1611,6 @@
GNUNET_free (ephemeral_key);
}
- req->header.size = htons (sizeof (*req));
- req->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER);
- req->policy = policy;
- req->place_key = hst->place_key;
- req->host_key = plc->ego_key;
-
- plc->connect_msg = (struct GNUNET_MessageHeader *) req;
plc->cfg = cfg;
plc->is_host = GNUNET_YES;
plc->slicer = slicer;
@@ -1565,7 +1636,15 @@
NULL, host_recv_notice_place_leave_eom,
hst);
hst->recv = GNUNET_PSYC_receive_create (NULL, slicer_message, hst->slicer);
+ req->header.size = htons (sizeof (*req));
+ req->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER);
+ req->policy = policy;
+ req->place_key = hst->place_key;
+ req->host_key = plc->ego_key;
+
+ plc->connect_msg = (struct GNUNET_MessageHeader *) req;
place_send_connect_msg (plc);
+
return hst;
}
@@ -1972,7 +2051,7 @@
const struct GNUNET_PeerIdentity *origin,
uint32_t relay_count,
const struct GNUNET_PeerIdentity *relays,
- const struct GNUNET_PSYC_Message *entry_msg,
+ const struct GNUNET_PSYC_Message *join_msg,
struct GNUNET_SOCIAL_Slicer *slicer,
GNUNET_SOCIAL_GuestEnterCallback local_enter_cb,
GNUNET_SOCIAL_EntryDecisionCallback entry_dcsn_cb,
@@ -1999,7 +2078,7 @@
struct GuestEnterRequest *
req = guest_enter_request_create (&plc->ego_key, place_key, origin,
- relay_count, relays, entry_msg);
+ relay_count, relays, join_msg);
plc->connect_msg = &req->header;
place_send_connect_msg (plc);
return gst;
@@ -2200,7 +2279,7 @@
void
GNUNET_SOCIAL_guest_talk_cancel (struct GNUNET_SOCIAL_TalkRequest *tr)
{
- GNUNET_PSYC_transmit_cancel ((struct GNUNET_PSYC_TransmitHandle *) tr);
+ GNUNET_PSYC_transmit_cancel ( (struct GNUNET_PSYC_TransmitHandle *) tr);
}
@@ -2501,8 +2580,8 @@
* Ego.
* @param name
* The name for the PKEY record to put in the zone.
- * @param pub_key
- * Public key to add.
+ * @param nym_pub_key
+ * Public key of nym to add.
* @param expiration_time
* Expiration time of the record, use 0 to remove the record.
* @param result_cb
@@ -2514,7 +2593,7 @@
GNUNET_SOCIAL_zone_add_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg,
const struct GNUNET_IDENTITY_Ego *ego,
const char *name,
- const struct GNUNET_CRYPTO_EcdsaPublicKey
*pub_key,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey
*nym_pub_key,
struct GNUNET_TIME_Absolute expiration_time,
GNUNET_NAMESTORE_ContinuationWithStatus result_cb,
void *result_cls)
@@ -2526,8 +2605,8 @@
rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY;
rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
rd.expiration_time = expiration_time.abs_value_us;
- rd.data = pub_key;
- rd.data_size = sizeof (*pub_key);
+ rd.data = nym_pub_key;
+ rd.data_size = sizeof (*nym_pub_key);
GNUNET_NAMESTORE_records_store (namestore,
GNUNET_IDENTITY_ego_get_private_key (ego),
@@ -2535,4 +2614,68 @@
}
+/**
+ * Start listening for entered places as host or guest.
+ *
+ * The @notify_host and @notify_guest functions are
+ * initially called with the full list of entered places,
+ * then later each time a new place is entered.
+ *
+ * @param cfg
+ * Configuration.
+ * @param ego
+ * Listen for places of this ego.
+ * @param notify_host
+ * Function to notify about a place entered as host.
+ * @param notify_guest
+ * Function to notify about a place entered as guest..
+ * @param notify_cls
+ * Closure for the callbacks.
+ *
+ * @return Handle that can be used to stop listening.
+ */
+struct GNUNET_SOCIAL_PlaceListenHandle *
+GNUNET_SOCIAL_place_listen_start (const struct GNUNET_CONFIGURATION_Handle
*cfg,
+ const struct GNUNET_IDENTITY_Ego *ego,
+ GNUNET_SOCIAL_PlaceNotifyHostCallback
notify_host,
+ GNUNET_SOCIAL_PlaceNotifyGuestCallback
notify_guest,
+ void *notify_cls)
+{
+ struct GNUNET_SOCIAL_PlaceListenHandle *pl = GNUNET_malloc (sizeof *pl);
+ pl->notify_host = notify_host;
+ pl->notify_guest = notify_guest;
+ pl->notify_cls = notify_cls;
+
+ struct GNUNET_SOCIAL_Place *plc = &pl->plc;
+
+ plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego);
+ plc->cfg = cfg;
+ plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social",
+ notify_handlers);
+ GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, pl, sizeof (*pl));
+
+ struct PlaceListenRequest *req = GNUNET_malloc (sizeof (*req));
+ req->ego_key = plc->ego_key;
+ req->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LISTEN);
+ req->header.size = htons (sizeof (*req));
+
+ plc->connect_msg = (struct GNUNET_MessageHeader *) req;
+ place_send_connect_msg (plc);
+
+ return pl;
+}
+
+
+/**
+ * Stop listening for entered places.
+ *
+ * @param pl
+ * Place listen handle.
+ */
+void
+GNUNET_SOCIAL_place_listen_stop (struct GNUNET_SOCIAL_PlaceListenHandle *pl)
+{
+ GNUNET_CLIENT_MANAGER_disconnect (pl->plc.client, GNUNET_NO, NULL, NULL);
+}
+
/* end of social_api.c */
Modified: gnunet/src/social/test_social.c
===================================================================
--- gnunet/src/social/test_social.c 2015-11-18 15:23:23 UTC (rev 36671)
+++ gnunet/src/social/test_social.c 2015-11-18 22:13:27 UTC (rev 36672)
@@ -300,6 +300,8 @@
hst = NULL;
hst_plc = NULL;
+ // TODO: GNUNET_SOCIAL_place_listen_start ()
+
end ();
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r36672 - in gnunet/src: include social,
gnunet <=