[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r34021 - in gnunet: contrib src/include src/multicast src/p
From: |
gnunet |
Subject: |
[GNUnet-SVN] r34021 - in gnunet: contrib src/include src/multicast src/psyc src/social src/util |
Date: |
Wed, 23 Jul 2014 18:19:50 +0200 |
Author: tg
Date: 2014-07-23 18:19:49 +0200 (Wed, 23 Jul 2014)
New Revision: 34021
Modified:
gnunet/contrib/gnunet-logread
gnunet/src/include/gnunet_client_manager_lib.h
gnunet/src/include/gnunet_common.h
gnunet/src/include/gnunet_multicast_service.h
gnunet/src/include/gnunet_protocols.h
gnunet/src/include/gnunet_psyc_service.h
gnunet/src/include/gnunet_psyc_util_lib.h
gnunet/src/include/gnunet_social_service.h
gnunet/src/multicast/gnunet-service-multicast.c
gnunet/src/multicast/multicast_api.c
gnunet/src/psyc/gnunet-service-psyc.c
gnunet/src/psyc/psyc.h
gnunet/src/psyc/psyc_api.c
gnunet/src/psyc/psyc_util_lib.c
gnunet/src/psyc/test_psyc.c
gnunet/src/social/Makefile.am
gnunet/src/social/gnunet-service-social.c
gnunet/src/social/social.h
gnunet/src/social/social_api.c
gnunet/src/social/test_social.c
gnunet/src/util/client_manager.c
Log:
social: implement enter/leave/messaging; psyc: improvements and fixes
- social: implement enter/leave, send/receive messages, slicer
- psyc, social: add struct GNUNET_PSYC_Message for single-fragment join messages
- psyc: add message callback in addition to message part callback
- client_manager, social, psyc, multicast: add disconnect callback
Modified: gnunet/contrib/gnunet-logread
===================================================================
--- gnunet/contrib/gnunet-logread 2014-07-23 16:19:46 UTC (rev 34020)
+++ gnunet/contrib/gnunet-logread 2014-07-23 16:19:49 UTC (rev 34021)
@@ -47,7 +47,7 @@
$ipc = $opts{i} || '/tmp/gnunet-logread-ipc.sock';
$msg_level = exists $levels{$opts{L}} ? $levels{$opts{L}} : 0;
$msg_regex = $opts{m};
- print STDERR "RE: /$msg_regex/\n";
+ print STDERR "RE: /$msg_regex/\n" if defined $msg_regex;
open IPC, '>', $ipc or die "$ipc: $!\n";
}
Modified: gnunet/src/include/gnunet_client_manager_lib.h
===================================================================
--- gnunet/src/include/gnunet_client_manager_lib.h 2014-07-23 16:19:46 UTC
(rev 34020)
+++ gnunet/src/include/gnunet_client_manager_lib.h 2014-07-23 16:19:49 UTC
(rev 34021)
@@ -119,10 +119,14 @@
*
* @param mgr Client manager connection.
* @param transmit_queue Transmit pending messages in queue before
disconnecting.
+ * @param disconnect_cb Function called after disconnected from the service.
+ * @param disconnect_cls Closure for @a disconnect_cb.
*/
void
GNUNET_CLIENT_MANAGER_disconnect (struct GNUNET_CLIENT_MANAGER_Connection *mgr,
- int transmit_queue);
+ int transmit_queue,
+ GNUNET_ContinuationCallback disconnect_cb,
+ void *disconnect_cls);
/**
Modified: gnunet/src/include/gnunet_common.h
===================================================================
--- gnunet/src/include/gnunet_common.h 2014-07-23 16:19:46 UTC (rev 34020)
+++ gnunet/src/include/gnunet_common.h 2014-07-23 16:19:49 UTC (rev 34021)
@@ -264,6 +264,15 @@
const char *filename);
+/**
+ * Generic continuation callback.
+ *
+ * @param cls Closure.
+ */
+typedef void
+(*GNUNET_ContinuationCallback) (void *cls);
+
+
/* ****************************** logging ***************************** */
/**
Modified: gnunet/src/include/gnunet_multicast_service.h
===================================================================
--- gnunet/src/include/gnunet_multicast_service.h 2014-07-23 16:19:46 UTC
(rev 34020)
+++ gnunet/src/include/gnunet_multicast_service.h 2014-07-23 16:19:49 UTC
(rev 34021)
@@ -666,7 +666,9 @@
* @param origin Multicast group to stop.
*/
void
-GNUNET_MULTICAST_origin_stop (struct GNUNET_MULTICAST_Origin *origin);
+GNUNET_MULTICAST_origin_stop (struct GNUNET_MULTICAST_Origin *origin,
+ GNUNET_ContinuationCallback stop_cb,
+ void *stop_cls);
/**
@@ -795,7 +797,9 @@
* @param member Membership handle.
*/
void
-GNUNET_MULTICAST_member_part (struct GNUNET_MULTICAST_Member *member);
+GNUNET_MULTICAST_member_part (struct GNUNET_MULTICAST_Member *member,
+ GNUNET_ContinuationCallback part_cb,
+ void *part_cls);
/**
Modified: gnunet/src/include/gnunet_protocols.h
===================================================================
--- gnunet/src/include/gnunet_protocols.h 2014-07-23 16:19:46 UTC (rev
34020)
+++ gnunet/src/include/gnunet_protocols.h 2014-07-23 16:19:49 UTC (rev
34021)
@@ -2158,32 +2158,34 @@
/** C->S: request to add channel slave to the membership database */
#define GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_SLAVE_RM 690
-
-/** M<->S<->C: PSYC message which contains one or more message parts. */
+/** S<--C: PSYC message which contains one or more message parts. */
#define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE 691
+/** M<->S<->C: PSYC message which contains a header and one or more message
parts. */
+#define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_HEADER 692 // FIXME: start using this
where appropriate
+
/** Message part: method */
-#define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD 692
+#define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD 693
/** Message part: modifier */
-#define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER 693
+#define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER 694
/** Message part: modifier continuation */
-#define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT 694
+#define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT 695
/** Message part: data */
-#define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA 695
+#define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA 696
/** Message part: end of message */
-#define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END 696
+#define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END 697
/** Message part: message cancelled */
-#define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL 697
+#define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL 698
/** S->C: message acknowledgement */
-#define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK 698
+#define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK 699
-/* 699-700 */
+/* 700 */
/** C->S: client requests channel history from PSYCstore. */
#define GNUNET_MESSAGE_TYPE_PSYC_STORY_REQUEST 701
Modified: gnunet/src/include/gnunet_psyc_service.h
===================================================================
--- gnunet/src/include/gnunet_psyc_service.h 2014-07-23 16:19:46 UTC (rev
34020)
+++ gnunet/src/include/gnunet_psyc_service.h 2014-07-23 16:19:49 UTC (rev
34021)
@@ -190,6 +190,24 @@
GNUNET_NETWORK_STRUCT_BEGIN
/**
+ * A PSYC message.
+ *
+ * Used for single-fragment messages e.g. in a join request or response.
+ */
+struct GNUNET_PSYC_Message
+{
+ /**
+ * Message header with size and type information.
+ */
+ struct GNUNET_MessageHeader header;
+
+ /* Followed by concatenated PSYC message parts:
+ * messages with GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_* types
+ */
+};
+
+
+/**
* Header of a PSYC message.
*
* Only present when receiving a message.
@@ -215,6 +233,12 @@
uint64_t message_id GNUNET_PACKED;
/**
+ * Byte offset of this @e fragment of the @e message.
+ * FIXME: use data_offset instead
+ */
+ uint64_t fragment_offset GNUNET_PACKED;
+
+ /**
* Sending slave's public key.
* Not set if the message is from the master.
*/
@@ -299,6 +323,9 @@
};
+/**
+ * Join request sent to a PSYC master.
+ */
struct GNUNET_PSYC_JoinRequestMessage
{
/**
@@ -314,6 +341,9 @@
};
+/**
+ * Join decision sent in reply to a join request.
+ */
struct GNUNET_PSYC_JoinDecisionMessage
{
/**
@@ -379,26 +409,45 @@
/**
- * Method called from PSYC upon receiving part of a message.
+ * Method called from PSYC upon receiving a message.
*
* @param cls Closure.
* @param message_id Sequence number of the message.
* @param flags OR'ed GNUNET_PSYC_MessageFlags
* @param msg Message part, one of the following types:
- * - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_HEADER
- * - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD
- * - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER
- * - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT
- * - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA
*/
typedef void
(*GNUNET_PSYC_MessageCallback) (void *cls,
uint64_t message_id,
uint32_t flags,
- const struct GNUNET_MessageHeader *msg);
+ const struct GNUNET_PSYC_MessageHeader *msg);
/**
+ * Method called from PSYC upon receiving part of a message.
+ *
+ * @param cls Closure.
+ * @param message_id Sequence number of the message.
+ * @param data_offset Byte offset of data, only set if @a msg has a type
+ * #GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA
+ * @param flags OR'ed GNUNET_PSYC_MessageFlags
+ * @param msg Message part, one of the following types:
+ * - #GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_HEADER
+ * - #GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD
+ * - #GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER
+ * - #GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT
+ * - #GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA
+ * or NULL if an error occurred while receiving a message.
+ */
+typedef void
+(*GNUNET_PSYC_MessagePartCallback) (void *cls,
+ uint64_t message_id,
+ uint64_t data_offset,
+ uint32_t flags,
+ const struct GNUNET_MessageHeader *msg);
+
+
+/**
* Method called from PSYC upon receiving a join request.
*
* @param cls Closure.
@@ -408,10 +457,9 @@
*/
typedef void
(*GNUNET_PSYC_JoinRequestCallback) (void *cls,
- const struct
- GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
- const struct
- GNUNET_PSYC_MessageHeader *join_msg,
+ const struct
GNUNET_PSYC_JoinRequestMessage *req,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey
*slave_key,
+ const struct GNUNET_PSYC_Message *join_msg,
struct GNUNET_PSYC_JoinHandle *jh);
@@ -445,7 +493,7 @@
int is_admitted,
uint32_t relay_count,
const struct GNUNET_PeerIdentity *relays,
- const struct GNUNET_PSYC_MessageHeader *join_resp);
+ const struct GNUNET_PSYC_Message *join_resp);
/**
@@ -501,6 +549,7 @@
GNUNET_PSYC_MasterStartCallback master_start_cb,
GNUNET_PSYC_JoinRequestCallback join_request_cb,
GNUNET_PSYC_MessageCallback message_cb,
+ GNUNET_PSYC_MessagePartCallback message_part_cb,
void *cls);
@@ -645,10 +694,21 @@
/**
* Stop a PSYC master channel.
*
- * @param master PSYC channel master to stop.
+ * @param master
+ * PSYC channel master to stop.
+ * @param keep_active
+ * Keep place active after last application disconnected.
+ * @param stop_cb
+ * Function called after the master stopped
+ * and disconnected from the psyc service.
+ * @param stop_cls
+ * Closure for @a part_cb.
*/
void
-GNUNET_PSYC_master_stop (struct GNUNET_PSYC_Master *master);
+GNUNET_PSYC_master_stop (struct GNUNET_PSYC_Master *master,
+ int keep_active,
+ GNUNET_ContinuationCallback stop_cb,
+ void *stop_cls);
/**
@@ -679,9 +739,9 @@
*/
typedef void
(*GNUNET_PSYC_JoinDecisionCallback) (void *cls,
+ const struct
GNUNET_PSYC_JoinDecisionMessage *dcsn,
int is_admitted,
- const struct
- GNUNET_PSYC_MessageHeader *join_msg);
+ const struct GNUNET_PSYC_Message
*join_msg);
/**
@@ -726,10 +786,11 @@
uint32_t relay_count,
const struct GNUNET_PeerIdentity *relays,
GNUNET_PSYC_MessageCallback message_cb,
+ GNUNET_PSYC_MessagePartCallback message_part_cb,
GNUNET_PSYC_SlaveConnectCallback slave_connect_cb,
GNUNET_PSYC_JoinDecisionCallback join_decision_cb,
void *cls,
- const struct GNUNET_MessageHeader *join_msg);
+ const struct GNUNET_PSYC_Message *join_msg);
/**
@@ -738,10 +799,21 @@
* Will terminate the connection to the PSYC service. Polite clients should
* first explicitly send a part request (via GNUNET_PSYC_slave_transmit()).
*
- * @param slave Slave handle.
+ * @param slave
+ * Slave handle.
+ * @param keep_active
+ * Keep place active after last application disconnected.
+ * @param part_cb
+ * Function called after the slave parted the channel
+ * and disconnected from the psyc service.
+ * @param part_cls
+ * Closure for @a part_cb.
*/
void
-GNUNET_PSYC_slave_part (struct GNUNET_PSYC_Slave *slave);
+GNUNET_PSYC_slave_part (struct GNUNET_PSYC_Slave *slave,
+ int keep_active,
+ GNUNET_ContinuationCallback part_cb,
+ void *part_cls);
/**
@@ -937,6 +1009,7 @@
uint64_t start_message_id,
uint64_t end_message_id,
GNUNET_PSYC_MessageCallback message_cb,
+ GNUNET_PSYC_MessagePartCallback
message_part_cb,
GNUNET_PSYC_FinishCallback finish_cb,
void *cls);
Modified: gnunet/src/include/gnunet_psyc_util_lib.h
===================================================================
--- gnunet/src/include/gnunet_psyc_util_lib.h 2014-07-23 16:19:46 UTC (rev
34020)
+++ gnunet/src/include/gnunet_psyc_util_lib.h 2014-07-23 16:19:49 UTC (rev
34021)
@@ -55,13 +55,37 @@
* @return Message header with size information,
* followed by the message parts.
*/
-struct GNUNET_MessageHeader *
+struct GNUNET_PSYC_Message *
GNUNET_PSYC_message_create (const char *method_name,
const struct GNUNET_ENV_Environment *env,
const void *data,
size_t data_size);
+/**
+ * Parse PSYC message.
+ *
+ * @param msg
+ * The PSYC message to parse.
+ * @param env
+ * The environment for the message with a list of modifiers.
+ * @param[out] method_name
+ * Pointer to the method name inside @a pmsg.
+ * @param[out] data
+ * Pointer to data inside @a pmsg.
+ * @param[out] data_size
+ * Size of @data is written here.
+ *
+ * @return #GNUNET_OK on success,
+ * #GNUNET_SYSERR on parse error.
+ */
+int
+GNUNET_PSYC_message_parse (const struct GNUNET_PSYC_Message *msg,
+ const char **method_name,
+ struct GNUNET_ENV_Environment *env,
+ const void **data,
+ uint16_t *data_size);
+
void
GNUNET_PSYC_log_message (enum GNUNET_ErrorType kind,
const struct GNUNET_MessageHeader *msg);
@@ -150,7 +174,7 @@
*/
struct GNUNET_PSYC_ReceiveHandle *
GNUNET_PSYC_receive_create (GNUNET_PSYC_MessageCallback message_cb,
- GNUNET_PSYC_MessageCallback hist_message_cb,
+ GNUNET_PSYC_MessagePartCallback message_part_cb,
void *cb_cls);
Modified: gnunet/src/include/gnunet_social_service.h
===================================================================
--- gnunet/src/include/gnunet_social_service.h 2014-07-23 16:19:46 UTC (rev
34020)
+++ gnunet/src/include/gnunet_social_service.h 2014-07-23 16:19:49 UTC (rev
34021)
@@ -81,6 +81,8 @@
*
* @param cls
* Closure.
+ * @param msg
+ * Message part, as it arrived from the network.
* @param message_id
* Message counter, monotonically increasing from 1.
* @param nym
@@ -92,12 +94,53 @@
* Original method name from PSYC.
* May be more specific than the registered method name due to
* try-and-slice matching.
- * @param env
- * Environment with operations and variables for the message.
- * Only set for the first call of this function for each @a message_id,
- * NULL when notifying about further data fragments.
- * It has to be freed using GNUNET_ENV_environment_destroy()
- * when it is not needed anymore.
+ */
+typedef void
+(*GNUNET_SOCIAL_MethodCallback) (void *cls,
+ const struct GNUNET_PSYC_MessageMethod *msg,
+ uint64_t message_id,
+ uint32_t flags,
+ const struct GNUNET_SOCIAL_Nym *nym,
+ const char *method_name);
+
+
+/**
+ * Function called upon receiving a data fragment of a message.
+ *
+ * @param cls
+ * Closure.
+ * @param message_id
+ * Message ID this data fragment belongs to.
+ * @param msg
+ * Message part, as it arrived from the network.
+ * @param oper
+ * Operation to perform.
+ * @param name
+ * Name of the modifier.
+ * @param value
+ * Value of the modifier.
+ * @param value_size
+ * Size of @value.
+ */
+typedef void
+(*GNUNET_SOCIAL_ModifierCallback) (void *cls,
+ const struct GNUNET_PSYC_MessageModifier
*msg,
+ uint64_t message_id,
+ enum GNUNET_ENV_Operator oper,
+ const char *name,
+ const void *value,
+ uint16_t value_size);
+
+
+/**
+ * Function called upon receiving a data fragment of a message.
+ *
+ * @param cls
+ * Closure.
+ * @param message_id
+ * Message ID this data fragment belongs to.
+ * @param msg
+ * Message part, as it arrived from the network.
* @param data_offset
* Byte offset of @a data in the overall data of the method.
* @param data_size
@@ -106,24 +149,40 @@
* Data stream given to the method.
* @param end
* End of message?
- * #GNUNET_NO if there are further fragments,
- * #GNUNET_YES if this is the last fragment,
- * #GNUNET_SYSERR indicates the message was cancelled by the sender.
+ * #GNUNET_NO if there are further fragments,
+ * #GNUNET_YES if this is the last fragment,
+ * #GNUNET_SYSERR indicates the message was cancelled by the sender.
*/
typedef void
-(*GNUNET_SOCIAL_MethodCallback) (void *cls,
- uint64_t message_id,
- uint32_t flags,
- const struct GNUNET_SOCIAL_Nym *nym,
- const char *method_name,
- struct GNUNET_ENV_Environment *env,
- uint64_t data_offset,
- size_t data_size,
- const void *data,
- int end);
+(*GNUNET_SOCIAL_DataCallback) (void *cls,
+ const struct GNUNET_MessageHeader *msg,
+ uint64_t message_id,
+ uint64_t data_offset,
+ const void *data,
+ uint16_t data_size);
/**
+ * End of message.
+ *
+ * @param cls
+ * Closure.
+ * @param msg
+ * Message part, as it arrived from the network.
+ * @param message_id
+ * Message ID this data fragment belongs to.
+ * @param cancelled.
+ * #GNUNET_YES if the message was cancelled,
+ * #GNUNET_NO if the message is complete.
+ */
+typedef void
+(*GNUNET_SOCIAL_EndOfMessageCallback) (void *cls,
+ const struct GNUNET_MessageHeader *msg,
+ uint64_t message_id,
+ uint8_t cancelled);
+
+
+/**
* Create a try-and-slice instance.
*
* @return A new try-and-slice construct.
@@ -148,21 +207,28 @@
GNUNET_SOCIAL_slicer_add (struct GNUNET_SOCIAL_Slicer *slicer,
const char *method_name,
GNUNET_SOCIAL_MethodCallback method_cb,
+ GNUNET_SOCIAL_ModifierCallback modifier_cb,
+ GNUNET_SOCIAL_DataCallback data_cb,
+ GNUNET_SOCIAL_EndOfMessageCallback eom_cb,
void *cls);
/**
- * Remove a registered method from the try-and-slice instance.
+ * Remove a registered method handler from the try-and-slice instance.
*
* @param slicer The try-and-slice instance.
* @param method_name Name of the method to remove.
* @param method Method handler.
*/
-void
+int
GNUNET_SOCIAL_slicer_remove (struct GNUNET_SOCIAL_Slicer *slicer,
const char *method_name,
- GNUNET_SOCIAL_MethodCallback method_cb);
+ GNUNET_SOCIAL_MethodCallback method_cb,
+ GNUNET_SOCIAL_ModifierCallback modifier_cb,
+ GNUNET_SOCIAL_DataCallback data_cb,
+ GNUNET_SOCIAL_EndOfMessageCallback eom_cb);
+
/**
* Destroy a given try-and-slice instance.
*
@@ -257,7 +323,7 @@
*/
struct GNUNET_SOCIAL_Host *
GNUNET_SOCIAL_host_enter (const struct GNUNET_CONFIGURATION_Handle *cfg,
- struct GNUNET_IDENTITY_Ego *ego,
+ const struct GNUNET_IDENTITY_Ego *ego,
const struct GNUNET_CRYPTO_EddsaPrivateKey
*place_key,
enum GNUNET_PSYC_Policy policy,
struct GNUNET_SOCIAL_Slicer *slicer,
@@ -268,17 +334,32 @@
/**
- * Admit @a nym to the place.
+ * Decision whether to admit @a nym into the place or refuse entry.
*
- * The @a nym reference will remain valid until either the @a host or @a nym
- * leaves the place.
- *
- * @param host Host of the place.
- * @param nym Handle for the entity that wants to enter.
+ * @param hst
+ * Host of the place.
+ * @param nym
+ * Handle for the entity that wanted to enter.
+ * @param is_admitted
+ * #GNUNET_YES if @a nym is admitted,
+ * #GNUNET_NO if @a nym is refused entry,
+ * #GNUNET_SYSERR if we cannot answer the request.
+ * @param method_name
+ * Method name for the rejection message.
+ * @param env
+ * Environment containing variables for the message, or NULL.
+ * @param data
+ * Data for the rejection message to send back.
+ * @param data_size
+ * Number of bytes in @a data for method.
+ * @return #GNUNET_OK on success,
+ * #GNUNET_SYSERR if the message is too large.
*/
-void
-GNUNET_SOCIAL_host_admit (struct GNUNET_SOCIAL_Host *host,
- struct GNUNET_SOCIAL_Nym *nym);
+int
+GNUNET_SOCIAL_host_entry_decision (struct GNUNET_SOCIAL_Host *hst,
+ struct GNUNET_SOCIAL_Nym *nym,
+ int is_admitted,
+ const struct GNUNET_PSYC_Message
*entry_resp);
/**
@@ -297,35 +378,17 @@
/**
- * Refuse @a nym entry into the place.
- *
- * @param host Host of the place.
- * @param nym Handle for the entity that wanted to enter.
- * @param method_name Method name for the rejection message.
- * @param env Environment containing variables for the message, or NULL.
- * @param data Data for the rejection message to send back.
- * @param data_size Number of bytes in @a data for method.
- */
-void
-GNUNET_SOCIAL_host_refuse_entry (struct GNUNET_SOCIAL_Host *host,
- struct GNUNET_SOCIAL_Nym *nym,
- const char *method_name,
- const struct GNUNET_ENV_Environment *env,
- const void *data,
- size_t data_size);
-
-
-/**
* Get the public key of a @a nym.
*
* Suitable, for example, to be used with GNUNET_NAMESTORE_zone_to_name().
*
- * @param nym Pseudonym to map to a cryptographic identifier.
- * @param[out] nym_key Set to the public key of the nym.
+ * @param nym
+ * Pseudonym to map to a cryptographic identifier.
+ *
+ * @return Public key of nym;
*/
-void
-GNUNET_SOCIAL_nym_get_key (struct GNUNET_SOCIAL_Nym *nym,
- struct GNUNET_CRYPTO_EddsaPublicKey *nym_key);
+struct GNUNET_CRYPTO_EcdsaPublicKey *
+GNUNET_SOCIAL_nym_get_key (struct GNUNET_SOCIAL_Nym *nym);
/**
@@ -418,9 +481,20 @@
/**
+ * Resume transmitting announcement.
+ *
+ * @param a
+ * The announcement to resume.
+ */
+void
+GNUNET_SOCIAL_host_announce_resume (struct GNUNET_SOCIAL_Announcement *a);
+
+
+/**
* Cancel announcement.
*
- * @param a The announcement to cancel.
+ * @param a
+ * The announcement to cancel.
*/
void
GNUNET_SOCIAL_host_announce_cancel (struct GNUNET_SOCIAL_Announcement *a);
@@ -431,7 +505,8 @@
*
* The returned handle can be used to access the place API.
*
- * @param host Handle for the host.
+ * @param host
+ * Handle for the host.
*
* @return Handle for the hosted place, valid as long as @a host is valid.
*/
@@ -444,11 +519,21 @@
*
* Invalidates host handle.
*
- * @param host Host leaving the place.
- * @param keep_active Keep the place active after last host disconnected.
+ * @param host
+ * Host leaving the place.
+ * @param keep_active
+ * Keep the place active after last host disconnected.
+ * @param leave_cb
+ * Function called after the host left the place
+ * and disconnected from the social service.
+ * @param leave_cls
+ * Closure for @a leave_cb.
*/
void
-GNUNET_SOCIAL_host_leave (struct GNUNET_SOCIAL_Host *host, int keep_active);
+GNUNET_SOCIAL_host_leave (struct GNUNET_SOCIAL_Host *host,
+ int keep_active,
+ GNUNET_ContinuationCallback leave_cb,
+ void *leave_cls);
/**
@@ -493,13 +578,10 @@
* @param data
* Payload of the message.
*/
-typedef int
+typedef void
(*GNUNET_SOCIAL_EntryDecisionCallback) (void *cls,
int is_admitted,
- const char *method_name,
- struct GNUNET_ENV_Environment *env,
- size_t data_size,
- const void *data);
+ const struct GNUNET_PSYC_Message
*entry_resp);
/**
@@ -521,15 +603,12 @@
*/
struct GNUNET_SOCIAL_Guest *
GNUNET_SOCIAL_guest_enter (const struct GNUNET_CONFIGURATION_Handle *cfg,
- struct GNUNET_IDENTITY_Ego *ego,
- struct GNUNET_CRYPTO_EddsaPublicKey *place_key,
- struct GNUNET_PeerIdentity *origin,
+ const struct GNUNET_IDENTITY_Ego *ego,
+ const struct GNUNET_CRYPTO_EddsaPublicKey
*place_key,
+ const struct GNUNET_PeerIdentity *origin,
uint32_t relay_count,
- struct GNUNET_PeerIdentity *relays,
- const char *method_name,
- const struct GNUNET_ENV_Environment *env,
- const void *data,
- size_t data_size,
+ 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,
@@ -558,10 +637,7 @@
GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_CONFIGURATION_Handle
*cfg,
struct GNUNET_IDENTITY_Ego *ego,
char *gns_name,
- const char *method_name,
- const struct GNUNET_ENV_Environment *env,
- const void *data,
- size_t data_size,
+ const struct GNUNET_PSYC_Message *join_msg,
struct GNUNET_SOCIAL_Slicer *slicer,
GNUNET_SOCIAL_GuestEnterCallback
local_enter_cb,
GNUNET_SOCIAL_EntryDecisionCallback
entry_decision_cb,
@@ -612,9 +688,20 @@
/**
+ * Resume talking to the host of the place.
+ *
+ * @param tr
+ * Talk request to resume.
+ */
+void
+GNUNET_SOCIAL_guest_talk_resume (struct GNUNET_SOCIAL_TalkRequest *tr);
+
+
+/**
* Cancel talking to the host of the place.
*
- * @param tr Talk request to cancel.
+ * @param tr
+ * Talk request to cancel.
*/
void
GNUNET_SOCIAL_guest_talk_cancel (struct GNUNET_SOCIAL_TalkRequest *tr);
@@ -625,11 +712,21 @@
*
* Notifies the owner of the place about leaving, and destroys the place
handle.
*
- * @param place Place to leave permanently.
- * @param keep_active Keep place active after last application disconnected.
+ * @param place
+ * Place to leave permanently.
+ * @param keep_active
+ * Keep place active after last application disconnected.
+ * @param leave_cb
+ * Function called after the guest left the place
+ * and disconnected from the social service.
+ * @param leave_cls
+ * Closure for @a leave_cb.
*/
void
-GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Guest *guest, int keep_active);
+GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Guest *guest,
+ int keep_active,
+ GNUNET_ContinuationCallback leave_cb,
+ void *leave_cls);
/**
Modified: gnunet/src/multicast/gnunet-service-multicast.c
===================================================================
--- gnunet/src/multicast/gnunet-service-multicast.c 2014-07-23 16:19:46 UTC
(rev 34020)
+++ gnunet/src/multicast/gnunet-service-multicast.c 2014-07-23 16:19:49 UTC
(rev 34021)
@@ -423,6 +423,7 @@
{
orig = GNUNET_new (struct Origin);
orig->priv_key = msg->group_key;
+ orig->max_fragment_id = GNUNET_ntohll (msg->max_fragment_id);
grp = &orig->grp;
grp->is_origin = GNUNET_YES;
grp->pub_key = pub_key;
@@ -482,6 +483,7 @@
mem->priv_key = msg->member_key;
mem->pub_key = mem_pub_key;
mem->pub_key_hash = mem_pub_key_hash;
+ mem->max_fragment_id = 0; // FIXME
grp = &mem->grp;
grp->is_origin = GNUNET_NO;
@@ -663,7 +665,7 @@
struct GNUNET_MULTICAST_MessageHeader *
msg = (struct GNUNET_MULTICAST_MessageHeader *) m;
- msg->fragment_id = GNUNET_htonll (orig->max_fragment_id++);
+ msg->fragment_id = GNUNET_htonll (++orig->max_fragment_id);
msg->purpose.size = htonl (sizeof (*msg) + ntohs (m->size)
- sizeof (msg->header)
- sizeof (msg->hop_counter)
@@ -699,8 +701,7 @@
struct GNUNET_MULTICAST_RequestHeader *
req = (struct GNUNET_MULTICAST_RequestHeader *) m;
- req->fragment_id = GNUNET_ntohll (mem->max_fragment_id++);
-
+ req->fragment_id = GNUNET_ntohll (++mem->max_fragment_id);
req->purpose.size = htonl (sizeof (*req) + ntohs (m->size)
- sizeof (req->header)
- sizeof (req->member_key)
Modified: gnunet/src/multicast/multicast_api.c
===================================================================
--- gnunet/src/multicast/multicast_api.c 2014-07-23 16:19:46 UTC (rev
34020)
+++ gnunet/src/multicast/multicast_api.c 2014-07-23 16:19:49 UTC (rev
34021)
@@ -88,6 +88,16 @@
void *cb_cls;
/**
+ * Function called after disconnected from the service.
+ */
+ GNUNET_ContinuationCallback disconnect_cb;
+
+ /**
+ * Closure for @a disconnect_cb.
+ */
+ void *disconnect_cls;
+
+ /**
* Are we currently transmitting a message?
*/
uint8_t in_transmit;
@@ -96,6 +106,12 @@
* Is this the origin or a member?
*/
uint8_t is_origin;
+
+ /**
+ * Is this channel in the process of disconnecting from the service?
+ * #GNUNET_YES or #GNUNET_NO
+ */
+ uint8_t is_disconnecting;
};
@@ -320,8 +336,9 @@
mem->join_dcsn_cb (grp->cb_cls, is_admitted, &hdcsn->peer,
relay_count, relays, join_resp);
- if (GNUNET_YES != is_admitted)
- GNUNET_MULTICAST_member_part (mem);
+ // FIXME:
+ //if (GNUNET_YES != is_admitted)
+ // GNUNET_MULTICAST_member_part (mem);
}
@@ -371,6 +388,33 @@
};
+static void
+group_cleanup (struct GNUNET_MULTICAST_Group *grp)
+{
+ GNUNET_free (grp->connect_msg);
+ if (NULL != grp->disconnect_cb)
+ grp->disconnect_cb (grp->disconnect_cls);
+}
+
+
+static void
+origin_cleanup (void *cls)
+{
+ struct GNUNET_MULTICAST_Origin *orig = cls;
+ group_cleanup (&orig->grp);
+ GNUNET_free (orig);
+}
+
+
+static void
+member_cleanup (void *cls)
+{
+ struct GNUNET_MULTICAST_Member *mem = cls;
+ group_cleanup (&mem->grp);
+ GNUNET_free (mem);
+}
+
+
/**
* Function to call with the decision made for a join request.
*
@@ -565,10 +609,18 @@
* @param origin Multicast group to stop.
*/
void
-GNUNET_MULTICAST_origin_stop (struct GNUNET_MULTICAST_Origin *orig)
+GNUNET_MULTICAST_origin_stop (struct GNUNET_MULTICAST_Origin *orig,
+ GNUNET_ContinuationCallback stop_cb,
+ void *stop_cls)
{
- GNUNET_CLIENT_MANAGER_disconnect (orig->grp.client, GNUNET_YES);
- GNUNET_free (orig);
+ struct GNUNET_MULTICAST_Group *grp = &orig->grp;
+
+ grp->is_disconnecting = GNUNET_YES;
+ grp->disconnect_cb = stop_cb;
+ grp->disconnect_cls = stop_cls;
+
+ GNUNET_CLIENT_MANAGER_disconnect (orig->grp.client, GNUNET_YES,
+ &origin_cleanup, orig);
}
@@ -774,10 +826,18 @@
* @param member Membership handle.
*/
void
-GNUNET_MULTICAST_member_part (struct GNUNET_MULTICAST_Member *mem)
+GNUNET_MULTICAST_member_part (struct GNUNET_MULTICAST_Member *mem,
+ GNUNET_ContinuationCallback part_cb,
+ void *part_cls)
{
- GNUNET_CLIENT_MANAGER_disconnect (mem->grp.client, GNUNET_YES);
- GNUNET_free (mem);
+ struct GNUNET_MULTICAST_Group *grp = &mem->grp;
+
+ grp->is_disconnecting = GNUNET_YES;
+ grp->disconnect_cb = part_cb;
+ grp->disconnect_cls = part_cls;
+
+ GNUNET_CLIENT_MANAGER_disconnect (mem->grp.client, GNUNET_YES,
+ &member_cleanup, mem);
}
Modified: gnunet/src/psyc/gnunet-service-psyc.c
===================================================================
--- gnunet/src/psyc/gnunet-service-psyc.c 2014-07-23 16:19:46 UTC (rev
34020)
+++ gnunet/src/psyc/gnunet-service-psyc.c 2014-07-23 16:19:49 UTC (rev
34021)
@@ -168,7 +168,7 @@
* Is the message queued for delivery to the client?
* i.e. added to the recv_msgs queue
*/
- uint8_t queued;
+ uint8_t is_queued;
};
@@ -382,7 +382,7 @@
/**
* Join request to be transmitted to the master on join.
*/
- struct GNUNET_MessageHeader *join_req;
+ struct GNUNET_PSYC_Message *join_msg;
/**
* Join decision received from multicast.
@@ -435,7 +435,7 @@
struct Channel *chn = &mst->chn;
if (NULL != mst->origin)
- GNUNET_MULTICAST_origin_stop (mst->origin);
+ GNUNET_MULTICAST_origin_stop (mst->origin, NULL, NULL); // FIXME
GNUNET_CONTAINER_multihashmap_destroy (mst->join_reqs);
GNUNET_CONTAINER_multihashmap_remove (masters, &chn->pub_key_hash, chn);
}
@@ -462,12 +462,21 @@
}
GNUNET_CONTAINER_multihashmap_remove (slaves, &chn->pub_key_hash, slv);
- if (NULL != slv->join_req)
- GNUNET_free (slv->join_req);
+ if (NULL != slv->join_msg)
+ {
+ GNUNET_free (slv->join_msg);
+ slv->join_msg = NULL;
+ }
if (NULL != slv->relays)
+ {
GNUNET_free (slv->relays);
+ slv->relays = NULL;
+ }
if (NULL != slv->member)
- GNUNET_MULTICAST_member_part (slv->member);
+ {
+ GNUNET_MULTICAST_member_part (slv->member, NULL, NULL); // FIXME
+ slv->member = NULL;
+ }
GNUNET_CONTAINER_multihashmap_remove (slaves, &chn->pub_key_hash, chn);
}
@@ -482,7 +491,10 @@
GNUNET_CONTAINER_multihashmap_remove_all (recv_cache, &chn->pub_key_hash);
if (NULL != chn->store_op)
+ {
GNUNET_PSYCSTORE_operation_cancel (chn->store_op);
+ chn->store_op = NULL;
+ }
(GNUNET_YES == chn->is_master)
? cleanup_master ((struct Master *) chn)
@@ -574,7 +586,7 @@
struct GNUNET_CRYPTO_EcdsaPublicKey slave_key;
struct Channel *chn;
struct GNUNET_MULTICAST_JoinHandle *jh;
- struct MasterJoinRequest *master_join_req;
+ struct GNUNET_PSYC_JoinRequestMessage *join_msg;
};
@@ -594,14 +606,14 @@
&slave_key_hash);
GNUNET_CONTAINER_multihashmap_put (mst->join_reqs, &slave_key_hash,
jcls->jh,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
- client_send_msg (jcls->chn, &jcls->master_join_req->header);
+ client_send_msg (jcls->chn, &jcls->join_msg->header);
}
else
{
// FIXME: add relays
GNUNET_MULTICAST_join_decision (jcls->jh, result, 0, NULL, NULL);
}
- GNUNET_free (jcls->master_join_req);
+ GNUNET_free (jcls->join_msg);
GNUNET_free (jcls);
}
@@ -633,7 +645,8 @@
}
}
- struct MasterJoinRequest *req = GNUNET_malloc (sizeof (*req) +
join_msg_size);
+ struct GNUNET_PSYC_JoinRequestMessage *
+ req = GNUNET_malloc (sizeof (*req) + join_msg_size);
req->header.size = htons (sizeof (*req) + join_msg_size);
req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST);
req->slave_key = *slave_key;
@@ -644,7 +657,7 @@
jcls->slave_key = *slave_key;
jcls->chn = chn;
jcls->jh = jh;
- jcls->master_join_req = req;
+ jcls->join_msg = req;
GNUNET_PSYCSTORE_membership_test (store, &chn->pub_key, slave_key,
chn->max_message_id, 0,
@@ -780,6 +793,7 @@
pmsg->header.size = htons (psize);
pmsg->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE);
pmsg->message_id = mmsg->message_id;
+ pmsg->fragment_offset = mmsg->fragment_offset;
memcpy (&pmsg[1], &mmsg[1], size - sizeof (*mmsg));
client_send_msg (chn, &pmsg->header);
@@ -810,6 +824,7 @@
pmsg->header.size = htons (psize);
pmsg->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE);
pmsg->message_id = req->request_id;
+ pmsg->fragment_offset = req->fragment_offset;
pmsg->flags = htonl (GNUNET_PSYC_MESSAGE_REQUEST);
memcpy (&pmsg[1], &req[1], size - sizeof (*req));
@@ -870,11 +885,12 @@
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"%p Adding message fragment to cache. "
- "message_id: %" PRIu64 ", fragment_id: %" PRIu64 ", "
- "header_size: %" PRIu64 " + %u).\n",
+ "message_id: %" PRIu64 ", fragment_id: %" PRIu64 "\n",
chn, GNUNET_ntohll (mmsg->message_id),
- GNUNET_ntohll (mmsg->fragment_id),
- fragq->header_size, size);
+ GNUNET_ntohll (mmsg->fragment_id));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%p header_size: %" PRIu64 " + %u\n",
+ chn, fragq->header_size, size);
cache_entry = GNUNET_new (struct RecvCacheEntry);
cache_entry->ref_count = 1;
cache_entry->mmsg = GNUNET_malloc (size);
@@ -955,11 +971,11 @@
case MSG_FRAG_STATE_DATA:
case MSG_FRAG_STATE_END:
case MSG_FRAG_STATE_CANCEL:
- if (GNUNET_NO == fragq->queued)
+ if (GNUNET_NO == fragq->is_queued)
{
GNUNET_CONTAINER_heap_insert (chn->recv_msgs, NULL,
GNUNET_ntohll (mmsg->message_id));
- fragq->queued = GNUNET_YES;
+ fragq->is_queued = GNUNET_YES;
}
}
@@ -1034,7 +1050,7 @@
if (MSG_FRAG_STATE_END <= fragq->state)
{
struct GNUNET_HashCode msg_id_hash;
- hash_key_from_nll (&msg_id_hash, msg_id);
+ hash_key_from_hll (&msg_id_hash, msg_id);
GNUNET_CONTAINER_multihashmap_remove (chn->recv_frags, &msg_id_hash,
fragq);
GNUNET_CONTAINER_heap_destroy (fragq->fragments);
@@ -1042,7 +1058,7 @@
}
else
{
- fragq->queued = GNUNET_NO;
+ fragq->is_queued = GNUNET_NO;
}
}
@@ -1331,13 +1347,18 @@
= GNUNET_MULTICAST_member_join (cfg, &chn->pub_key, &slv->priv_key,
&slv->origin,
slv->relay_count, slv->relays,
- slv->join_req,
+ &slv->join_msg->header,
&mcast_recv_join_request,
&mcast_recv_join_decision,
&mcast_recv_membership_test,
&mcast_recv_replay_fragment,
&mcast_recv_replay_message,
&mcast_recv_message, chn);
+ if (NULL != slv->join_msg)
+ {
+ GNUNET_free (slv->join_msg);
+ slv->join_msg = NULL;
+ }
}
else
{
@@ -1435,6 +1456,7 @@
{
const struct SlaveJoinRequest *req
= (const struct SlaveJoinRequest *) msg;
+ uint16_t req_size = ntohs (req->header.size);
struct GNUNET_CRYPTO_EcdsaPublicKey slv_pub_key;
struct GNUNET_HashCode pub_key_hash, slv_pub_key_hash;
@@ -1460,15 +1482,32 @@
slv->pub_key_hash = slv_pub_key_hash;
slv->origin = req->origin;
slv->relay_count = ntohl (req->relay_count);
+
+ const struct GNUNET_PeerIdentity *
+ relays = (const struct GNUNET_PeerIdentity *) &req[1];
+ uint16_t relay_size = slv->relay_count * sizeof (*relays);
+ uint16_t join_msg_size = 0;
+
+ if (sizeof (*req) + relay_size + sizeof (struct GNUNET_MessageHeader)
+ <= req_size)
+ {
+ join_msg_size = ntohs (slv->join_msg->header.size);
+ slv->join_msg = GNUNET_malloc (join_msg_size);
+ memcpy (slv->join_msg, ((char *) &req[1]) + relay_size, join_msg_size);
+ }
+ if (sizeof (*req) + relay_size + join_msg_size != req_size)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "%u + %u + %u != %u\n",
+ sizeof (*req), relay_size, join_msg_size, req_size);
+ GNUNET_break (0);
+ GNUNET_SERVER_client_disconnect (client);
+ return;
+ }
if (0 < slv->relay_count)
{
- const struct GNUNET_PeerIdentity *relays
- = (const struct GNUNET_PeerIdentity *) &req[1];
- slv->relays
- = GNUNET_malloc (slv->relay_count * sizeof (struct
GNUNET_PeerIdentity));
- uint32_t i;
- for (i = 0; i < slv->relay_count; i++)
- memcpy (&slv->relays[i], &relays[i], sizeof (*relays));
+ slv->relays = GNUNET_malloc (relay_size);
+ memcpy (slv->relays, &req[1], relay_size);
}
chn = &slv->chn;
@@ -1510,14 +1549,18 @@
= GNUNET_MULTICAST_member_join (cfg, &chn->pub_key, &slv->priv_key,
&slv->origin,
slv->relay_count, slv->relays,
- slv->join_req,
+ &slv->join_msg->header,
&mcast_recv_join_request,
&mcast_recv_join_decision,
&mcast_recv_membership_test,
&mcast_recv_replay_fragment,
&mcast_recv_replay_message,
&mcast_recv_message, chn);
-
+ if (NULL != slv->join_msg)
+ {
+ GNUNET_free (slv->join_msg);
+ slv->join_msg = NULL;
+ }
}
else if (NULL != slv->join_dcsn)
{
@@ -1549,13 +1592,14 @@
/**
- * Iterator callback for responding to join requests of a slave.
+ * Iterator callback for sending join decisions to multicast.
*/
static int
mcast_send_join_decision (void *cls, const struct GNUNET_HashCode
*pub_key_hash,
- void *jh)
+ void *value)
{
struct JoinDecisionClosure *jcls = cls;
+ struct GNUNET_MULTICAST_JoinHandle *jh = value;
// FIXME: add relays
GNUNET_MULTICAST_join_decision (jh, jcls->is_admitted, 0, NULL, jcls->msg);
return GNUNET_YES;
@@ -1579,8 +1623,7 @@
struct JoinDecisionClosure jcls;
jcls.is_admitted = ntohl (dcsn->is_admitted);
jcls.msg
- = (sizeof (*dcsn) + sizeof (struct GNUNET_PSYC_MessageHeader)
- <= ntohs (msg->size))
+ = (sizeof (*dcsn) + sizeof (*jcls.msg) <= ntohs (msg->size))
? (struct GNUNET_MessageHeader *) &dcsn[1]
: NULL;
@@ -1901,6 +1944,9 @@
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%p Received message with first part type %u and last part type
%u.\n",
+ chn, first_ptype, last_ptype);
queue_message (chn, client, size - sizeof (*msg), &msg[1],
first_ptype, last_ptype);
Modified: gnunet/src/psyc/psyc.h
===================================================================
--- gnunet/src/psyc/psyc.h 2014-07-23 16:19:46 UTC (rev 34020)
+++ gnunet/src/psyc/psyc.h 2014-07-23 16:19:49 UTC (rev 34021)
@@ -229,22 +229,6 @@
*/
};
-
-struct MasterJoinRequest
-{
- /**
- * Type: GNUNET_MESSAGE_TYPE_PSYC_MASTER_JOIN_REQUEST
- */
- struct GNUNET_MessageHeader header;
- /**
- * Public key of the joining slave.
- */
- struct GNUNET_CRYPTO_EcdsaPublicKey slave_key;
-
- /* Followed by struct GNUNET_MessageHeader join_request */
-};
-
-
GNUNET_NETWORK_STRUCT_END
#endif
Modified: gnunet/src/psyc/psyc_api.c
===================================================================
--- gnunet/src/psyc/psyc_api.c 2014-07-23 16:19:46 UTC (rev 34020)
+++ gnunet/src/psyc/psyc_api.c 2014-07-23 16:19:49 UTC (rev 34021)
@@ -74,6 +74,16 @@
struct GNUNET_MessageHeader *connect_msg;
/**
+ * Function called after disconnected from the service.
+ */
+ GNUNET_ContinuationCallback disconnect_cb;
+
+ /**
+ * Closure for @a disconnect_cb.
+ */
+ void *disconnect_cls;
+
+ /**
* Are we polling for incoming messages right now?
*/
uint8_t in_receive;
@@ -82,6 +92,12 @@
* Is this a master or slave channel?
*/
uint8_t is_master;
+
+ /**
+ * Is this channel in the process of disconnecting from the service?
+ * #GNUNET_YES or #GNUNET_NO
+ */
+ uint8_t is_disconnecting;
};
@@ -232,19 +248,26 @@
struct GNUNET_PSYC_Master *
mst = GNUNET_CLIENT_MANAGER_get_user_context_ (client,
sizeof (struct
GNUNET_PSYC_Channel));
+ if (NULL == mst->join_req_cb)
+ return;
- const struct MasterJoinRequest *req = (const struct MasterJoinRequest *) msg;
+ const struct GNUNET_PSYC_JoinRequestMessage *
+ req = (const struct GNUNET_PSYC_JoinRequestMessage *) msg;
+ const struct GNUNET_PSYC_Message *join_msg = NULL;
+ if (sizeof (*req) + sizeof (*join_msg) <= ntohs (req->header.size))
+ {
+ join_msg = (struct GNUNET_PSYC_Message *) &req[1];
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "Received join_msg of type %u and size %u.\n",
+ ntohs (join_msg->header.type), ntohs (join_msg->header.size));
+ }
- struct GNUNET_PSYC_MessageHeader *pmsg = NULL;
- if (ntohs (req->header.size) <= sizeof (*req) + sizeof (*pmsg))
- pmsg = (struct GNUNET_PSYC_MessageHeader *) &req[1];
-
struct GNUNET_PSYC_JoinHandle *jh = GNUNET_malloc (sizeof (*jh));
jh->mst = mst;
jh->slave_key = req->slave_key;
if (NULL != mst->join_req_cb)
- mst->join_req_cb (mst->cb_cls, &req->slave_key, pmsg, jh);
+ mst->join_req_cb (mst->cb_cls, req, &req->slave_key, join_msg, jh);
}
@@ -273,13 +296,12 @@
const struct GNUNET_PSYC_JoinDecisionMessage *
dcsn = (const struct GNUNET_PSYC_JoinDecisionMessage *) msg;
- struct GNUNET_PSYC_MessageHeader *pmsg = NULL;
+ struct GNUNET_PSYC_Message *pmsg = NULL;
if (ntohs (dcsn->header.size) <= sizeof (*dcsn) + sizeof (*pmsg))
- pmsg = (struct GNUNET_PSYC_MessageHeader *) &dcsn[1];
+ pmsg = (struct GNUNET_PSYC_Message *) &dcsn[1];
- struct GNUNET_PSYC_JoinHandle *jh = GNUNET_malloc (sizeof (*jh));
if (NULL != slv->join_dcsn_cb)
- slv->join_dcsn_cb (slv->cb_cls, ntohl (dcsn->is_admitted), pmsg);
+ slv->join_dcsn_cb (slv->cb_cls, dcsn, ntohl (dcsn->is_admitted), pmsg);
}
@@ -299,7 +321,7 @@
{ &master_recv_join_request, NULL,
GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST,
- sizeof (struct MasterJoinRequest), GNUNET_YES },
+ sizeof (struct GNUNET_PSYC_JoinRequestMessage), GNUNET_YES },
{ &channel_recv_disconnect, NULL, 0, 0, GNUNET_NO },
@@ -331,6 +353,35 @@
};
+static void
+channel_cleanup (struct GNUNET_PSYC_Channel *chn)
+{
+ GNUNET_PSYC_transmit_destroy (chn->tmit);
+ GNUNET_PSYC_receive_destroy (chn->recv);
+ GNUNET_free (chn->connect_msg);
+ if (NULL != chn->disconnect_cb)
+ chn->disconnect_cb (chn->disconnect_cls);
+}
+
+
+static void
+master_cleanup (void *cls)
+{
+ struct GNUNET_PSYC_Master *mst = cls;
+ channel_cleanup (&mst->chn);
+ GNUNET_free (mst);
+}
+
+
+static void
+slave_cleanup (void *cls)
+{
+ struct GNUNET_PSYC_Slave *slv = cls;
+ channel_cleanup (&slv->chn);
+ GNUNET_free (slv);
+}
+
+
/**
* Start a PSYC master channel.
*
@@ -367,6 +418,7 @@
GNUNET_PSYC_MasterStartCallback start_cb,
GNUNET_PSYC_JoinRequestCallback join_request_cb,
GNUNET_PSYC_MessageCallback message_cb,
+ GNUNET_PSYC_MessagePartCallback message_part_cb,
void *cls)
{
struct GNUNET_PSYC_Master *mst = GNUNET_malloc (sizeof (*mst));
@@ -390,7 +442,7 @@
GNUNET_CLIENT_MANAGER_set_user_context_ (chn->client, mst, sizeof (*chn));
chn->tmit = GNUNET_PSYC_transmit_create (chn->client);
- chn->recv = GNUNET_PSYC_receive_create (message_cb, message_cb, cls);
+ chn->recv = GNUNET_PSYC_receive_create (message_cb, message_part_cb, cls);
channel_send_connect_msg (chn);
return mst;
@@ -404,10 +456,21 @@
* @param keep_active FIXME
*/
void
-GNUNET_PSYC_master_stop (struct GNUNET_PSYC_Master *mst)
+GNUNET_PSYC_master_stop (struct GNUNET_PSYC_Master *mst,
+ int keep_active,
+ GNUNET_ContinuationCallback stop_cb,
+ void *stop_cls)
{
- GNUNET_CLIENT_MANAGER_disconnect (mst->chn.client, GNUNET_YES);
- GNUNET_free (mst);
+ struct GNUNET_PSYC_Channel *chn = &mst->chn;
+
+ /* FIXME: send msg to service */
+
+ chn->is_disconnecting = GNUNET_YES;
+ chn->disconnect_cb = stop_cb;
+ chn->disconnect_cls = stop_cls;
+
+ GNUNET_CLIENT_MANAGER_disconnect (mst->chn.client, GNUNET_YES,
+ &master_cleanup, mst);
}
@@ -439,7 +502,7 @@
int is_admitted,
uint32_t relay_count,
const struct GNUNET_PeerIdentity *relays,
- const struct GNUNET_PSYC_MessageHeader *join_resp)
+ const struct GNUNET_PSYC_Message *join_resp)
{
struct GNUNET_PSYC_Channel *chn = &jh->mst->chn;
struct GNUNET_PSYC_JoinDecisionMessage *dcsn;
@@ -461,6 +524,7 @@
memcpy (&dcsn[1], join_resp, join_resp_size);
GNUNET_CLIENT_MANAGER_transmit (chn->client, &dcsn->header);
+ GNUNET_free (jh);
return GNUNET_OK;
}
@@ -576,15 +640,19 @@
uint32_t relay_count,
const struct GNUNET_PeerIdentity *relays,
GNUNET_PSYC_MessageCallback message_cb,
+ GNUNET_PSYC_MessagePartCallback message_part_cb,
GNUNET_PSYC_SlaveConnectCallback connect_cb,
GNUNET_PSYC_JoinDecisionCallback join_decision_cb,
void *cls,
- const struct GNUNET_MessageHeader *join_msg)
+ const struct GNUNET_PSYC_Message *join_msg)
{
struct GNUNET_PSYC_Slave *slv = GNUNET_malloc (sizeof (*slv));
struct GNUNET_PSYC_Channel *chn = &slv->chn;
+
+ uint16_t relay_size = relay_count * sizeof (*relays);
+ uint16_t join_msg_size = ntohs (join_msg->header.size);
struct SlaveJoinRequest *req
- = GNUNET_malloc (sizeof (*req) + relay_count * sizeof (*relays));
+ = GNUNET_malloc (sizeof (*req) + relay_size + join_msg_size);
req->header.size = htons (sizeof (*req)
+ relay_count * sizeof (*relays));
req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN);
@@ -592,8 +660,13 @@
req->slave_key = *slave_key;
req->origin = *origin;
req->relay_count = htonl (relay_count);
- memcpy (&req[1], relays, relay_count * sizeof (*relays));
+ if (0 < relay_size)
+ memcpy (&req[1], relays, relay_size);
+
+ if (0 < join_msg_size)
+ memcpy ((char *) &req[1] + relay_size, join_msg, join_msg_size);
+
chn->connect_msg = (struct GNUNET_MessageHeader *) req;
chn->cfg = cfg;
chn->is_master = GNUNET_NO;
@@ -605,7 +678,7 @@
chn->client = GNUNET_CLIENT_MANAGER_connect (cfg, "psyc", slave_handlers);
GNUNET_CLIENT_MANAGER_set_user_context_ (chn->client, slv, sizeof (*chn));
- chn->recv = GNUNET_PSYC_receive_create (message_cb, message_cb, cls);
+ chn->recv = GNUNET_PSYC_receive_create (message_cb, message_part_cb, cls);
chn->tmit = GNUNET_PSYC_transmit_create (chn->client);
channel_send_connect_msg (chn);
@@ -622,10 +695,21 @@
* @param slave Slave handle.
*/
void
-GNUNET_PSYC_slave_part (struct GNUNET_PSYC_Slave *slv)
+GNUNET_PSYC_slave_part (struct GNUNET_PSYC_Slave *slv,
+ int keep_active,
+ GNUNET_ContinuationCallback part_cb,
+ void *part_cls)
{
- GNUNET_CLIENT_MANAGER_disconnect (slv->chn.client, GNUNET_YES);
- GNUNET_free (slv);
+ struct GNUNET_PSYC_Channel *chn = &slv->chn;
+
+ /* FIXME: send msg to service */
+
+ chn->is_disconnecting = GNUNET_YES;
+ chn->disconnect_cb = part_cb;
+ chn->disconnect_cls = part_cls;
+
+ GNUNET_CLIENT_MANAGER_disconnect (slv->chn.client, GNUNET_YES,
+ &slave_cleanup, slv);
}
@@ -796,6 +880,7 @@
uint64_t start_message_id,
uint64_t end_message_id,
GNUNET_PSYC_MessageCallback message_cb,
+ GNUNET_PSYC_MessagePartCallback
message_part_cb,
GNUNET_PSYC_FinishCallback finish_cb,
void *cls)
{
Modified: gnunet/src/psyc/psyc_util_lib.c
===================================================================
--- gnunet/src/psyc/psyc_util_lib.c 2014-07-23 16:19:46 UTC (rev 34020)
+++ gnunet/src/psyc/psyc_util_lib.c 2014-07-23 16:19:49 UTC (rev 34021)
@@ -76,9 +76,13 @@
*
*/
const char *mod_value;
- size_t mod_value_size;
/**
+ * Number of bytes remaining to be transmitted from the current modifier
value.
+ */
+ uint32_t mod_value_remaining;
+
+ /**
* State of the current message being received from client.
*/
enum GNUNET_PSYC_MessageState state;
@@ -104,14 +108,14 @@
struct GNUNET_PSYC_ReceiveHandle
{
/**
- * Message part callback.
+ * Message callback.
*/
GNUNET_PSYC_MessageCallback message_cb;
/**
- * Message part callback for historic message.
+ * Message part callback.
*/
- GNUNET_PSYC_MessageCallback hist_message_cb;
+ GNUNET_PSYC_MessagePartCallback message_part_cb;
/**
* Closure for the callbacks.
@@ -149,6 +153,7 @@
uint32_t mod_value_size;
};
+
/**** Messages ****/
@@ -167,7 +172,7 @@
* @return Message header with size information,
* followed by the message parts.
*/
-struct GNUNET_MessageHeader *
+struct GNUNET_PSYC_Message *
GNUNET_PSYC_message_create (const char *method_name,
const struct GNUNET_ENV_Environment *env,
const void *data,
@@ -188,7 +193,7 @@
}
}
- struct GNUNET_MessageHeader *msg;
+ struct GNUNET_PSYC_Message *msg;
uint16_t method_name_size = strlen (method_name) + 1;
if (method_name_size == 1)
return NULL;
@@ -199,12 +204,13 @@
+ ((0 < data_size) ? sizeof (*pmsg) + data_size : 0)/* data */
+ sizeof (*pmsg); /* end of message */
msg = GNUNET_malloc (msg_size);
- msg->size = htons (msg_size);
- msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE);
+ msg->header.size = htons (msg_size);
+ msg->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE); /* FIXME */
pmeth = (struct GNUNET_PSYC_MessageMethod *) &msg[1];
+ pmeth->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD);
pmeth->header.size = htons (sizeof (*pmeth) + method_name_size);
- memcpy (pmeth, method_name, method_name_size);
+ memcpy (&pmeth[1], method_name, method_name_size);
uint16_t p = sizeof (*msg) + sizeof (*pmeth) + method_name_size;
if (NULL != env)
@@ -215,7 +221,7 @@
uint16_t mod_name_size = strlen (mod->name) + 1;
pmod = (struct GNUNET_PSYC_MessageModifier *) ((char *) msg + p);
pmod->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER);
- pmod->header.size = sizeof (*pmod) + mod_name_size + 1 + mod->value_size;
+ pmod->header.size = sizeof (*pmod) + mod_name_size + mod->value_size;
p += pmod->header.size;
pmod->header.size = htons (pmod->header.size);
@@ -241,6 +247,7 @@
pmsg->size = htons (sizeof (*pmsg));
pmsg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END);
+ GNUNET_assert (p + sizeof (*pmsg) == msg_size);
return msg;
}
@@ -276,8 +283,8 @@
uint16_t name_size = ntohs (mod->name_size);
char oper = ' ' < mod->oper ? mod->oper : ' ';
GNUNET_log (kind, "\t%c%.*s\t%.*s\n", oper, name_size, &mod[1],
- size - sizeof (*mod) - name_size - 1,
- ((char *) &mod[1]) + name_size + 1);
+ size - sizeof (*mod) - name_size,
+ ((char *) &mod[1]) + name_size);
break;
}
case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT:
@@ -331,7 +338,7 @@
uint16_t size = (NULL != msg) ? ntohs (msg->size) : 0;
LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Queueing message of type %u and size %u (end: %u)).\n",
+ "Queueing message part of type %u and size %u (end: %u)).\n",
ntohs (msg->type), size, end);
if (NULL != tmit->msg)
@@ -396,6 +403,9 @@
msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA);
int notify_ret = tmit->notify_data (tmit->notify_data_cls, &data_size,
&msg[1]);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "transmit_data (ret: %d, size: %u): %.*s\n",
+ notify_ret, data_size, data_size, &msg[1]);
switch (notify_ret)
{
case GNUNET_NO:
@@ -463,9 +473,15 @@
msg->size = sizeof (struct GNUNET_PSYC_MessageModifier);
notify_ret = tmit->notify_mod (tmit->notify_mod_cls, &data_size, &mod[1],
&mod->oper, &mod->value_size);
- mod->name_size = strnlen ((char *) &mod[1], data_size);
+
+ mod->name_size = strnlen ((char *) &mod[1], data_size) + 1;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "transmit_mod (ret: %d, size: %u + %u): %.*s\n",
+ notify_ret, mod->name_size, mod->value_size, data_size, &mod[1]);
if (mod->name_size < data_size)
{
+ tmit->mod_value_remaining
+ = mod->value_size - (data_size - mod->name_size);
mod->value_size = htonl (mod->value_size);
mod->name_size = htons (mod->name_size);
}
@@ -483,6 +499,10 @@
msg->size = sizeof (struct GNUNET_MessageHeader);
notify_ret = tmit->notify_mod (tmit->notify_mod_cls,
&data_size, &msg[1], NULL, NULL);
+ tmit->mod_value_remaining -= data_size;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "transmit_mod (ret: %d, size: %u): %.*s\n",
+ notify_ret, data_size, data_size, &msg[1]);
break;
}
default:
@@ -497,26 +517,19 @@
tmit->paused = GNUNET_YES;
return;
}
- tmit->state = GNUNET_PSYC_MESSAGE_STATE_MOD_CONT;
+ tmit->state
+ = (0 == tmit->mod_value_remaining)
+ ? GNUNET_PSYC_MESSAGE_STATE_MODIFIER
+ : GNUNET_PSYC_MESSAGE_STATE_MOD_CONT;
break;
- case GNUNET_YES:
- if (0 == data_size)
- {
- /* End of modifiers. */
- tmit->state = GNUNET_PSYC_MESSAGE_STATE_DATA;
- if (0 == tmit->acks_pending)
- transmit_data (tmit);
-
- return;
- }
- tmit->state = GNUNET_PSYC_MESSAGE_STATE_MODIFIER;
+ case GNUNET_YES: /* End of modifiers. */
+ GNUNET_assert (0 == tmit->mod_value_remaining);
break;
default:
LOG (GNUNET_ERROR_TYPE_ERROR,
- "TransmitNotifyModifier callback returned error "
- "when requesting a modifier.\n");
+ "TransmitNotifyModifier callback returned with error.\n");
tmit->state = GNUNET_PSYC_MESSAGE_STATE_CANCEL;
msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL);
@@ -533,7 +546,16 @@
transmit_queue_insert (tmit, msg, GNUNET_NO);
}
- transmit_mod (tmit);
+ if (GNUNET_YES == notify_ret)
+ {
+ tmit->state = GNUNET_PSYC_MESSAGE_STATE_DATA;
+ if (0 == tmit->acks_pending)
+ transmit_data (tmit);
+ }
+ else
+ {
+ transmit_mod (tmit);
+ }
}
@@ -547,9 +569,10 @@
size_t value_size = 0;
const char *value = NULL;
- if (NULL != oper && NULL != tmit->mod)
+ if (NULL != oper)
{ /* New modifier */
- tmit->mod = tmit->mod->next;
+ if (NULL != tmit->mod)
+ tmit->mod = tmit->mod->next;
if (NULL == tmit->mod)
{ /* No more modifiers, continue with data */
*data_size = 0;
@@ -559,30 +582,29 @@
GNUNET_assert (tmit->mod->value_size < UINT32_MAX);
*full_value_size = tmit->mod->value_size;
*oper = tmit->mod->oper;
- name_size = strlen (tmit->mod->name);
+ name_size = strlen (tmit->mod->name) + 1;
- if (name_size + 1 + tmit->mod->value_size <= *data_size)
+ if (name_size + tmit->mod->value_size <= *data_size)
{
- *data_size = name_size + 1 + tmit->mod->value_size;
+ *data_size = name_size + tmit->mod->value_size;
}
else
{
- tmit->mod_value_size = tmit->mod->value_size;
- value_size = *data_size - name_size - 1;
- tmit->mod_value_size -= value_size;
+ value_size = *data_size - name_size;
tmit->mod_value = tmit->mod->value + value_size;
}
memcpy (data, tmit->mod->name, name_size);
- ((char *)data)[name_size] = '\0';
- memcpy ((char *)data + name_size + 1, tmit->mod->value, value_size);
+ memcpy ((char *)data + name_size, tmit->mod->value, value_size);
+ return GNUNET_NO;
}
- else if (NULL != tmit->mod_value && 0 < tmit->mod_value_size)
+ else
{ /* Modifier continuation */
+ GNUNET_assert (NULL != tmit->mod_value && 0 < tmit->mod_value_remaining);
value = tmit->mod_value;
- if (tmit->mod_value_size <= *data_size)
+ if (tmit->mod_value_remaining <= *data_size)
{
- value_size = tmit->mod_value_size;
+ value_size = tmit->mod_value_remaining;
tmit->mod_value = NULL;
}
else
@@ -590,7 +612,6 @@
value_size = *data_size;
tmit->mod_value += value_size;
}
- tmit->mod_value_size -= value_size;
if (*data_size < value_size)
{
@@ -603,9 +624,8 @@
*data_size = value_size;
memcpy (data, value, value_size);
+ return (tmit->mod_value = NULL) ? GNUNET_YES : GNUNET_NO;
}
-
- return 0 == tmit->mod_value_size ? GNUNET_YES : GNUNET_NO;
}
@@ -663,10 +683,16 @@
{
tmit->notify_mod = &transmit_notify_env;
tmit->notify_mod_cls = tmit;
- tmit->mod
- = (NULL != env)
- ? GNUNET_ENV_environment_head (env)
- : NULL;
+ if (NULL != env)
+ {
+ struct GNUNET_ENV_Modifier mod = {};
+ mod.next = GNUNET_ENV_environment_head (env);
+ tmit->mod = &mod;
+ }
+ else
+ {
+ tmit->mod = NULL;
+ }
}
transmit_mod (tmit);
@@ -762,12 +788,12 @@
*/
struct GNUNET_PSYC_ReceiveHandle *
GNUNET_PSYC_receive_create (GNUNET_PSYC_MessageCallback message_cb,
- GNUNET_PSYC_MessageCallback hist_message_cb,
+ GNUNET_PSYC_MessagePartCallback message_part_cb,
void *cb_cls)
{
struct GNUNET_PSYC_ReceiveHandle *recv = GNUNET_malloc (sizeof (*recv));
recv->message_cb = message_cb;
- recv->hist_message_cb = hist_message_cb;
+ recv->message_part_cb = message_part_cb;
recv->cb_cls = cb_cls;
return recv;
}
@@ -800,13 +826,11 @@
static void
recv_error (struct GNUNET_PSYC_ReceiveHandle *recv)
{
- GNUNET_PSYC_MessageCallback message_cb
- = recv->flags & GNUNET_PSYC_MESSAGE_HISTORIC
- ? recv->hist_message_cb
- : recv->message_cb;
+ if (NULL != recv->message_part_cb)
+ recv->message_part_cb (recv->cb_cls, recv->message_id, 0, recv->flags,
NULL);
- if (NULL != message_cb)
- message_cb (recv->cb_cls, recv->message_id, recv->flags, NULL);
+ if (NULL != recv->message_cb)
+ recv->message_cb (recv->cb_cls, recv->message_id, recv->flags, NULL);
GNUNET_PSYC_receive_reset (recv);
}
@@ -827,6 +851,7 @@
{
uint16_t size = ntohs (msg->header.size);
uint32_t flags = ntohl (msg->flags);
+ uint64_t message_id;
GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG,
(struct GNUNET_MessageHeader *) msg);
@@ -858,6 +883,7 @@
recv_error (recv);
return GNUNET_SYSERR;
}
+ message_id = recv->message_id;
uint16_t pos = 0, psize = 0, ptype, size_eq, size_min;
@@ -964,10 +990,10 @@
uint16_t name_size = ntohs (mod->name_size);
recv->mod_value_size_expected = ntohl (mod->value_size);
- recv->mod_value_size = psize - sizeof (*mod) - name_size - 1;
+ recv->mod_value_size = psize - sizeof (*mod) - name_size;
- if (psize < sizeof (*mod) + name_size + 1
- || '\0' != *((char *) &mod[1] + name_size)
+ if (psize < sizeof (*mod) + name_size
+ || '\0' != *((char *) &mod[1] + name_size - 1)
|| recv->mod_value_size_expected < recv->mod_value_size)
{
LOG (GNUNET_ERROR_TYPE_WARNING, "Dropping malformed modifier.\n");
@@ -1018,14 +1044,10 @@
}
}
- GNUNET_PSYC_MessageCallback message_cb
- = recv->flags & GNUNET_PSYC_MESSAGE_HISTORIC
- ? recv->hist_message_cb
- : recv->message_cb;
+ if (NULL != recv->message_part_cb)
+ recv->message_part_cb (recv->cb_cls, recv->message_id, 0, // FIXME:
data_offset
+ recv->flags, pmsg);
- if (NULL != message_cb)
- message_cb (recv->cb_cls, recv->message_id, recv->flags, pmsg);
-
switch (ptype)
{
case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
@@ -1034,6 +1056,9 @@
break;
}
}
+
+ if (NULL != recv->message_cb)
+ recv->message_cb (recv->cb_cls, message_id, flags, msg);
return GNUNET_OK;
}
@@ -1063,6 +1088,7 @@
for (pos = 0; pos < data_size; pos += psize, parts++)
{
pmsg = (const struct GNUNET_MessageHeader *) (data + pos);
+ GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, pmsg);
psize = ntohs (pmsg->size);
ptype = ntohs (pmsg->type);
if (0 == parts && NULL != first_ptype)
@@ -1084,3 +1110,111 @@
}
return parts;
}
+
+
+struct ParseMessageClosure
+{
+ struct GNUNET_ENV_Environment *env;
+ const char **method_name;
+ const void **data;
+ uint16_t *data_size;
+ enum GNUNET_PSYC_MessageState msg_state;
+};
+
+
+static void
+parse_message_part_cb (void *cls, uint64_t message_id, uint64_t data_offset,
+ uint32_t flags, const struct GNUNET_MessageHeader *msg)
+{
+ struct ParseMessageClosure *pmc = cls;
+ if (NULL == msg)
+ {
+ pmc->msg_state = GNUNET_PSYC_MESSAGE_STATE_ERROR;
+ return;
+ }
+
+ switch (ntohs (msg->type))
+ {
+ case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD:
+ {
+ struct GNUNET_PSYC_MessageMethod *
+ pmeth = (struct GNUNET_PSYC_MessageMethod *) msg;
+ *pmc->method_name = (const char *) &pmeth[1];
+ pmc->msg_state = GNUNET_PSYC_MESSAGE_STATE_METHOD;
+ break;
+ }
+
+ case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER:
+ {
+ struct GNUNET_PSYC_MessageModifier *
+ pmod = (struct GNUNET_PSYC_MessageModifier *) msg;
+
+ const char *name = (const char *) &pmod[1];
+ const void *value = name + pmod->name_size;
+ GNUNET_ENV_environment_add (pmc->env, pmod->oper, name, value,
+ pmod->value_size);
+ pmc->msg_state = GNUNET_PSYC_MESSAGE_STATE_MODIFIER;
+ break;
+ }
+
+ case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA:
+ *pmc->data = &msg[1];
+ *pmc->data_size = ntohs (msg->size) - sizeof (*msg);
+ pmc->msg_state = GNUNET_PSYC_MESSAGE_STATE_DATA;
+ break;
+
+ case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
+ pmc->msg_state = GNUNET_PSYC_MESSAGE_STATE_END;
+ break;
+
+ default:
+ pmc->msg_state = GNUNET_PSYC_MESSAGE_STATE_ERROR;
+ }
+}
+
+
+/**
+ * Parse PSYC message.
+ *
+ * @param msg
+ * The PSYC message to parse.
+ * @param[out] method_name
+ * Pointer to the method name inside @a pmsg.
+ * @param env
+ * The environment for the message with a list of modifiers.
+ * @param[out] data
+ * Pointer to data inside @a pmsg.
+ * @param[out] data_size
+ * Size of @data is written here.
+ *
+ * @return #GNUNET_OK on success,
+ * #GNUNET_SYSERR on parse error.
+ */
+int
+GNUNET_PSYC_message_parse (const struct GNUNET_PSYC_Message *msg,
+ const char **method_name,
+ struct GNUNET_ENV_Environment *env,
+ const void **data,
+ uint16_t *data_size)
+{
+ struct ParseMessageClosure cls;
+ cls.env = env;
+ cls.method_name = method_name;
+ cls.data = data;
+ cls.data_size = data_size;
+
+ uint16_t msg_size = ntohs (msg->header.size);
+ struct GNUNET_PSYC_MessageHeader *
+ pmsg = GNUNET_malloc (sizeof (*pmsg) + msg_size - sizeof (*msg));
+ memcpy (&pmsg[1], &msg[1], msg_size - sizeof (*msg));
+
+ struct GNUNET_PSYC_ReceiveHandle *
+ recv = GNUNET_PSYC_receive_create (NULL, &parse_message_part_cb, &cls);
+ GNUNET_PSYC_receive_message (recv, pmsg);
+ GNUNET_PSYC_receive_destroy (recv);
+ GNUNET_free (pmsg);
+
+ return (GNUNET_PSYC_MESSAGE_STATE_END == cls.msg_state)
+ ? GNUNET_OK
+ : GNUNET_SYSERR;
+}
Modified: gnunet/src/psyc/test_psyc.c
===================================================================
--- gnunet/src/psyc/test_psyc.c 2014-07-23 16:19:46 UTC (rev 34020)
+++ gnunet/src/psyc/test_psyc.c 2014-07-23 16:19:49 UTC (rev 34021)
@@ -62,8 +62,6 @@
static struct GNUNET_CRYPTO_EddsaPublicKey channel_pub_key;
static struct GNUNET_CRYPTO_EcdsaPublicKey slave_pub_key;
-struct GNUNET_PSYC_MasterTransmitHandle *mth;
-
struct TransmitClosure
{
struct GNUNET_PSYC_MasterTransmitHandle *mst_tmit;
@@ -95,6 +93,28 @@
master_transmit ();
+void master_stopped (void *cls)
+{
+ if (NULL != tmit)
+ {
+ GNUNET_ENV_environment_destroy (tmit->env);
+ GNUNET_free (tmit);
+ tmit = NULL;
+ }
+ GNUNET_SCHEDULER_shutdown ();
+}
+
+void slave_parted (void *cls)
+{
+ if (NULL != mst)
+ {
+ GNUNET_PSYC_master_stop (mst, GNUNET_NO, &master_stopped, NULL);
+ mst = NULL;
+ }
+ else
+ master_stopped (NULL);
+}
+
/**
* Clean up all resources used.
*/
@@ -103,21 +123,11 @@
{
if (NULL != slv)
{
- GNUNET_PSYC_slave_part (slv);
+ GNUNET_PSYC_slave_part (slv, GNUNET_NO, &slave_parted, NULL);
slv = NULL;
}
- if (NULL != mst)
- {
- GNUNET_PSYC_master_stop (mst);
- mst = NULL;
- }
- if (NULL != tmit)
- {
- GNUNET_ENV_environment_destroy (tmit->env);
- GNUNET_free (tmit);
- tmit = NULL;
- }
- GNUNET_SCHEDULER_shutdown ();
+ else
+ slave_parted (NULL);
}
@@ -171,8 +181,21 @@
static void
master_message_cb (void *cls, uint64_t message_id, uint32_t flags,
- const struct GNUNET_MessageHeader *msg)
+ const struct GNUNET_PSYC_MessageHeader *msg)
{
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Master got PSYC message fragment of size %u "
+ "belonging to message ID %llu with flags %x\n",
+ ntohs (msg->header.size), message_id, flags);
+ // FIXME
+}
+
+
+static void
+master_message_part_cb (void *cls, uint64_t message_id,
+ uint64_t data_offset, uint32_t flags,
+ const struct GNUNET_MessageHeader *msg)
+{
if (NULL == msg)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -215,8 +238,21 @@
static void
slave_message_cb (void *cls, uint64_t message_id, uint32_t flags,
- const struct GNUNET_MessageHeader *msg)
+ const struct GNUNET_PSYC_MessageHeader *msg)
{
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Slave got PSYC message fragment of size %u "
+ "belonging to message ID %llu with flags %x\n",
+ ntohs (msg->header.size), message_id, flags);
+ // FIXME
+}
+
+
+static void
+slave_message_part_cb (void *cls, uint64_t message_id,
+ uint64_t data_offset, uint32_t flags,
+ const struct GNUNET_MessageHeader *msg)
+{
if (NULL == msg)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -371,7 +407,7 @@
memcpy (data, value, value_size);
}
- return 0 == tmit->mod_value_size ? GNUNET_YES : GNUNET_NO;
+ return GNUNET_NO;
}
@@ -380,8 +416,10 @@
static void
-join_decision_cb (void *cls, int is_admitted,
- const struct GNUNET_PSYC_MessageHeader *join_msg)
+join_decision_cb (void *cls,
+ const struct GNUNET_PSYC_JoinDecisionMessage *dcsn,
+ int is_admitted,
+ const struct GNUNET_PSYC_Message *join_msg)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Slave got join decision: %d\n", is_admitted);
@@ -415,8 +453,10 @@
static void
-join_request_cb (void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey
*slave_key,
- const struct GNUNET_PSYC_MessageHeader *msg,
+join_request_cb (void *cls,
+ const struct GNUNET_PSYC_JoinRequestMessage *req,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
+ const struct GNUNET_PSYC_Message *join_msg,
struct GNUNET_PSYC_JoinHandle *jh)
{
struct GNUNET_HashCode slave_key_hash;
@@ -450,11 +490,11 @@
"_foo", "bar baz", 7);
GNUNET_ENV_environment_add (env, GNUNET_ENV_OP_ASSIGN,
"_foo_bar", "foo bar baz", 11);
- struct GNUNET_MessageHeader *
+ 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, &slave_message_cb,
+ slv = GNUNET_PSYC_slave_join (cfg, &channel_pub_key, slave_key, &origin, 0,
NULL,
+ &slave_message_cb, &slave_message_part_cb,
&slave_connect_cb, &join_decision_cb, NULL,
join_msg);
GNUNET_ENV_environment_destroy (env);
@@ -551,7 +591,8 @@
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Starting master.\n");
mst = GNUNET_PSYC_master_start (cfg, channel_key,
GNUNET_PSYC_CHANNEL_PRIVATE,
&master_start_cb, &join_request_cb,
- &master_message_cb, NULL);
+ &master_message_cb, &master_message_part_cb,
+ NULL);
}
Modified: gnunet/src/social/Makefile.am
===================================================================
--- gnunet/src/social/Makefile.am 2014-07-23 16:19:46 UTC (rev 34020)
+++ gnunet/src/social/Makefile.am 2014-07-23 16:19:49 UTC (rev 34021)
@@ -24,6 +24,11 @@
libgnunetsocial_la_LIBADD = \
$(top_builddir)/src/util/libgnunetutil.la \
$(top_builddir)/src/env/libgnunetenv.la \
+ $(top_builddir)/src/psyc/libgnunetpsycutil.la \
+ $(top_builddir)/src/core/libgnunetcore.la \
+ $(top_builddir)/src/identity/libgnunetidentity.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
$(GN_LIBINTL) $(XLIB)
libgnunetsocial_la_LDFLAGS = \
$(GN_LIB_LDFLAGS) $(WINFLAGS) \
Modified: gnunet/src/social/gnunet-service-social.c
===================================================================
--- gnunet/src/social/gnunet-service-social.c 2014-07-23 16:19:46 UTC (rev
34020)
+++ gnunet/src/social/gnunet-service-social.c 2014-07-23 16:19:49 UTC (rev
34021)
@@ -32,6 +32,7 @@
#include "gnunet_protocols.h"
#include "gnunet_statistics_service.h"
#include "gnunet_psyc_service.h"
+#include "gnunet_psyc_util_lib.h"
#include "gnunet_social_service.h"
#include "social.h"
@@ -71,41 +72,56 @@
/**
- * Message in the transmission queue.
+ * Message fragment transmission queue.
*/
-struct TransmitMessage
+struct FragmentTransmitQueue
{
- struct TransmitMessage *prev;
- struct TransmitMessage *next;
+ struct FragmentTransmitQueue *prev;
+ struct FragmentTransmitQueue *next;
struct GNUNET_SERVER_Client *client;
/**
- * ID assigned to the message.
+ * Pointer to the next message part inside the data after this struct.
*/
- uint64_t id;
+ struct GNUNET_MessageHeader *next_part;
/**
- * Size of @a buf
+ * Size of message.
*/
uint16_t size;
/**
- * @see enum MessageState
+ * @see enum GNUNET_PSYC_MessageState
*/
uint8_t state;
- /* Followed by message */
+ /* Followed by one or more message parts. */
};
/**
+ * Message transmission queue.
+ */
+struct MessageTransmitQueue
+{
+ struct MessageTransmitQueue *prev;
+ struct MessageTransmitQueue *next;
+
+ struct FragmentTransmitQueue *frags_head;
+ struct FragmentTransmitQueue *frags_tail;
+
+ struct GNUNET_SERVER_Client *client;
+};
+
+/**
* List of connected clients.
*/
-struct ClientList
+struct ClientListItem
{
- struct ClientList *prev;
- struct ClientList *next;
+ struct ClientListItem *prev;
+ struct ClientListItem *next;
+
struct GNUNET_SERVER_Client *client;
};
@@ -115,11 +131,11 @@
*/
struct Place
{
- struct ClientList *clients_head;
- struct ClientList *clients_tail;
+ struct ClientListItem *clients_head;
+ struct ClientListItem *clients_tail;
- struct TransmitMessage *tmit_head;
- struct TransmitMessage *tmit_tail;
+ struct MessageTransmitQueue *tmit_msgs_head;
+ struct MessageTransmitQueue *tmit_msgs_tail;
/**
* Public key of the channel.
@@ -132,9 +148,27 @@
struct GNUNET_HashCode pub_key_hash;
/**
+ * Last message ID received for the place.
+ * 0 if there is no such message.
+ */
+ uint64_t max_message_id;
+
+ /**
* Is this a host (#GNUNET_YES), or guest (#GNUNET_NO)?
*/
uint8_t is_host;
+
+ /**
+ * Is this place ready to receive messages from client?
+ * #GNUNET_YES or #GNUNET_NO
+ */
+ uint8_t is_ready;
+
+ /**
+ * Is the client disconnected?
+ * #GNUNET_YES or #GNUNET_NO
+ */
+ uint8_t is_disconnected;
};
@@ -146,7 +180,7 @@
/**
* Place struct common for Host and Guest
*/
- struct Place pl;
+ struct Place plc;
/**
* Private key of the channel.
@@ -184,17 +218,17 @@
/**
* Place struct common for Host and Guest.
*/
- struct Place pl;
+ struct Place plc;
/**
* Private key of the slave.
*/
- struct GNUNET_CRYPTO_EddsaPrivateKey priv_key;
+ struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
/**
* Public key of the slave.
*/
- struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
+ struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
/**
* Hash of @a pub_key.
@@ -230,13 +264,34 @@
* Join request to be transmitted to the master on join.
*/
struct GNUNET_MessageHeader *join_req;
+
+ /**
+ * Join decision received from PSYC.
+ */
+ struct GNUNET_PSYC_JoinDecisionMessage *join_dcsn;
+
};
-static inline void
-transmit_message (struct Place *pl);
+struct Client
+{
+ /**
+ * Place where the client entered.
+ */
+ struct Place *plc;
+ /**
+ * Message queue for the message currently being transmitted
+ * by this client.
+ */
+ struct MessageTransmitQueue *tmit_msg;
+};
+
+static int
+psyc_transmit_message (struct Place *plc);
+
+
/**
* Task run during shutdown.
*
@@ -265,12 +320,12 @@
static void
cleanup_host (struct Host *hst)
{
- struct Place *pl = &hst->pl;
+ struct Place *plc = &hst->plc;
if (NULL != hst->master)
- GNUNET_PSYC_master_stop (hst->master);
+ GNUNET_PSYC_master_stop (hst->master, GNUNET_NO, NULL, NULL); // FIXME
GNUNET_CONTAINER_multihashmap_destroy (hst->join_reqs);
- GNUNET_CONTAINER_multihashmap_remove (hosts, &pl->pub_key_hash, pl);
+ GNUNET_CONTAINER_multihashmap_remove (hosts, &plc->pub_key_hash, plc);
}
@@ -280,28 +335,28 @@
static void
cleanup_guest (struct Guest *gst)
{
- struct Place *pl = &gst->pl;
+ struct Place *plc = &gst->plc;
struct GNUNET_CONTAINER_MultiHashMap *
- pl_gst = GNUNET_CONTAINER_multihashmap_get (place_guests,
- &pl->pub_key_hash);
- GNUNET_assert (NULL != pl_gst);
- GNUNET_CONTAINER_multihashmap_remove (pl_gst, &gst->pub_key_hash, gst);
+ plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests,
+ &plc->pub_key_hash);
+ GNUNET_assert (NULL != plc_gst);
+ GNUNET_CONTAINER_multihashmap_remove (plc_gst, &gst->pub_key_hash, gst);
- if (0 == GNUNET_CONTAINER_multihashmap_size (pl_gst))
+ if (0 == GNUNET_CONTAINER_multihashmap_size (plc_gst))
{
- GNUNET_CONTAINER_multihashmap_remove (place_guests, &pl->pub_key_hash,
- pl_gst);
- GNUNET_CONTAINER_multihashmap_destroy (pl_gst);
+ GNUNET_CONTAINER_multihashmap_remove (place_guests, &plc->pub_key_hash,
+ plc_gst);
+ GNUNET_CONTAINER_multihashmap_destroy (plc_gst);
}
- GNUNET_CONTAINER_multihashmap_remove (guests, &pl->pub_key_hash, gst);
+ GNUNET_CONTAINER_multihashmap_remove (guests, &plc->pub_key_hash, gst);
if (NULL != gst->join_req)
GNUNET_free (gst->join_req);
if (NULL != gst->relays)
GNUNET_free (gst->relays);
if (NULL != gst->slave)
- GNUNET_PSYC_slave_part (gst->slave);
- GNUNET_CONTAINER_multihashmap_remove (guests, &pl->pub_key_hash, pl);
+ GNUNET_PSYC_slave_part (gst->slave, GNUNET_NO, NULL, NULL); // FIXME
+ GNUNET_CONTAINER_multihashmap_remove (guests, &plc->pub_key_hash, plc);
}
@@ -309,15 +364,26 @@
* Clean up place data structures after a client disconnected.
*/
static void
-cleanup_place (struct Place *pl)
+cleanup_place (struct Place *plc)
{
- (GNUNET_YES == pl->is_host)
- ? cleanup_host ((struct Host *) pl)
- : cleanup_guest ((struct Guest *) pl);
- GNUNET_free (pl);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%p Cleaning up place %s\n",
+ plc, GNUNET_h2s (&plc->pub_key_hash));
+
+ (GNUNET_YES == plc->is_host)
+ ? cleanup_host ((struct Host *) plc)
+ : cleanup_guest ((struct Guest *) plc);
+ GNUNET_free (plc);
}
+static void
+schedule_cleanup_place (void *cls, const struct GNUNET_SCHEDULER_TaskContext
*tc)
+{
+ cleanup_place (cls);
+}
+
+
/**
* Called whenever a client is disconnected.
* Frees our resources associated with that client.
@@ -331,76 +397,1073 @@
if (NULL == client)
return;
- struct Place *
- pl = GNUNET_SERVER_client_get_user_context (client, struct Place);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%p Client (%s) disconnected from place %s\n",
- pl, (GNUNET_YES == pl->is_host) ? "host" : "guest",
- GNUNET_h2s (&pl->pub_key_hash));
-
- if (NULL == pl)
+ struct Client *
+ ctx = GNUNET_SERVER_client_get_user_context (client, struct Client);
+ if (NULL == ctx)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "%p User context is NULL in client_disconnect()\n", pl);
+ "%p User context is NULL in client_disconnect()\n", ctx);
GNUNET_break (0);
return;
}
- struct ClientList *cl = pl->clients_head;
- while (NULL != cl)
+ struct Place *plc = ctx->plc;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%p Client (%s) disconnected from place %s\n",
+ plc, (GNUNET_YES == plc->is_host) ? "host" : "guest",
+ GNUNET_h2s (&plc->pub_key_hash));
+
+ struct ClientListItem *cli = plc->clients_head;
+ while (NULL != cli)
{
- if (cl->client == client)
+ if (cli->client == client)
{
- GNUNET_CONTAINER_DLL_remove (pl->clients_head, pl->clients_tail, cl);
- GNUNET_free (cl);
+ GNUNET_CONTAINER_DLL_remove (plc->clients_head, plc->clients_tail, cli);
+ GNUNET_free (cli);
break;
}
- cl = cl->next;
+ cli = cli->next;
}
- if (NULL == pl->clients_head)
+ if (NULL == plc->clients_head)
{ /* Last client disconnected. */
- if (NULL != pl->tmit_head)
- { /* Send pending messages to PSYC before cleanup. */
- //FIXME: transmit_message (pl);
+ if (GNUNET_YES != plc->is_disconnected)
+ {
+ plc->is_disconnected = GNUNET_YES;
+ if (NULL != plc->tmit_msgs_head)
+ { /* Send pending messages to PSYC before cleanup. */
+ psyc_transmit_message (plc);
+ }
+ else
+ {
+ cleanup_place (plc);
+ }
}
- else
+ }
+}
+
+
+/**
+ * Send message to all clients connected to the channel.
+ */
+static void
+client_send_msg (const struct Place *plc,
+ const struct GNUNET_MessageHeader *msg)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "%p Sending message to clients.\n", plc);
+
+ struct ClientListItem *cli = plc->clients_head;
+ while (NULL != cli)
+ {
+ GNUNET_SERVER_notification_context_add (nc, cli->client);
+ GNUNET_SERVER_notification_context_unicast (nc, cli->client, msg,
GNUNET_NO);
+ cli = cli->next;
+ }
+}
+
+
+/**
+ * Called after a PSYC master is started.
+ */
+static void
+psyc_master_started (void *cls, uint64_t max_message_id)
+{
+ struct Host *hst = cls;
+ struct Place *plc = &hst->plc;
+ plc->max_message_id = max_message_id;
+ plc->is_ready = GNUNET_YES;
+
+ struct CountersResult res;
+ res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK);
+ res.header.size = htons (sizeof (res));
+ res.result_code = htonl (GNUNET_OK);
+ res.max_message_id = GNUNET_htonll (plc->max_message_id);
+
+ client_send_msg (plc, &res.header);
+}
+
+
+/**
+ * Called when a PSYC master receives a join request.
+ */
+static void
+psyc_recv_join_request (void *cls,
+ const struct GNUNET_PSYC_JoinRequestMessage *req,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
+ const struct GNUNET_PSYC_Message *join_msg,
+ struct GNUNET_PSYC_JoinHandle *jh)
+{
+ struct Host *hst = cls;
+ struct GNUNET_HashCode slave_key_hash;
+ GNUNET_CRYPTO_hash (slave_key, sizeof (*slave_key), &slave_key_hash);
+ GNUNET_CONTAINER_multihashmap_put (hst->join_reqs, &slave_key_hash, jh,
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+ client_send_msg (&hst->plc, &req->header);
+}
+
+
+/**
+ * Called after a PSYC slave is connected.
+ */
+static void
+psyc_slave_connected (void *cls, uint64_t max_message_id)
+{
+ struct Guest *gst = cls;
+ struct Place *plc = &gst->plc;
+ plc->max_message_id = max_message_id;
+ plc->is_ready = GNUNET_YES;
+
+ struct CountersResult res;
+ res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK);
+ res.header.size = htons (sizeof (res));
+ res.result_code = htonl (GNUNET_OK);
+ res.max_message_id = GNUNET_htonll (plc->max_message_id);
+
+ client_send_msg (plc, &res.header);
+}
+
+
+/**
+ * Called when a PSYC slave receives a join decision.
+ */
+static void
+psyc_recv_join_dcsn (void *cls,
+ const struct GNUNET_PSYC_JoinDecisionMessage *dcsn,
+ int is_admitted,
+ const struct GNUNET_PSYC_Message *join_msg)
+{
+ struct Guest *gst = cls;
+ client_send_msg (&gst->plc, &dcsn->header);
+}
+
+
+/**
+ * Called when a PSYC master or slave receives a message.
+ */
+static void
+psyc_recv_message (void *cls,
+ uint64_t message_id,
+ uint32_t flags,
+ const struct GNUNET_PSYC_MessageHeader *msg)
+{
+ struct Place *plc = cls;
+ client_send_msg (plc, &msg->header);
+
+ /* FIXME: further processing */
+}
+
+
+/**
+ * Initialize place data structure.
+ */
+static void
+place_init (struct Place *plc)
+{
+
+}
+
+
+/**
+ * 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 *req
+ = (const struct HostEnterRequest *) msg;
+
+ struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
+ struct GNUNET_HashCode pub_key_hash;
+
+ GNUNET_CRYPTO_eddsa_key_get_public (&req->place_key, &pub_key);
+ GNUNET_CRYPTO_hash (&pub_key, sizeof (pub_key), &pub_key_hash);
+
+ struct Host *
+ hst = GNUNET_CONTAINER_multihashmap_get (hosts, &pub_key_hash);
+ struct Place *plc;
+
+ if (NULL == hst)
+ {
+ hst = GNUNET_new (struct Host);
+ hst->policy = ntohl (req->policy);
+ hst->priv_key = req->place_key;
+ hst->join_reqs = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
+
+ plc = &hst->plc;
+ plc->is_host = GNUNET_YES;
+ plc->pub_key = pub_key;
+ plc->pub_key_hash = pub_key_hash;
+ place_init (plc);
+
+ GNUNET_CONTAINER_multihashmap_put (hosts, &plc->pub_key_hash, plc,
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+ hst->master = GNUNET_PSYC_master_start (cfg, &hst->priv_key, hst->policy,
+ &psyc_master_started,
+ &psyc_recv_join_request,
+ &psyc_recv_message, NULL, hst);
+ }
+ else
+ {
+ plc = &hst->plc;
+
+ struct CountersResult res;
+ res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK);
+ res.header.size = htons (sizeof (res));
+ res.result_code = htonl (GNUNET_OK);
+ res.max_message_id = GNUNET_htonll (plc->max_message_id);
+
+ GNUNET_SERVER_notification_context_add (nc, client);
+ GNUNET_SERVER_notification_context_unicast (nc, client, &res.header,
+ GNUNET_NO);
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "%p Client connected as host to place %s.\n",
+ hst, GNUNET_h2s (&plc->pub_key_hash));
+
+ struct ClientListItem *cli = GNUNET_new (struct ClientListItem);
+ cli->client = client;
+ GNUNET_CONTAINER_DLL_insert (plc->clients_head, plc->clients_tail, cli);
+
+ struct Client *ctx = GNUNET_new (struct Client);
+ ctx->plc = plc;
+ GNUNET_SERVER_client_set_user_context (client, ctx);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
+ * 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 *req
+ = (const struct GuestEnterRequest *) msg;
+ uint16_t req_size = ntohs (req->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);
+ 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);
+
+ struct GNUNET_CONTAINER_MultiHashMap *
+ plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests, &pub_key_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->pub_key = gst_pub_key;
+ gst->pub_key_hash = gst_pub_key_hash;
+ gst->origin = req->origin;
+ gst->relay_count = ntohl (req->relay_count);
+
+ const struct GNUNET_PeerIdentity *
+ relays = (const struct GNUNET_PeerIdentity *) &req[1];
+ uint16_t relay_size = gst->relay_count * sizeof (*relays);
+ struct GNUNET_PSYC_Message *join_msg = NULL;
+ uint16_t join_msg_size = 0;
+
+ if (sizeof (*req) + relay_size + sizeof (struct GNUNET_MessageHeader)
+ <= req_size)
{
- cleanup_place (pl);
+ join_msg = (struct GNUNET_PSYC_Message *)
+ (((char *) &req[1]) + relay_size);
+ join_msg_size = ntohs (join_msg->header.size);
}
+ if (sizeof (*req) + relay_size + join_msg_size != req_size)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "%u + %u + %u != %u\n",
+ sizeof (*req), relay_size, join_msg_size, req_size);
+ GNUNET_break (0);
+ GNUNET_SERVER_client_disconnect (client);
+ return;
+ }
+ if (0 < gst->relay_count)
+ {
+ gst->relays = GNUNET_malloc (relay_size);
+ memcpy (gst->relays, &req[1], relay_size);
+ }
+
+ plc = &gst->plc;
+ plc->is_host = GNUNET_NO;
+ plc->pub_key = req->place_key;
+ plc->pub_key_hash = pub_key_hash;
+ place_init (plc);
+
+ if (NULL == plc_gst)
+ {
+ plc_gst = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
+ GNUNET_CONTAINER_multihashmap_put (place_guests, &plc->pub_key_hash,
plc_gst,
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+ }
+ GNUNET_CONTAINER_multihashmap_put (plc_gst, &gst->pub_key_hash, plc,
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+ GNUNET_CONTAINER_multihashmap_put (guests, &plc->pub_key_hash, plc,
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+ gst->slave
+ = GNUNET_PSYC_slave_join (cfg, &plc->pub_key, &gst->priv_key,
+ &gst->origin, gst->relay_count, gst->relays,
+ &psyc_recv_message, NULL,
&psyc_slave_connected,
+ &psyc_recv_join_dcsn, gst, join_msg);
}
+ else
+ {
+ plc = &gst->plc;
+
+ struct CountersResult res;
+ res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK);
+ res.header.size = htons (sizeof (res));
+ res.result_code = htonl (GNUNET_OK);
+ res.max_message_id = GNUNET_htonll (plc->max_message_id);
+
+ GNUNET_SERVER_notification_context_add (nc, client);
+ GNUNET_SERVER_notification_context_unicast (nc, client, &res.header,
+ GNUNET_NO);
+ if (NULL != gst->join_dcsn)
+ {
+ GNUNET_SERVER_notification_context_add (nc, client);
+ GNUNET_SERVER_notification_context_unicast (nc, client,
+ &gst->join_dcsn->header,
+ GNUNET_NO);
+ }
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%p Client connected as guest to place %s.\n",
+ gst, GNUNET_h2s (&plc->pub_key_hash));
+
+ struct ClientListItem *cli = GNUNET_new (struct ClientListItem);
+ cli->client = client;
+ GNUNET_CONTAINER_DLL_insert (plc->clients_head, plc->clients_tail, cli);
+
+ struct Client *ctx = GNUNET_new (struct Client);
+ ctx->plc = plc;
+ GNUNET_SERVER_client_set_user_context (client, ctx);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
+struct JoinDecisionClosure
+{
+ int32_t is_admitted;
+ struct GNUNET_PSYC_Message *msg;
+};
+
+
+/**
+ * Iterator callback for responding to join requests.
+ */
+static int
+psyc_send_join_decision (void *cls, const struct GNUNET_HashCode *pub_key_hash,
+ void *value)
+{
+ struct JoinDecisionClosure *jcls = cls;
+ struct GNUNET_PSYC_JoinHandle *jh = value;
+ // FIXME: add relays
+ GNUNET_PSYC_join_decision (jh, jcls->is_admitted, 0, NULL, jcls->msg);
+ return GNUNET_YES;
+}
+
+
+/**
+ * Handle an entry decision from a host client.
+ */
static void
-client_home_enter (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *msg)
+client_recv_join_decision (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *msg)
{
+ struct Client *
+ ctx = GNUNET_SERVER_client_get_user_context (client, struct Client);
+ GNUNET_assert (NULL != ctx);
+ struct Place *plc = ctx->plc;
+ GNUNET_assert (GNUNET_YES == plc->is_host);
+ struct Host *hst = (struct Host *) plc;
+ struct GNUNET_PSYC_JoinDecisionMessage *
+ dcsn = (struct GNUNET_PSYC_JoinDecisionMessage *) msg;
+ struct JoinDecisionClosure jcls;
+ jcls.is_admitted = ntohl (dcsn->is_admitted);
+ jcls.msg
+ = (sizeof (*dcsn) + sizeof (*jcls.msg) <= ntohs (msg->size))
+ ? (struct GNUNET_PSYC_Message *) &dcsn[1]
+ : NULL;
+
+ struct GNUNET_HashCode slave_key_hash;
+ GNUNET_CRYPTO_hash (&dcsn->slave_key, sizeof (dcsn->slave_key),
+ &slave_key_hash);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%p Got join decision (%d) from client for place %s..\n",
+ hst, jcls.is_admitted, GNUNET_h2s (&plc->pub_key_hash));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%p ..and slave %s.\n",
+ hst, GNUNET_h2s (&slave_key_hash));
+
+ GNUNET_CONTAINER_multihashmap_get_multiple (hst->join_reqs, &slave_key_hash,
+ &psyc_send_join_decision, &jcls);
+ GNUNET_CONTAINER_multihashmap_remove_all (hst->join_reqs, &slave_key_hash);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
+/**
+ * Send acknowledgement to a client.
+ *
+ * Sent after a message fragment has been passed on to multicast.
+ *
+ * @param plc The place struct for the client.
+ */
static void
-client_place_enter (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *msg)
+send_message_ack (struct Place *plc, struct GNUNET_SERVER_Client *client)
{
+ struct GNUNET_MessageHeader res;
+ res.size = htons (sizeof (res));
+ res.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK);
+ GNUNET_SERVER_notification_context_add (nc, client);
+ GNUNET_SERVER_notification_context_unicast (nc, client, &res, GNUNET_NO);
}
+/**
+ * Proceed to the next message part in the transmission queue.
+ *
+ * @param plc
+ * Place where the transmission is going on.
+ * @param tmit_msg
+ * Currently transmitted message.
+ * @param tmit_frag
+ * Currently transmitted message fragment.
+ *
+ * @return @a tmit_frag, or NULL if reached the end of fragment.
+ */
+static struct FragmentTransmitQueue *
+psyc_transmit_queue_next_part (struct Place *plc,
+ struct MessageTransmitQueue *tmit_msg,
+ struct FragmentTransmitQueue *tmit_frag)
+{
+ uint16_t psize = ntohs (tmit_frag->next_part->size);
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "%p psyc_transmit_queue_next_part: %x + %u - %x = %u < %u\n",
+ plc, tmit_frag->next_part, psize, &tmit_frag[1],
+ (char *) tmit_frag->next_part + psize - ((char *) &tmit_frag[1]),
+ tmit_frag->size);
+ if ((char *) tmit_frag->next_part + psize - ((char *) &tmit_frag[1])
+ < tmit_frag->size)
+ {
+ tmit_frag->next_part
+ = (struct GNUNET_MessageHeader *) ((char *) tmit_frag->next_part +
psize);
+ }
+ else /* Reached end of current fragment. */
+ {
+ if (NULL != tmit_frag->client)
+ send_message_ack (plc, tmit_frag->client);
+ GNUNET_CONTAINER_DLL_remove (tmit_msg->frags_head, tmit_msg->frags_tail,
tmit_frag);
+ GNUNET_free (tmit_frag);
+ tmit_frag = NULL;
+ }
+ return tmit_frag;
+}
+
+
+/**
+ * Proceed to next message in transmission queue.
+ *
+ * @param plc
+ * Place where the transmission is going on.
+ * @param tmit_msg
+ * Currently transmitted message.
+ *
+ * @return The next message in queue, or NULL if queue is empty.
+ */
+static struct MessageTransmitQueue *
+psyc_transmit_queue_next_msg (struct Place *plc,
+ struct MessageTransmitQueue *tmit_msg)
+{
+ GNUNET_CONTAINER_DLL_remove (plc->tmit_msgs_head, plc->tmit_msgs_tail,
tmit_msg);
+ GNUNET_free (tmit_msg);
+ return plc->tmit_msgs_head;
+}
+
+
+/**
+ * Callback for data transmission to PSYC.
+ */
+static int
+psyc_transmit_notify_data (void *cls, uint16_t *data_size, void *data)
+{
+ struct Place *plc = cls;
+ struct MessageTransmitQueue *tmit_msg = plc->tmit_msgs_head;
+ GNUNET_assert (NULL != tmit_msg);
+ struct FragmentTransmitQueue *tmit_frag = tmit_msg->frags_head;
+ if (NULL == tmit_frag)
+ { /* Rest of the message have not arrived yet, pause transmission */
+ *data_size = 0;
+ return GNUNET_NO;
+ }
+ struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part;
+ if (NULL == pmsg)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%p psyc_transmit_notify_data: nothing to send.\n", plc);
+ *data_size = 0;
+ return GNUNET_NO;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%p psyc_transmit_notify_data()\n", plc);
+ GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, pmsg);
+
+ uint16_t ptype = ntohs (pmsg->type);
+ uint16_t pdata_size = ntohs (pmsg->size) - sizeof (*pmsg);
+ int ret;
+
+ switch (ptype)
+ {
+ case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA:
+ if (*data_size < pdata_size)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%p psyc_transmit_notify_data: buffer size too small for
data.\n", plc);
+ *data_size = 0;
+ return GNUNET_NO;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%p psyc_transmit_notify_data: sending %u bytes.\n",
+ plc, pdata_size);
+
+ *data_size = pdata_size;
+ memcpy (data, &pmsg[1], *data_size);
+ ret = GNUNET_NO;
+ break;
+
+ case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
+ case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
+ *data_size = 0;
+ ret = GNUNET_YES;
+ break;
+
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "%p psyc_transmit_notify_data: unexpected message part of type
%u.\n",
+ plc, ptype);
+ ret = GNUNET_SYSERR;
+ }
+
+ if (GNUNET_SYSERR == ret)
+ {
+ *data_size = 0;
+ tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
+ plc->is_disconnected = GNUNET_YES;
+ GNUNET_SERVER_client_disconnect (tmit_frag->client);
+ GNUNET_SCHEDULER_add_now (&schedule_cleanup_place, plc);
+ return ret;
+ }
+ else
+ {
+ psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag);
+
+ if (NULL == tmit_msg->frags_head
+ && GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype)
+ { /* Reached end of current message. */
+ tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
+ }
+ }
+
+ if (ret != GNUNET_NO)
+ {
+ if (NULL != tmit_msg)
+ {
+ psyc_transmit_message (plc);
+ }
+ else if (GNUNET_YES == plc->is_disconnected)
+ {
+ /* FIXME: handle partial message (when still in_transmit) */
+ cleanup_place (plc);
+ }
+ }
+ return ret;
+}
+
+
+/**
+ * Callback for modifier transmission to PSYC.
+ */
+static int
+psyc_transmit_notify_mod (void *cls, uint16_t *data_size, void *data,
+ uint8_t *oper, uint32_t *full_value_size)
+{
+ struct Place *plc = cls;
+ struct MessageTransmitQueue *tmit_msg = plc->tmit_msgs_head;
+ GNUNET_assert (NULL != tmit_msg);
+ struct FragmentTransmitQueue *tmit_frag = tmit_msg->frags_head;
+ if (NULL == tmit_frag)
+ { /* Rest of the message have not arrived yet, pause transmission */
+ *data_size = 0;
+ return GNUNET_NO;
+ }
+ struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part;
+ if (NULL == pmsg)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%p psyc_transmit_notify_mod: nothing to send.\n", plc);
+ *data_size = 0;
+ return GNUNET_NO;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%p psyc_transmit_notify_mod()\n", plc);
+ GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, pmsg);
+
+ uint16_t ptype = ntohs (pmsg->type);
+ int ret;
+
+ switch (ptype)
+ {
+ case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER:
+ {
+ if (NULL == oper)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "%p psyc_transmit_notify_mod: oper is NULL.\n", plc);
+ ret = GNUNET_SYSERR;
+ break;
+ }
+ struct GNUNET_PSYC_MessageModifier *
+ pmod = (struct GNUNET_PSYC_MessageModifier *) tmit_frag->next_part;
+ uint16_t mod_size = ntohs (pmod->header.size) - sizeof (*pmod);
+
+ if (*data_size < mod_size)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%p psyc_transmit_notify_mod: buffer size too small for
data.\n", plc);
+ *data_size = 0;
+ return GNUNET_NO;
+ }
+
+ *full_value_size = ntohl (pmod->value_size);
+ *oper = pmod->oper;
+ *data_size = mod_size;
+ memcpy (data, &pmod[1], mod_size);
+ ret = GNUNET_NO;
+#if REMOVE // FIXME
+ ret = (mod_size - strnlen ((char *) &pmod[1], mod_size) - 1
+ == *full_value_size)
+ ? GNUNET_YES
+ : GNUNET_NO;
+#endif
+ break;
+ }
+
+ case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT:
+ {
+ if (NULL != oper)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "%p psyc_transmit_notify_mod: oper is not NULL.\n", plc);
+ ret = GNUNET_SYSERR;
+ break;
+ }
+ uint16_t mod_size = ntohs (pmsg->size) - sizeof (*pmsg);
+ if (*data_size < mod_size)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%p psyc_transmit_notify_mod: buffer size too small for
data.\n", plc);
+ *data_size = 0;
+ return GNUNET_NO;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%p psyc_transmit_notify_mod: sending %u bytes.\n", plc,
mod_size);
+
+ *data_size = mod_size;
+ memcpy (data, &pmsg[1], *data_size);
+ ret = GNUNET_NO;
+ break;
+ }
+
+ case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA:
+ case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
+ case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
+ *data_size = 0;
+ ret = GNUNET_YES;
+ break;
+
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "%p psyc_transmit_notify_mod: unexpected message part of type
%u.\n",
+ plc, ptype);
+ ret = GNUNET_SYSERR;
+ }
+
+ if (GNUNET_SYSERR == ret)
+ {
+ *data_size = 0;
+ ret = GNUNET_SYSERR;
+ tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
+ plc->is_disconnected = GNUNET_YES;
+ GNUNET_SERVER_client_disconnect (tmit_frag->client);
+ GNUNET_SCHEDULER_add_now (&schedule_cleanup_place, plc);
+ }
+ else
+ {
+ psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag);
+
+ if (NULL == tmit_msg->frags_head
+ && GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype)
+ { /* Reached end of current message. */
+ tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
+ }
+ }
+ return ret;
+}
+
+/**
+ * Callback for data transmission from a host to PSYC.
+ */
+static int
+host_transmit_notify_data (void *cls, uint16_t *data_size, void *data)
+{
+ int ret = psyc_transmit_notify_data (cls, data_size, data);
+
+ if (GNUNET_NO != ret)
+ {
+ struct Host *hst = cls;
+ hst->tmit_handle = NULL;
+ }
+ return ret;
+}
+
+
+/**
+ * Callback for the transmit functions of multicast.
+ */
+static int
+guest_transmit_notify_data (void *cls, uint16_t *data_size, void *data)
+{
+ int ret = psyc_transmit_notify_data (cls, data_size, data);
+
+ if (GNUNET_NO != ret)
+ {
+ struct Guest *gst = cls;
+ gst->tmit_handle = NULL;
+ }
+ return ret;
+}
+
+
+/**
+ * Callback for modifier transmission from a host to PSYC.
+ */
+static int
+host_transmit_notify_mod (void *cls, uint16_t *data_size, void *data,
+ uint8_t *oper, uint32_t *full_value_size)
+{
+ int ret = psyc_transmit_notify_mod (cls, data_size, data,
+ oper, full_value_size);
+ if (GNUNET_SYSERR == ret)
+ {
+ struct Host *hst = cls;
+ hst->tmit_handle = NULL;
+ }
+ return ret;
+}
+
+
+/**
+ * Callback for modifier transmission from a guest to PSYC.
+ */
+static int
+guest_transmit_notify_mod (void *cls, uint16_t *data_size, void *data,
+ uint8_t *oper, uint32_t *full_value_size)
+{
+ int ret = psyc_transmit_notify_mod (cls, data_size, data,
+ oper, full_value_size);
+ if (GNUNET_SYSERR == ret)
+ {
+ struct Guest *gst = cls;
+ gst->tmit_handle = NULL;
+ }
+ return ret;
+}
+
+
+/**
+ * Get method part of next message from transmission queue.
+ *
+ * @param tmit_msg
+ * Next item in message transmission queue.
+ * @param[out] pmeth
+ * The message method is returned here.
+ *
+ * @return #GNUNET_OK on success
+ * #GNUNET_NO if there are no more messages in queue.
+ * #GNUNET_SYSERR if the next message is malformed.
+ */
+static int
+psyc_transmit_queue_next_method (struct Place *plc,
+ struct GNUNET_PSYC_MessageMethod **pmeth)
+{
+ struct MessageTransmitQueue *tmit_msg = plc->tmit_msgs_head;
+ if (NULL == tmit_msg)
+ return GNUNET_NO;
+
+ struct FragmentTransmitQueue *tmit_frag = tmit_msg->frags_head;
+ if (NULL == tmit_frag)
+ {
+ GNUNET_break (0);
+ return GNUNET_NO;
+ }
+
+ struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part;
+ if (NULL == pmsg
+ || GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD != ntohs (pmsg->type))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "%p psyc_transmit_queue_next_method: unexpected message part
of type %u.\n",
+ plc, ntohs (pmsg->type));
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+
+ uint16_t psize = ntohs (pmsg->size);
+ *pmeth = (struct GNUNET_PSYC_MessageMethod *) pmsg;
+
+ if (psize < sizeof (**pmeth) + 1 || '\0' != *((char *) *pmeth + psize - 1))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "%p psyc_transmit_queue_next_method: invalid method name.\n",
+ plc, ntohs (pmsg->type));
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "%u <= %u || NUL != %u\n",
+ sizeof (**pmeth), psize, *((char *) *pmeth + psize - 1));
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Transmit the next message in queue from the host to the PSYC channel.
+ */
+static int
+psyc_master_transmit_message (struct Host *hst)
+{
+
+ if (NULL == hst->tmit_handle)
+ {
+ struct GNUNET_PSYC_MessageMethod *pmeth = NULL;
+ int ret = psyc_transmit_queue_next_method (&hst->plc, &pmeth);
+ if (GNUNET_OK != ret)
+ return ret;
+
+ hst->tmit_handle
+ = GNUNET_PSYC_master_transmit (hst->master, (const char *) &pmeth[1],
+ &host_transmit_notify_mod,
+ &host_transmit_notify_data, hst,
+ pmeth->flags);
+ }
+ else
+ {
+ GNUNET_PSYC_master_transmit_resume (hst->tmit_handle);
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Transmit the next message in queue from a guest to the PSYC channel.
+ */
+static int
+psyc_slave_transmit_message (struct Guest *gst)
+{
+ if (NULL == gst->tmit_handle)
+ {
+ struct GNUNET_PSYC_MessageMethod *pmeth = NULL;
+ int ret = psyc_transmit_queue_next_method (&gst->plc, &pmeth);
+ if (GNUNET_OK != ret)
+ return ret;
+
+ gst->tmit_handle
+ = GNUNET_PSYC_slave_transmit (gst->slave, (const char *) &pmeth[1],
+ &guest_transmit_notify_mod,
+ &guest_transmit_notify_data, gst,
+ pmeth->flags);
+ }
+ else
+ {
+ GNUNET_PSYC_slave_transmit_resume (gst->tmit_handle);
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Transmit a message to PSYC.
+ */
+static int
+psyc_transmit_message (struct Place *plc)
+{
+ return
+ (plc->is_host)
+ ? psyc_master_transmit_message ((struct Host *) plc)
+ : psyc_slave_transmit_message ((struct Guest *) plc);
+}
+
+
+/**
+ * Queue message parts for sending to PSYC.
+ *
+ * @param plc Place to send to.
+ * @param client Client the message originates from.
+ * @param data_size Size of @a data.
+ * @param data Concatenated message parts.
+ * @param first_ptype First message part type in @a data.
+ * @param last_ptype Last message part type in @a data.
+ */
+static struct MessageTransmitQueue *
+psyc_transmit_queue_message (struct Place *plc,
+ struct GNUNET_SERVER_Client *client,
+ size_t data_size,
+ const void *data,
+ uint16_t first_ptype, uint16_t last_ptype,
+ struct MessageTransmitQueue *tmit_msg)
+{
+ if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == first_ptype)
+ {
+ tmit_msg = GNUNET_malloc (sizeof (*tmit_msg));
+ GNUNET_CONTAINER_DLL_insert_tail (plc->tmit_msgs_head,
plc->tmit_msgs_tail, tmit_msg);
+ }
+ else if (NULL == tmit_msg)
+ {
+ return NULL;
+ }
+
+ struct FragmentTransmitQueue *
+ tmit_frag = GNUNET_malloc (sizeof (*tmit_frag) + data_size);
+ memcpy (&tmit_frag[1], data, data_size);
+ tmit_frag->next_part = (struct GNUNET_MessageHeader *) &tmit_frag[1];
+ tmit_frag->client = client;
+ tmit_frag->size = data_size;
+
+ GNUNET_CONTAINER_DLL_insert_tail (tmit_msg->frags_head,
tmit_msg->frags_tail, tmit_frag);
+ tmit_msg->client = client;
+ return tmit_msg;
+}
+
+
+/**
+ * Cancel transmission of current message to PSYC.
+ *
+ * @param plc Place to send to.
+ * @param client Client the message originates from.
+ */
static void
-client_join_decision (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *msg)
+psyc_transmit_cancel (struct Place *plc, struct GNUNET_SERVER_Client *client)
{
+ uint16_t type = GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL;
+ struct GNUNET_MessageHeader msg;
+ msg.size = htons (sizeof (msg));
+ msg.type = htons (type);
+
+ psyc_transmit_queue_message (plc, client, sizeof (msg), &msg, type, type,
NULL);
+ psyc_transmit_message (plc);
+
+ /* FIXME: cleanup */
}
+/**
+ * Handle an incoming message from a client, to be transmitted to the place.
+ */
static void
-client_psyc_message (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *msg)
+client_recv_psyc_message (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *msg)
{
+ struct Client *
+ ctx = GNUNET_SERVER_client_get_user_context (client, struct Client);
+ GNUNET_assert (NULL != ctx);
+ struct Place *plc = ctx->plc;
+ int ret = GNUNET_SYSERR;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%p Received message from client.\n", plc);
+ GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, msg);
+
+ if (GNUNET_YES != plc->is_ready)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "%p Place is not ready yet, disconnecting client.\n", plc);
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+
+ uint16_t size = ntohs (msg->size);
+ uint16_t psize = size - sizeof (*msg);
+ if (psize < sizeof (struct GNUNET_MessageHeader)
+ || GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD < psize)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "%p Received message with invalid payload size (%u) from
client.\n",
+ plc, psize);
+ GNUNET_break (0);
+ psyc_transmit_cancel (plc, client);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+
+ uint16_t first_ptype = 0, last_ptype = 0;
+ if (GNUNET_SYSERR
+ == GNUNET_PSYC_receive_check_parts (psize, (const char *) &msg[1],
+ &first_ptype, &last_ptype))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "%p Received invalid message part from client.\n", plc);
+ GNUNET_break (0);
+ psyc_transmit_cancel (plc, client);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%p Received message with first part type %u and last part type
%u.\n",
+ plc, first_ptype, last_ptype);
+
+ ctx->tmit_msg
+ = psyc_transmit_queue_message (plc, client, psize, &msg[1],
+ first_ptype, last_ptype, ctx->tmit_msg);
+ if (NULL != ctx->tmit_msg)
+ {
+ if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= last_ptype)
+ ctx->tmit_msg = NULL;
+ ret = psyc_transmit_message (plc);
+ }
+
+ if (GNUNET_OK != ret)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "%p Received invalid message part from client.\n", plc);
+ GNUNET_break (0);
+ psyc_transmit_cancel (plc, client);
+ ret = GNUNET_SYSERR;
+ }
+ GNUNET_SERVER_receive_done (client, ret);
}
@@ -416,16 +1479,16 @@
const struct GNUNET_CONFIGURATION_Handle *c)
{
static const struct GNUNET_SERVER_MessageHandler handlers[] = {
- { &client_home_enter, NULL,
- GNUNET_MESSAGE_TYPE_SOCIAL_HOME_ENTER, 0 },
+ { &client_recv_host_enter, NULL,
+ GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER, 0 },
- { &client_place_enter, NULL,
- GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_ENTER, 0 },
+ { &client_recv_guest_enter, NULL,
+ GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER, 0 },
- { &client_join_decision, NULL,
- GNUNET_MESSAGE_TYPE_SOCIAL_JOIN_DECISION, 0 },
+ { &client_recv_join_decision, NULL,
+ GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION, 0 },
- { &client_psyc_message, NULL,
+ { &client_recv_psyc_message, NULL,
GNUNET_MESSAGE_TYPE_PSYC_MESSAGE, 0 }
};
Modified: gnunet/src/social/social.h
===================================================================
--- gnunet/src/social/social.h 2014-07-23 16:19:46 UTC (rev 34020)
+++ gnunet/src/social/social.h 2014-07-23 16:19:49 UTC (rev 34021)
@@ -19,7 +19,7 @@
*/
/**
- * @file psyc/psyc.h
+ * @file social/social.h
* @brief Common type definitions for the Social service and API.
* @author Gabor X Toth
*/
@@ -30,17 +30,100 @@
#include "platform.h"
#include "gnunet_social_service.h"
+enum MessageState
+{
+ MSG_STATE_START = 0,
+ MSG_STATE_HEADER = 1,
+ MSG_STATE_METHOD = 2,
+ MSG_STATE_MODIFIER = 3,
+ MSG_STATE_MOD_CONT = 4,
+ MSG_STATE_DATA = 5,
+ MSG_STATE_END = 6,
+ MSG_STATE_CANCEL = 7,
+ MSG_STATE_ERROR = 8,
+};
+
GNUNET_NETWORK_STRUCT_BEGIN
/**** library -> service ****/
+struct HostEnterRequest
+{
+ /**
+ * Type: GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER
+ */
+ struct GNUNET_MessageHeader header;
+ uint32_t policy GNUNET_PACKED;
+
+ struct GNUNET_CRYPTO_EcdsaPrivateKey host_key;
+
+ struct GNUNET_CRYPTO_EddsaPrivateKey place_key;
+};
+
+
+struct GuestEnterRequest
+{
+ /**
+ * Type: GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ADDR
+ */
+ struct GNUNET_MessageHeader header;
+
+ uint32_t relay_count GNUNET_PACKED;
+
+ struct GNUNET_CRYPTO_EcdsaPrivateKey guest_key;
+
+ struct GNUNET_CRYPTO_EddsaPublicKey place_key;
+
+ struct GNUNET_PeerIdentity origin;
+
+ /* Followed by struct GNUNET_PeerIdentity relays[relay_count] */
+
+ /* Followed by struct GNUNET_MessageHeader join_msg */
+};
+
+
/**** service -> library ****/
+struct CountersResult
+{
+ /**
+ * Type: GNUNET_MESSAGE_TYPE_PSYC_RESULT_COUNTERS
+ */
+ struct GNUNET_MessageHeader header;
+ /**
+ * Status code for the operation.
+ */
+ int32_t result_code GNUNET_PACKED;
+
+ /**
+ * Last message ID sent to the channel.
+ */
+ uint64_t max_message_id;
+};
+
+
+#if REMOVE
+struct NymEnterRequest
+{
+ /**
+ * Type: GNUNET_MESSAGE_TYPE_SOCIAL_NYM_ENTER
+ */
+ struct GNUNET_MessageHeader header;
+ /**
+ * Public key of the joining slave.
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey nym_key;
+
+ /* Followed by struct GNUNET_MessageHeader join_request */
+};
+#endif
+
+
GNUNET_NETWORK_STRUCT_END
#endif
Modified: gnunet/src/social/social_api.c
===================================================================
--- gnunet/src/social/social_api.c 2014-07-23 16:19:46 UTC (rev 34020)
+++ gnunet/src/social/social_api.c 2014-07-23 16:19:49 UTC (rev 34021)
@@ -1,4 +1,4 @@
-/*
+ /*
* This file is part of GNUnet
* (C) 2013 Christian Grothoff (and other contributing authors)
*
@@ -25,30 +25,93 @@
*/
#include <inttypes.h>
+#include <string.h>
#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_env_lib.h"
+#include "gnunet_core_service.h"
+#include "gnunet_identity_service.h"
+#include "gnunet_namestore_service.h"
+#include "gnunet_gns_service.h"
#include "gnunet_psyc_service.h"
+#include "gnunet_psyc_util_lib.h"
#include "gnunet_social_service.h"
#include "social.h"
+#define LOG(kind,...) GNUNET_log_from (kind, "social-api",__VA_ARGS__)
-/**
- * Handle for a pseudonym of another user in the network.
- */
-struct GNUNET_SOCIAL_Nym
-{
-};
+static struct GNUNET_CORE_Handle *core;
+static struct GNUNET_GNS_Handle *gns;
+static struct GNUNET_NAMESTORE_Handle *namestore;
+static struct GNUNET_PeerIdentity this_peer;
-
/**
* Handle for a place where social interactions happen.
*/
struct GNUNET_SOCIAL_Place
{
+ /**
+ * Configuration to use.
+ */
+ const struct GNUNET_CONFIGURATION_Handle *cfg;
+ /**
+ * Client connection to the service.
+ */
+ struct GNUNET_CLIENT_MANAGER_Connection *client;
+
+ /**
+ * Transmission handle;
+ */
+ struct GNUNET_PSYC_TransmitHandle *tmit;
+
+ /**
+ * Receipt handle;
+ */
+ struct GNUNET_PSYC_ReceiveHandle *recv;
+
+ /**
+ * Message to send on reconnect.
+ */
+ struct GNUNET_MessageHeader *connect_msg;
+
+ /**
+ * Slicer for processing incoming methods.
+ */
+ struct GNUNET_SOCIAL_Slicer *slicer;
+
+ /**
+ * Function called after disconnected from the service.
+ */
+ GNUNET_ContinuationCallback disconnect_cb;
+
+ /**
+ * Closure for @a disconnect_cb.
+ */
+ void *disconnect_cls;
+
+ /**
+ * Public key of the place.
+ */
+ struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
+
+ /**
+ * Private key of the ego.
+ */
+ struct GNUNET_CRYPTO_EcdsaPrivateKey ego_key;
+
+ /**
+ * Does this place belong to a host (#GNUNET_YES) or guest (#GNUNET_NO)?
+ */
+ uint8_t is_host;
+
+ /**
+ * Is this place in the process of disconnecting from the service?
+ * #GNUNET_YES or #GNUNET_NO
+ */
+ uint8_t is_disconnecting;
};
@@ -57,7 +120,20 @@
*/
struct GNUNET_SOCIAL_Host
{
+ struct GNUNET_SOCIAL_Place plc;
+ struct GNUNET_CRYPTO_EddsaPrivateKey place_key;
+
+ GNUNET_SOCIAL_HostEnterCallback enter_cb;
+
+ GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb;
+
+ GNUNET_SOCIAL_FarewellCallback farewell_cb;
+
+ /**
+ * Closure for callbacks.
+ */
+ void *cb_cls;
};
@@ -66,20 +142,95 @@
*/
struct GNUNET_SOCIAL_Guest
{
+ struct GNUNET_SOCIAL_Place plc;
+ GNUNET_SOCIAL_GuestEnterCallback enter_cb;
+
+ GNUNET_SOCIAL_EntryDecisionCallback entry_dcsn_cb;
+
+ /**
+ * Closure for callbacks.
+ */
+ void *cb_cls;
};
/**
- * Handle to an implementation of try-and-slice.
+ * Handle for a pseudonym of another user in the network.
*/
+struct GNUNET_SOCIAL_Nym
+{
+ struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
+ struct GNUNET_HashCode pub_key_hash;
+};
+
+
+/**
+ * Hash map of all nyms.
+ * pub_key_hash -> struct GNUNET_SOCIAL_Nym *
+ */
+struct GNUNET_CONTAINER_MultiHashMap *nyms;
+
+
+/**
+ * Handle for a try-and-slice instance.
+ */
struct GNUNET_SOCIAL_Slicer
{
+ /**
+ * Message handlers: method_name -> SlicerCallbacks
+ */
+ struct GNUNET_CONTAINER_MultiHashMap *handlers;
+
+ /**
+ * Currently being processed message part.
+ */
+ const struct GNUNET_MessageHeader *msg;
+
+ /**
+ * ID of currently being received message.
+ */
+ uint64_t message_id;
+
+ /**
+ * Method name of currently being received message.
+ */
+ char *method_name;
+
+ /**
+ * Public key of the nym the current message originates from.
+ */
+ struct GNUNET_CRYPTO_EcdsaPublicKey nym_key;
+
+ /**
+ * Size of @a method_name (including terminating \0).
+ */
+ uint16_t method_name_size;
};
/**
+ * Callbacks for a slicer method handler.
+ */
+struct SlicerCallbacks
+{
+ GNUNET_SOCIAL_MethodCallback method_cb;
+ GNUNET_SOCIAL_ModifierCallback modifier_cb;
+ GNUNET_SOCIAL_DataCallback data_cb;
+ GNUNET_SOCIAL_EndOfMessageCallback eom_cb;
+ void *cls;
+};
+
+
+struct SlicerRemoveClosure
+{
+ struct GNUNET_SOCIAL_Slicer *slicer;
+ struct SlicerCallbacks rm_cbs;
+};
+
+
+/**
* Handle for an announcement request.
*/
struct GNUNET_SOCIAL_Announcement
@@ -118,9 +269,184 @@
};
+static struct GNUNET_SOCIAL_Nym *
+nym_get_or_create (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub_key)
+{
+ struct GNUNET_SOCIAL_Nym *nym = NULL;
+ struct GNUNET_HashCode pub_key_hash;
+ if (NULL == pub_key)
+ return NULL;
+ GNUNET_CRYPTO_hash (pub_key, sizeof (*pub_key), &pub_key_hash);
+
+ if (NULL == nyms)
+ nyms = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
+ else
+ nym = GNUNET_CONTAINER_multihashmap_get (nyms, &pub_key_hash);
+
+ if (NULL == nym)
+ {
+ nym = GNUNET_new (struct GNUNET_SOCIAL_Nym);
+ nym->pub_key = *pub_key;
+ nym->pub_key_hash = pub_key_hash;
+ GNUNET_CONTAINER_multihashmap_put (nyms, &nym->pub_key_hash, nym,
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+ }
+ return nym;
+}
+
+
+static void
+nym_destroy (struct GNUNET_SOCIAL_Nym *nym)
+{
+ GNUNET_CONTAINER_multihashmap_remove (nyms, &nym->pub_key_hash, nym);
+ GNUNET_free (nym);
+}
+
+
/**
+ * Call a handler for an incoming message part.
+ *
+ * @param cls
+ * @param key
+ * @param value
+ *
+ * @return
+ */
+int
+slicer_handler_notify (void *cls, const struct GNUNET_HashCode *key,
+ void *value)
+{
+ struct GNUNET_SOCIAL_Slicer *slicer = cls;
+ const struct GNUNET_MessageHeader *msg = slicer->msg;
+ struct SlicerCallbacks *cbs = value;
+ uint16_t ptype = ntohs (msg->type);
+
+ switch (ptype)
+ {
+ case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD:
+ {
+ if (NULL == cbs->method_cb)
+ break;
+ struct GNUNET_PSYC_MessageMethod *
+ meth = (struct GNUNET_PSYC_MessageMethod *) msg;
+ cbs->method_cb (cbs->cls, meth, slicer->message_id,
+ ntohl (meth->flags),
+ nym_get_or_create (&slicer->nym_key),
+ slicer->method_name);
+ break;
+ }
+
+ case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER:
+ {
+ if (NULL == cbs->modifier_cb)
+ break;
+ struct GNUNET_PSYC_MessageModifier *
+ mod = (struct GNUNET_PSYC_MessageModifier *) msg;
+ cbs->modifier_cb (cbs->cls, mod, slicer->message_id,
+ mod->oper, (const char *) &mod[1],
+ (const void *) &mod[1] + ntohs (mod->name_size),
+ ntohs (mod->value_size));
+ break;
+ }
+
+ case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT:
+ {
+ if (NULL == cbs->modifier_cb)
+ break;
+ /* FIXME: concatenate until done */
+ break;
+ }
+
+ case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA:
+ {
+ if (NULL == cbs->data_cb)
+ break;
+ uint64_t data_offset = 0; // FIXME
+ cbs->data_cb (cbs->cls, msg, slicer->message_id,
+ data_offset, &msg[1], ntohs (msg->size) - sizeof (*msg));
+ break;
+ }
+
+ case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
+ if (NULL == cbs->eom_cb)
+ break;
+ cbs->eom_cb (cbs->cls, msg, slicer->message_id, GNUNET_NO);
+ break;
+
+ case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
+ if (NULL == cbs->eom_cb)
+ break;
+ cbs->eom_cb (cbs->cls, msg, slicer->message_id, GNUNET_YES);
+ break;
+ }
+ return GNUNET_YES;
+}
+
+
+/**
+ * Process an incoming message part and call matching handlers.
+ *
+ * @param cls
+ * Closure.
+ * @param message_id
+ * ID of the message.
+ * @param flags
+ * Flags for the message.
+ * @see enum GNUNET_PSYC_MessageFlags
+ * @param msg
+ * The message part. as it arrived from the network.
+ */
+static void
+slicer_message (void *cls, uint64_t message_id, uint64_t fragment_offset,
+ uint32_t flags, const struct GNUNET_MessageHeader *msg)
+{
+ struct GNUNET_SOCIAL_Slicer *slicer = cls;
+ uint16_t ptype = ntohs (msg->type);
+ if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == ptype)
+ {
+ struct GNUNET_PSYC_MessageMethod *
+ meth = (struct GNUNET_PSYC_MessageMethod *) msg;
+ slicer->method_name_size = ntohs (meth->header.size) - sizeof (*meth);
+ slicer->method_name = GNUNET_malloc (slicer->method_name_size);
+ memcpy (slicer->method_name, &meth[1], slicer->method_name_size);
+ slicer->message_id = message_id;
+ }
+ else
+ {
+ GNUNET_assert (message_id == slicer->message_id);
+ }
+
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ "Slicer received message of type %u and size %u, "
+ "with ID %" PRIu64 " and method %s\n",
+ ptype, ntohs (msg->size), message_id, slicer->method_name);
+
+ slicer->msg = msg;
+ char *name = GNUNET_malloc (slicer->method_name_size);
+ memcpy (name, slicer->method_name, slicer->method_name_size);
+ do
+ {
+ struct GNUNET_HashCode key;
+ uint16_t name_len = strlen (name);
+ GNUNET_CRYPTO_hash (name, name_len, &key);
+ GNUNET_CONTAINER_multihashmap_get_multiple (slicer->handlers, &key,
+ &slicer_handler_notify,
slicer);
+ char *p = strrchr (name, '_');
+ if (NULL == p)
+ break;
+ *p = '\0';
+ } while (1);
+ GNUNET_free (name);
+ slicer->msg = NULL;
+
+ if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype)
+ GNUNET_free (slicer->method_name);
+}
+
+
+/**
* Create a try-and-slice instance.
*
* @return A new try-and-slice construct.
@@ -128,7 +454,9 @@
struct GNUNET_SOCIAL_Slicer *
GNUNET_SOCIAL_slicer_create (void)
{
- return NULL;
+ struct GNUNET_SOCIAL_Slicer *slicer = GNUNET_malloc (sizeof (*slicer));
+ slicer->handlers = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
+ return slicer;
}
@@ -148,89 +476,524 @@
GNUNET_SOCIAL_slicer_add (struct GNUNET_SOCIAL_Slicer *slicer,
const char *method_name,
GNUNET_SOCIAL_MethodCallback method_cb,
+ GNUNET_SOCIAL_ModifierCallback modifier_cb,
+ GNUNET_SOCIAL_DataCallback data_cb,
+ GNUNET_SOCIAL_EndOfMessageCallback eom_cb,
void *cls)
{
+ struct GNUNET_HashCode key;
+ GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key);
+ struct SlicerCallbacks *cbs = GNUNET_malloc (sizeof (*cbs));
+ cbs->method_cb = method_cb;
+ cbs->modifier_cb = modifier_cb;
+ cbs->data_cb = data_cb;
+ cbs->eom_cb = eom_cb;
+ cbs->cls = cls;
+
+ GNUNET_CONTAINER_multihashmap_put (slicer->handlers, &key, cbs,
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
}
+int
+slicer_remove_handler (void *cls, const struct GNUNET_HashCode *key, void
*value)
+{
+ struct SlicerRemoveClosure *rm_cls = cls;
+ struct GNUNET_SOCIAL_Slicer *slicer = rm_cls->slicer;
+ struct SlicerCallbacks *rm_cbs = &rm_cls->rm_cbs;
+ struct SlicerCallbacks *cbs = value;
+
+ if (cbs->method_cb == rm_cbs->method_cb
+ && cbs->modifier_cb == rm_cbs->modifier_cb
+ && cbs->data_cb == rm_cbs->data_cb
+ && cbs->eom_cb == rm_cbs->eom_cb)
+ {
+ GNUNET_CONTAINER_multihashmap_remove (slicer->handlers, key, cbs);
+ GNUNET_free (cbs);
+ return GNUNET_NO;
+ }
+ return GNUNET_YES;
+}
+
+
/**
* Remove a registered method from the try-and-slice instance.
*
+ * Removes the first matching handler registered with @a method and the given
callbacks.
+ *
* @param slicer The try-and-slice instance.
* @param method_name Name of the method to remove.
* @param method Method handler.
+ *
+ * @return #GNUNET_OK if a method handler was removed,
+ * #GNUNET_NO if no handler matched the given method name and
callbacks.
*/
-void
+int
GNUNET_SOCIAL_slicer_remove (struct GNUNET_SOCIAL_Slicer *slicer,
const char *method_name,
- GNUNET_SOCIAL_MethodCallback method_cb)
+ GNUNET_SOCIAL_MethodCallback method_cb,
+ GNUNET_SOCIAL_ModifierCallback modifier_cb,
+ GNUNET_SOCIAL_DataCallback data_cb,
+ GNUNET_SOCIAL_EndOfMessageCallback eom_cb)
{
+ struct GNUNET_HashCode key;
+ GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key);
+ struct SlicerRemoveClosure rm_cls;
+ rm_cls.slicer = slicer;
+ struct SlicerCallbacks *rm_cbs = &rm_cls.rm_cbs;
+ rm_cbs->method_cb = method_cb;
+ rm_cbs->modifier_cb = modifier_cb;
+ rm_cbs->data_cb = data_cb;
+ rm_cbs->eom_cb = eom_cb;
+
+ return
+ (GNUNET_SYSERR
+ == GNUNET_CONTAINER_multihashmap_get_multiple (slicer->handlers, &key,
+ &slicer_remove_handler,
+ &rm_cls))
+ ? GNUNET_NO
+ : GNUNET_OK;
}
+
+int
+slicer_free_handler (void *cls, const struct GNUNET_HashCode *key, void *value)
+{
+ struct SlicerCallbacks *cbs = value;
+ GNUNET_free (cbs);
+ return GNUNET_YES;
+}
+
+
/**
* Destroy a given try-and-slice instance.
*
- * @param slicer slicer to destroy
+ * @param slicer
+ * Slicer to destroy
*/
void
GNUNET_SOCIAL_slicer_destroy (struct GNUNET_SOCIAL_Slicer *slicer)
{
+ GNUNET_CONTAINER_multihashmap_iterate (slicer->handlers,
&slicer_free_handler,
+ NULL);
+ GNUNET_CONTAINER_multihashmap_destroy (slicer->handlers);
+ GNUNET_free (slicer);
+}
+
+static void
+place_send_connect_msg (struct GNUNET_SOCIAL_Place *plc)
+{
+ uint16_t cmsg_size = ntohs (plc->connect_msg->size);
+ struct GNUNET_MessageHeader * cmsg = GNUNET_malloc (cmsg_size);
+ memcpy (cmsg, plc->connect_msg, cmsg_size);
+ GNUNET_CLIENT_MANAGER_transmit_now (plc->client, cmsg);
}
+static void
+place_recv_message_ack (void *cls,
+ struct GNUNET_CLIENT_MANAGER_Connection *client,
+ const struct GNUNET_MessageHeader *msg)
+{
+ struct GNUNET_SOCIAL_Place *
+ plc = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*plc));
+ GNUNET_PSYC_transmit_got_ack (plc->tmit);
+}
+
+
+static void
+place_recv_message (void *cls,
+ struct GNUNET_CLIENT_MANAGER_Connection *client,
+ const struct GNUNET_MessageHeader *msg)
+{
+ struct GNUNET_SOCIAL_Place *
+ plc = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*plc));
+ GNUNET_PSYC_receive_message (plc->recv,
+ (const struct GNUNET_PSYC_MessageHeader *) msg);
+}
+
+
+static void
+place_recv_disconnect (void *cls,
+ struct GNUNET_CLIENT_MANAGER_Connection *client,
+ const struct GNUNET_MessageHeader *msg)
+{
+ struct GNUNET_SOCIAL_Place *
+ plc = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*plc));
+
+ GNUNET_CLIENT_MANAGER_reconnect (client);
+ place_send_connect_msg (plc);
+}
+
+
+static void
+host_recv_enter_ack (void *cls,
+ struct GNUNET_CLIENT_MANAGER_Connection *client,
+ const struct GNUNET_MessageHeader *msg)
+{
+ struct GNUNET_SOCIAL_Host *
+ hst = GNUNET_CLIENT_MANAGER_get_user_context_ (client,
+ sizeof (struct
GNUNET_SOCIAL_Place));
+
+ struct GNUNET_PSYC_CountersResultMessage *
+ cres = (struct GNUNET_PSYC_CountersResultMessage *) msg;
+ if (NULL != hst->enter_cb)
+ hst->enter_cb (hst->cb_cls, GNUNET_ntohll (cres->max_message_id));
+}
+
+
+static void
+host_recv_enter_request (void *cls,
+ struct GNUNET_CLIENT_MANAGER_Connection *client,
+ const struct GNUNET_MessageHeader *msg)
+{
+ struct GNUNET_SOCIAL_Host *
+ hst = GNUNET_CLIENT_MANAGER_get_user_context_ (client,
+ sizeof (struct
GNUNET_SOCIAL_Place));
+ if (NULL == hst->answer_door_cb)
+ return;
+
+ const char *method_name = NULL;
+ struct GNUNET_ENV_Environment *env = NULL;
+ const void *data = NULL;
+ uint16_t data_size = 0;
+
+ const struct GNUNET_PSYC_JoinRequestMessage *
+ req = (const struct GNUNET_PSYC_JoinRequestMessage *) msg;
+ const struct GNUNET_PSYC_Message *entry_msg = NULL;
+ if (sizeof (*req) + sizeof (*entry_msg) <= ntohs (req->header.size))
+ {
+ entry_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));
+
+ env = GNUNET_ENV_environment_create ();
+ if (GNUNET_OK != GNUNET_PSYC_message_parse (entry_msg, &method_name, env,
+ &data, &data_size))
+ {
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ "Ignoring invalid entry request from nym %s.\n",
+ GNUNET_CRYPTO_ecdsa_public_key_to_string (&req->slave_key));
+ GNUNET_break_op (0);
+ GNUNET_ENV_environment_destroy (env);
+ return;
+ }
+ }
+
+ struct GNUNET_SOCIAL_Nym *nym = nym_get_or_create (&req->slave_key);
+ hst->answer_door_cb (hst->cb_cls, nym, method_name, env,
+ data_size, data);
+
+ if (NULL != env)
+ GNUNET_ENV_environment_destroy (env);
+}
+
+
+static void
+guest_recv_enter_ack (void *cls,
+ struct GNUNET_CLIENT_MANAGER_Connection *client,
+ const struct GNUNET_MessageHeader *msg)
+{
+ struct GNUNET_SOCIAL_Guest *
+ gst = GNUNET_CLIENT_MANAGER_get_user_context_ (client,
+ sizeof (struct
GNUNET_SOCIAL_Place));
+
+ struct GNUNET_PSYC_CountersResultMessage *
+ cres = (struct GNUNET_PSYC_CountersResultMessage *) msg;
+ if (NULL != gst->enter_cb)
+ gst->enter_cb (gst->cb_cls, ntohl (cres->result_code),
+ GNUNET_ntohll (cres->max_message_id));
+}
+
+
+static void
+guest_recv_join_decision (void *cls,
+ struct GNUNET_CLIENT_MANAGER_Connection *client,
+ const struct GNUNET_MessageHeader *msg)
+{
+ struct GNUNET_SOCIAL_Guest *
+ gst = GNUNET_CLIENT_MANAGER_get_user_context_ (client,
+ sizeof (struct
GNUNET_SOCIAL_Place));
+ const struct GNUNET_PSYC_JoinDecisionMessage *
+ dcsn = (const struct GNUNET_PSYC_JoinDecisionMessage *) msg;
+
+ struct GNUNET_PSYC_Message *pmsg = NULL;
+ if (ntohs (dcsn->header.size) <= sizeof (*dcsn) + sizeof (*pmsg))
+ pmsg = (struct GNUNET_PSYC_Message *) &dcsn[1];
+
+ if (NULL != gst->entry_dcsn_cb)
+ gst->entry_dcsn_cb (gst->cb_cls, ntohl (dcsn->is_admitted), pmsg);
+}
+
+
+static struct GNUNET_CLIENT_MANAGER_MessageHandler host_handlers[] =
+{
+ { &host_recv_enter_ack, NULL,
+ GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK,
+ sizeof (struct CountersResult), GNUNET_NO },
+
+ { &host_recv_enter_request, NULL,
+ GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST,
+ sizeof (struct GNUNET_PSYC_JoinRequestMessage), GNUNET_YES },
+
+ { &place_recv_message, NULL,
+ GNUNET_MESSAGE_TYPE_PSYC_MESSAGE,
+ sizeof (struct GNUNET_PSYC_MessageHeader), GNUNET_YES },
+
+ { &place_recv_message_ack, NULL,
+ GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK,
+ sizeof (struct GNUNET_MessageHeader), GNUNET_NO },
+
+ { &place_recv_disconnect, NULL, 0, 0, GNUNET_NO },
+
+ { NULL, NULL, 0, 0, GNUNET_NO }
+};
+
+
+static struct GNUNET_CLIENT_MANAGER_MessageHandler guest_handlers[] =
+{
+ { &guest_recv_enter_ack, NULL,
+ GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK,
+ sizeof (struct CountersResult), GNUNET_NO },
+
+ { &host_recv_enter_request, NULL,
+ GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST,
+ sizeof (struct GNUNET_PSYC_JoinRequestMessage), GNUNET_YES },
+
+ { &place_recv_message, NULL,
+ GNUNET_MESSAGE_TYPE_PSYC_MESSAGE,
+ sizeof (struct GNUNET_PSYC_MessageHeader), GNUNET_YES },
+
+ { &place_recv_message_ack, NULL,
+ GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK,
+ sizeof (struct GNUNET_MessageHeader), GNUNET_NO },
+
+ { &guest_recv_join_decision, NULL,
+ GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION,
+ sizeof (struct GNUNET_PSYC_JoinDecisionMessage), GNUNET_YES },
+
+ { &place_recv_disconnect, NULL, 0, 0, GNUNET_NO },
+
+ { NULL, NULL, 0, 0, GNUNET_NO }
+};
+
+
+static void
+place_cleanup (struct GNUNET_SOCIAL_Place *plc)
+{
+ GNUNET_PSYC_transmit_destroy (plc->tmit);
+ GNUNET_PSYC_receive_destroy (plc->recv);
+ GNUNET_free (plc->connect_msg);
+ if (NULL != plc->disconnect_cb)
+ plc->disconnect_cb (plc->disconnect_cls);
+}
+
+
+static void
+host_cleanup (void *cls)
+{
+ struct GNUNET_SOCIAL_Host *hst = cls;
+ place_cleanup (&hst->plc);
+ GNUNET_free (hst);
+}
+
+
+static void
+guest_cleanup (void *cls)
+{
+ struct GNUNET_SOCIAL_Guest *gst = cls;
+ place_cleanup (&gst->plc);
+ GNUNET_free (gst);
+}
+
+
/**
* Enter a place as host.
*
* 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 place_keyfile File with the private-public key pair of the place,
- * created if the file does not exist; pass NULL for ephemeral places.
- * @param policy Policy specifying entry and history restrictions of the
place.
- * @param ego Identity of the host.
- * @param slicer Slicer to handle incoming messages.
- * @param listener_cb Function to handle new nyms that want to enter.
- * @param farewell_cb Function to handle departing nyms.
- * @param cls Closure for @a listener_cb and @a farewell_cb.
+ * @param cfg
+ * Configuration to contact the social service.
+ * @param ego
+ * Identity of the host.
+ * @param place_key
+ * Private-public key pair of the place.
+ * NULL for ephemeral places.
+ * @param policy
+ * Policy specifying entry and history restrictions for the place.
+ * @param slicer
+ * Slicer to handle incoming messages.
+ * @param answer_door_cb
+ * Function to handle new nyms that want to enter.
+ * @param farewell_cb
+ * Function to handle departing nyms.
+ * @param cls
+ * Closure for the callbacks.
*
* @return Handle for the host.
*/
struct GNUNET_SOCIAL_Host *
GNUNET_SOCIAL_host_enter (const struct GNUNET_CONFIGURATION_Handle *cfg,
- const char *place_keyfile,
+ const struct GNUNET_IDENTITY_Ego *ego,
+ const struct GNUNET_CRYPTO_EddsaPrivateKey
*place_key,
enum GNUNET_PSYC_Policy policy,
- struct GNUNET_IDENTITY_Ego *ego,
struct GNUNET_SOCIAL_Slicer *slicer,
- GNUNET_SOCIAL_AnswerDoorCallback listener_cb,
+ GNUNET_SOCIAL_HostEnterCallback enter_cb,
+ GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb,
GNUNET_SOCIAL_FarewellCallback farewell_cb,
void *cls)
{
- return NULL;
+ struct GNUNET_SOCIAL_Host *hst = GNUNET_malloc (sizeof (*hst));
+ struct GNUNET_SOCIAL_Place *plc = &hst->plc;
+ struct HostEnterRequest *req = GNUNET_malloc (sizeof (*req));
+
+ if (NULL != place_key)
+ {
+ hst->place_key = *place_key;
+ }
+ else
+ {
+ struct GNUNET_CRYPTO_EddsaPrivateKey *
+ ephemeral_key = GNUNET_CRYPTO_eddsa_key_create ();
+ hst->place_key = *ephemeral_key;
+ GNUNET_CRYPTO_eddsa_key_get_public (&hst->place_key, &plc->pub_key);
+ GNUNET_CRYPTO_eddsa_key_clear (ephemeral_key);
+ GNUNET_free (ephemeral_key);
+ }
+ plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego);
+
+ 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;
+
+ hst->plc.ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego);
+ hst->enter_cb = enter_cb;
+ hst->answer_door_cb = answer_door_cb;
+ hst->cb_cls = cls;
+
+ plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social", host_handlers);
+ GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, hst, sizeof (*plc));
+
+ plc->tmit = GNUNET_PSYC_transmit_create (plc->client);
+ plc->recv = GNUNET_PSYC_receive_create (NULL, &slicer_message, plc->slicer);
+
+ place_send_connect_msg (plc);
+ return hst;
}
/**
- * Admit @a nym to the place.
+ * Enter a place as host.
*
- * The @a nym reference will remain valid until either the @a host or @a nym
- * leaves the place.
+ * A place is created upon first entering, and it is active until permanently
+ * left using GNUNET_SOCIAL_host_leave().
*
- * @param host Host of the place.
- * @param nym Handle for the entity that wants to enter.
+ * @param cfg
+ * Configuration to contact the social service.
+ * @param ego
+ * Identity of the host.
+ * @param gns_name
+ * GNS name in the zone of the @a ego that contains the
+ * public key of the place in a PLACE record.
+ * @param policy
+ * Policy specifying entry and history restrictions for the place.
+ * @param slicer
+ * Slicer to handle incoming messages.
+ * @param answer_door_cb
+ * Function to handle new nyms that want to enter.
+ * @param farewell_cb
+ * Function to handle departing nyms.
+ * @param cls
+ * Closure for the callbacks.
+ *
+ * @return Handle for the host.
*/
-void
-GNUNET_SOCIAL_host_admit (struct GNUNET_SOCIAL_Host *host,
- struct GNUNET_SOCIAL_Nym *nym)
+struct GNUNET_SOCIAL_Host *
+GNUNET_SOCIAL_host_enter_by_name (const struct GNUNET_CONFIGURATION_Handle
*cfg,
+ struct GNUNET_IDENTITY_Ego *ego,
+ const char *gns_name,
+ enum GNUNET_PSYC_Policy policy,
+ struct GNUNET_SOCIAL_Slicer *slicer,
+ GNUNET_SOCIAL_HostEnterCallback enter_cb,
+ GNUNET_SOCIAL_AnswerDoorCallback
answer_door_cb,
+ GNUNET_SOCIAL_FarewellCallback farewell_cb,
+ void *cls)
{
+ struct GNUNET_CRYPTO_EddsaPrivateKey place_key = {};
+ /* FIXME:
+ * 1. get public key by looking up PLACE entry under gns_name
+ * in the zone of the ego.
+ * 2. get private key from $GNUNET_DATA_HOME/social/places/PUB_KEY_HASH
+ */
+
+ return GNUNET_SOCIAL_host_enter (cfg, ego, &place_key, policy, slicer,
+ enter_cb, answer_door_cb, farewell_cb, cls);
}
/**
+ * Decision whether to admit @a nym into the place or refuse entry.
+ *
+ * @param hst
+ * Host of the place.
+ * @param nym
+ * Handle for the entity that wanted to enter.
+ * @param is_admitted
+ * #GNUNET_YES if @a nym is admitted,
+ * #GNUNET_NO if @a nym is refused entry,
+ * #GNUNET_SYSERR if we cannot answer the request.
+ * @param method_name
+ * Method name for the rejection message.
+ * @param env
+ * Environment containing variables for the message, or NULL.
+ * @param data
+ * Data for the rejection message to send back.
+ * @param data_size
+ * Number of bytes in @a data for method.
+ * @return #GNUNET_OK on success,
+ * #GNUNET_SYSERR if the message is too large.
+ */
+int
+GNUNET_SOCIAL_host_entry_decision (struct GNUNET_SOCIAL_Host *hst,
+ struct GNUNET_SOCIAL_Nym *nym,
+ int is_admitted,
+ const struct GNUNET_PSYC_Message
*entry_resp)
+{
+ struct GNUNET_PSYC_JoinDecisionMessage *dcsn;
+ uint16_t entry_resp_size
+ = (NULL != entry_resp) ? ntohs (entry_resp->header.size) : 0;
+
+ if (GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD < sizeof (*dcsn) + entry_resp_size)
+ return GNUNET_SYSERR;
+
+ dcsn = GNUNET_malloc (sizeof (*dcsn) + entry_resp_size);
+ dcsn->header.size = htons (sizeof (*dcsn) + entry_resp_size);
+ dcsn->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION);
+ dcsn->is_admitted = htonl (is_admitted);
+ dcsn->slave_key = nym->pub_key;
+
+ if (0 < entry_resp_size)
+ memcpy (&dcsn[1], entry_resp, entry_resp_size);
+
+ GNUNET_CLIENT_MANAGER_transmit (hst->plc.client, &dcsn->header);
+ return GNUNET_OK;
+}
+
+
+/**
* Throw @a nym out of the place.
*
* The @a nym reference will remain valid until the
@@ -249,63 +1012,60 @@
/**
- * Refuse @a nym entry into the place.
+ * Get the public key of a @a nym.
*
- * @param host Host of the place.
- * @param nym Handle for the entity that wanted to enter.
- * @param method_name Method name for the rejection message.
- * @param env Environment containing variables for the message, or NULL.
- * @param data Data for the rejection message to send back.
- * @param data_size Number of bytes in @a data for method.
+ * Suitable, for example, to be used with GNUNET_NAMESTORE_zone_to_name().
+ *
+ * @param nym Pseudonym to map to a cryptographic identifier.
+ * @param[out] nym_key Set to the public key of the nym.
*/
-void
-GNUNET_SOCIAL_host_refuse_entry (struct GNUNET_SOCIAL_Host *host,
- struct GNUNET_SOCIAL_Nym *nym,
- const char *method_name,
- const struct GNUNET_ENV_Environment *env,
- const void *data,
- size_t data_size)
+struct GNUNET_CRYPTO_EcdsaPublicKey *
+GNUNET_SOCIAL_nym_get_key (struct GNUNET_SOCIAL_Nym *nym)
{
-
+ return &nym->pub_key;
}
/**
- * Get the public key of a @a nym.
+ * Obtain the private-public key pair of the hosted place.
*
- * Suitable, for example, to be used with GNUNET_NAMESTORE_zone_to_name().
+ * The public part is suitable for storing in GNS within a PLACE record,
+ * along with peer IDs to join at.
*
- * @param nym Pseudonym to map to a cryptographic identifier.
- * @param[out] nym_key Set to the public key of the nym.
+ * @param host
+ * Host of the place.
+ *
+ * @return Private-public key pair of the hosted place.
*/
-void
-GNUNET_SOCIAL_nym_get_key (struct GNUNET_SOCIAL_Nym *nym,
- struct GNUNET_CRYPTO_EddsaPublicKey *nym_key)
+const struct GNUNET_CRYPTO_EddsaPrivateKey *
+GNUNET_SOCIAL_host_get_place_key (struct GNUNET_SOCIAL_Host *hst)
{
+ return &hst->place_key;
+}
+
+static void
+namestore_result_host_advertise (void *cls, int32_t success, const char *emsg)
+{
+
}
/**
- * Obtain the private-public key pair of the host.
- *
- * @param host Host to get the key of.
- * @param[out] host_key Set to the private-public key pair of the host. The
- * public part is suitable for storing in GNS within a "PLACE"
- * record, along with peer IDs to join at.
+ * Connected to core service.
*/
-void
-GNUNET_SOCIAL_host_get_key (struct GNUNET_SOCIAL_Host *host,
- struct GNUNET_CRYPTO_EddsaPrivateKey *host_key)
+static void
+core_connected_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity)
{
-
+ this_peer = *my_identity;
+ // FIXME
}
/**
* Advertise the place in the GNS zone of the @e ego of the @a host.
*
- * @param host Host of the place.
+ * @param hst Host of the place.
* @param name The name for the PLACE record to put in the zone.
* @param peer_count Number of elements in the @a peers array.
* @param peers List of peers in the PLACE record that can be used to send join
@@ -314,14 +1074,37 @@
* @param password Password used to encrypt the record.
*/
void
-GNUNET_SOCIAL_host_advertise (struct GNUNET_SOCIAL_Host *host,
+GNUNET_SOCIAL_host_advertise (struct GNUNET_SOCIAL_Host *hst,
const char *name,
size_t peer_count,
const struct GNUNET_PeerIdentity *peers,
struct GNUNET_TIME_Relative expiration_time,
const char *password)
{
+ struct GNUNET_SOCIAL_Place *plc = &hst->plc;
+ if (NULL == namestore)
+ namestore = GNUNET_NAMESTORE_connect (plc->cfg);
+ if (NULL == core)
+ core = GNUNET_CORE_connect (plc->cfg, NULL, core_connected_cb, NULL, NULL,
+ NULL, GNUNET_NO, NULL, GNUNET_NO, NULL);
+ struct GNUNET_GNSRECORD_Data rd = { 0 };
+ rd.record_type = GNUNET_GNSRECORD_TYPE_PLACE;
+ rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+ rd.expiration_time
+ = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_WEEKS, 1).rel_value_us;
+
+ struct GNUNET_GNSRECORD_PlaceData *rec = GNUNET_malloc (sizeof (*rec));
+ rec->place_key = plc->pub_key;
+ rec->origin = this_peer;
+ rec->relay_count = htons (0); // FIXME
+
+ rd.data_size = sizeof (*rec);
+ rd.data = rec;
+
+ GNUNET_NAMESTORE_records_store (namestore, &hst->plc.ego_key,
+ name, 1, &rd,
namestore_result_host_advertise,
+ hst);
}
@@ -342,26 +1125,43 @@
* @return NULL on error (announcement already in progress?).
*/
struct GNUNET_SOCIAL_Announcement *
-GNUNET_SOCIAL_host_announce (struct GNUNET_SOCIAL_Host *host,
+GNUNET_SOCIAL_host_announce (struct GNUNET_SOCIAL_Host *hst,
const char *method_name,
const struct GNUNET_ENV_Environment *env,
- GNUNET_CONNECTION_TransmitReadyNotify notify,
- void *notify_cls,
+ GNUNET_PSYC_TransmitNotifyData notify_data,
+ void *notify_data_cls,
enum GNUNET_SOCIAL_AnnounceFlags flags)
{
- return NULL;
+ if (GNUNET_OK ==
+ GNUNET_PSYC_transmit_message (hst->plc.tmit, method_name, env,
+ NULL, notify_data, notify_data_cls,
flags));
+ return (struct GNUNET_SOCIAL_Announcement *) hst->plc.tmit;
}
/**
+ * Resume transmitting announcement.
+ *
+ * @param a
+ * The announcement to resume.
+ */
+void
+GNUNET_SOCIAL_host_announce_resume (struct GNUNET_SOCIAL_Announcement *a)
+{
+ GNUNET_PSYC_transmit_resume ((struct GNUNET_PSYC_TransmitHandle *) a);
+}
+
+
+/**
* Cancel announcement.
*
- * @param a The announcement to cancel.
+ * @param a
+ * The announcement to cancel.
*/
void
GNUNET_SOCIAL_host_announce_cancel (struct GNUNET_SOCIAL_Announcement *a)
{
-
+ GNUNET_PSYC_transmit_cancel ((struct GNUNET_PSYC_TransmitHandle *) a);
}
@@ -375,9 +1175,9 @@
* @return Handle for the hosted place, valid as long as @a host is valid.
*/
struct GNUNET_SOCIAL_Place *
-GNUNET_SOCIAL_host_get_place (struct GNUNET_SOCIAL_Host *host)
+GNUNET_SOCIAL_host_get_place (struct GNUNET_SOCIAL_Host *hst)
{
- return NULL;
+ return &hst->plc;
}
@@ -390,22 +1190,65 @@
* @param keep_active Keep the place active after last host disconnected.
*/
void
-GNUNET_SOCIAL_host_leave (struct GNUNET_SOCIAL_Host *host, int keep_active)
+GNUNET_SOCIAL_host_leave (struct GNUNET_SOCIAL_Host *hst,
+ int keep_active,
+ GNUNET_ContinuationCallback leave_cb,
+ void *leave_cls)
{
+ struct GNUNET_SOCIAL_Place *plc = &hst->plc;
+ /* FIXME: send msg to service */
+
+ plc->is_disconnecting = GNUNET_YES;
+ plc->disconnect_cb = leave_cb;
+ plc->disconnect_cls = leave_cls;
+
+ GNUNET_CLIENT_MANAGER_disconnect (plc->client, GNUNET_YES,
+ &host_cleanup, hst);
}
+static struct GuestEnterRequest *
+guest_enter_request_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey
*guest_key,
+ const struct GNUNET_CRYPTO_EddsaPublicKey
*place_key,
+ const struct GNUNET_PeerIdentity *origin,
+ size_t relay_count,
+ const struct GNUNET_PeerIdentity *relays,
+ const struct GNUNET_PSYC_Message *join_msg)
+{
+ uint16_t join_msg_size = ntohs (join_msg->header.size);
+ uint16_t relay_size = relay_count * sizeof (*relays);
+
+ struct GuestEnterRequest *
+ 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_SOCIAL_GUEST_ENTER);
+ req->place_key = *place_key;
+ req->guest_key = *guest_key;
+ req->origin = *origin;
+ req->relay_count = relay_count;
+
+ uint16_t p = sizeof (*req);
+ if (0 < relay_size)
+ {
+ memcpy ((char *) req + p, relays, relay_size);
+ p += relay_size;
+ }
+
+ memcpy ((char *) req + p, join_msg, join_msg_size);
+ return req;
+}
+
/**
* Request entry to a place as a guest.
*
- * @param cfg Configuration to contact the social service.
+ * @param cfg Configuration to contact the social service.
* @param ego Identity of the guest.
- * @param address GNS name of the place to enter. Either in the form of
- * 'room.friend.gnu', or 'NYMPUBKEY.zkey'. This latter case refers to
- * the 'PLACE' record of the empty label ("+") in the GNS zone with the
- * nym's public key 'NYMPUBKEY', and can be used to request entry to a
- * pseudonym's place directly.
+ * @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.
@@ -416,26 +1259,132 @@
*/
struct GNUNET_SOCIAL_Guest *
GNUNET_SOCIAL_guest_enter (const struct GNUNET_CONFIGURATION_Handle *cfg,
- struct GNUNET_IDENTITY_Ego *ego,
- char *address,
- const char *method_name,
- const struct GNUNET_ENV_Environment *env,
- const void *data,
- size_t data_size,
- struct GNUNET_SOCIAL_Slicer *slicer)
+ const struct GNUNET_IDENTITY_Ego *ego,
+ 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,
+ struct GNUNET_SOCIAL_Slicer *slicer,
+ GNUNET_SOCIAL_GuestEnterCallback local_enter_cb,
+ GNUNET_SOCIAL_EntryDecisionCallback entry_dcsn_cb,
+ void *cls)
{
- return NULL;
+ struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst));
+ struct GNUNET_SOCIAL_Place *plc = &gst->plc;
+
+ struct GuestEnterRequest *
+ req = guest_enter_request_create (&plc->ego_key, place_key, origin,
+ relay_count, relays, entry_msg);
+ plc->connect_msg = &req->header;
+ plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego);
+ plc->pub_key = *place_key;
+ plc->cfg = cfg;
+ plc->is_host = GNUNET_YES;
+ plc->slicer = slicer;
+
+ gst->enter_cb = local_enter_cb;
+ gst->entry_dcsn_cb = entry_dcsn_cb;
+ gst->cb_cls = cls;
+
+ plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social", guest_handlers);
+ GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, gst, sizeof (*plc));
+
+ plc->tmit = GNUNET_PSYC_transmit_create (plc->client);
+ plc->recv = GNUNET_PSYC_receive_create (NULL, &slicer_message, plc->slicer);
+
+ place_send_connect_msg (plc);
+ return gst;
}
+
/**
+ * Result of a GNS name lookup for entering a place.
+ *
+ * @see GNUNET_SOCIAL_guest_enter_by_name
+ */
+static void
+gns_result_guest_enter (void *cls, uint32_t rd_count,
+ const struct GNUNET_GNSRECORD_Data *rd)
+{
+ struct GNUNET_SOCIAL_Guest *gst = cls;
+ struct GNUNET_SOCIAL_Place *plc = &gst->plc;
+
+ const struct GNUNET_GNSRECORD_PlaceData *
+ rec = (const struct GNUNET_GNSRECORD_PlaceData *) rd->data;
+
+ if (0 == rd_count)
+ {
+ if (NULL != gst->enter_cb)
+ gst->enter_cb (gst->cb_cls, GNUNET_SYSERR, 0);
+ return;
+ }
+
+
+ if (rd->data_size < sizeof (*rec))
+ {
+ GNUNET_break_op (0);
+ if (NULL != gst->enter_cb)
+ gst->enter_cb (gst->cb_cls, GNUNET_SYSERR, 0);
+ return;
+ }
+
+ struct GuestEnterRequest *
+ req = (struct GuestEnterRequest *) plc->connect_msg;
+ uint16_t req_size = ntohs (req->header.size);
+
+ struct GNUNET_PeerIdentity *relays = NULL;
+ uint16_t relay_count = ntohs (rec->relay_count);
+
+ if (0 < relay_count)
+ {
+ uint16_t relay_size = relay_count * sizeof (struct GNUNET_PeerIdentity);
+ struct GuestEnterRequest *
+ req2 = GNUNET_malloc (req_size + relay_size);
+
+ req2->header.size = htons (req_size + relay_size);
+ req2->header.type = req->header.type;
+ req2->guest_key = req->guest_key;
+
+ uint16_t p = sizeof (*req);
+ if (0 < relay_size)
+ {
+ memcpy ((char *) req2 + p, relays, relay_size);
+ p += relay_size;
+ }
+
+ memcpy ((char *) req + p, &req[1], req_size - sizeof (*req));
+
+ plc->connect_msg = &req2->header;
+ GNUNET_free (req);
+ req = req2;
+ }
+
+ req->place_key = rec->place_key;
+ req->origin = rec->origin;
+ req->relay_count = rec->relay_count;
+ memcpy (&req[1], &rec[1],
+ ntohl (rec->relay_count) * sizeof (struct GNUNET_PeerIdentity));
+
+ plc->connect_msg = &req->header;
+ plc->pub_key = req->place_key;
+
+ plc->tmit = GNUNET_PSYC_transmit_create (plc->client);
+ plc->recv = GNUNET_PSYC_receive_create (NULL, &slicer_message, plc);
+
+ place_send_connect_msg (plc);
+}
+
+/**
* Request entry to a place as a guest.
*
- * @param cfg Configuration to contact the social service.
+ * @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 address GNS name of the place to enter. Either in the form of
+ * 'room.friend.gnu', or 'NYMPUBKEY.zkey'. This latter case refers to
+ * the 'PLACE' record of the empty label ("+") in the GNS zone with the
+ * nym's public key 'NYMPUBKEY', and can be used to request entry to a
+ * pseudonym's place directly.
* @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.
@@ -445,41 +1394,75 @@
* @return NULL on errors, otherwise handle for the guest.
*/
struct GNUNET_SOCIAL_Guest *
-GNUNET_SOCIAL_guest_enter2 (const struct GNUNET_CONFIGURATION_Handle *cfg,
- struct GNUNET_IDENTITY_Ego *ego,
- struct GNUNET_CRYPTO_EddsaPublicKey
*crypto_address,
- struct GNUNET_PeerIdentity *origin,
- size_t relay_count,
- struct GNUNET_PeerIdentity *relays,
- const char *method_name,
- const struct GNUNET_ENV_Environment *env,
- const void *data,
- size_t data_size,
- struct GNUNET_SOCIAL_Slicer *slicer)
+GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_CONFIGURATION_Handle
*cfg,
+ struct GNUNET_IDENTITY_Ego *ego,
+ char *gns_name,
+ const struct GNUNET_PSYC_Message *join_msg,
+ struct GNUNET_SOCIAL_Slicer *slicer,
+ GNUNET_SOCIAL_GuestEnterCallback
local_enter_cb,
+ GNUNET_SOCIAL_EntryDecisionCallback
entry_decision_cb,
+ void *cls)
{
- return NULL;
+ struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst));
+ struct GNUNET_SOCIAL_Place *plc = &gst->plc;
+
+ gst->enter_cb = local_enter_cb;
+ gst->cb_cls = cls;
+
+ plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego);
+ plc->cfg = cfg;
+ plc->is_host = GNUNET_NO;
+ plc->slicer = slicer;
+
+ struct GuestEnterRequest *
+ req = guest_enter_request_create (&plc->ego_key, NULL, NULL, 0, NULL,
+ join_msg);
+ plc->connect_msg = &req->header;
+
+ /* FIXME: get the public key of the origin and relays
+ * by looking up the PLACE record of gns_name.
+ */
+ if (NULL == gns)
+ gns = GNUNET_GNS_connect (cfg);
+
+ plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social", guest_handlers);
+ GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, gst, sizeof (*plc));
+
+ struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
+ GNUNET_IDENTITY_ego_get_public_key (ego, &ego_pub_key);
+ GNUNET_GNS_lookup (gns, gns_name, &ego_pub_key,
+ GNUNET_GNSRECORD_TYPE_PLACE, GNUNET_GNS_LO_DEFAULT,
+ NULL, gns_result_guest_enter, gst);
+
+ return gst;
}
/**
* Talk to the host of the place.
*
- * @param place Place where we want to talk to the host.
- * @param method_name Method to invoke on the host.
- * @param env Environment containing variables for the message, or NULL.
- * @param notify Function to use to get the payload for the method.
- * @param notify_cls Closure for @a notify.
- * @param flags Flags for the message being sent.
+ * @param place
+ * Place where we want to talk to the host.
+ * @param method_name
+ * Method to invoke on the host.
+ * @param env
+ * Environment containing variables for the message, or NULL.
+ * @param notify_data
+ * Function to use to get the payload for the method.
+ * @param notify_data_cls
+ * Closure for @a notify_data.
+ * @param flags
+ * Flags for the message being sent.
*
* @return NULL if we are already trying to talk to the host,
* otherwise handle to cancel the request.
*/
struct GNUNET_SOCIAL_TalkRequest *
-GNUNET_SOCIAL_guest_talk (struct GNUNET_SOCIAL_Place *place,
+GNUNET_SOCIAL_guest_talk (struct GNUNET_SOCIAL_Guest *guest,
const char *method_name,
const struct GNUNET_ENV_Environment *env,
- GNUNET_CONNECTION_TransmitReadyNotify notify,
- void *notify_cls,
+ GNUNET_PSYC_TransmitNotifyData notify_data,
+ void *notify_data_cls,
enum GNUNET_SOCIAL_TalkFlags flags)
{
return NULL;
@@ -487,14 +1470,28 @@
/**
+ * Resume talking to the host of the place.
+ *
+ * @param tr
+ * Talk request to resume.
+ */
+void
+GNUNET_SOCIAL_guest_talk_resume (struct GNUNET_SOCIAL_TalkRequest *tr)
+{
+ GNUNET_PSYC_transmit_resume ((struct GNUNET_PSYC_TransmitHandle *) tr);
+}
+
+
+/**
* Cancel talking to the host of the place.
*
- * @param tr Talk request to cancel.
+ * @param tr
+ * Talk request to cancel.
*/
void
GNUNET_SOCIAL_guest_talk_cancel (struct GNUNET_SOCIAL_TalkRequest *tr)
{
-
+ GNUNET_PSYC_transmit_cancel ((struct GNUNET_PSYC_TransmitHandle *) tr);
}
@@ -507,9 +1504,21 @@
* @param keep_active Keep place active after last application disconnected.
*/
void
-GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Place *place, int keep_active)
+GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Guest *gst,
+ int keep_active,
+ GNUNET_ContinuationCallback leave_cb,
+ void *leave_cls)
{
+ struct GNUNET_SOCIAL_Place *plc = &gst->plc;
+ /* FIXME: send msg to service */
+
+ plc->is_disconnecting = GNUNET_YES;
+ plc->disconnect_cb = leave_cb;
+ plc->disconnect_cls = leave_cls;
+
+ GNUNET_CLIENT_MANAGER_disconnect (plc->client, GNUNET_YES,
+ &guest_cleanup, gst);
}
@@ -523,9 +1532,9 @@
* @return Handle for the place, valid as long as @a guest is valid.
*/
struct GNUNET_SOCIAL_Place *
-GNUNET_SOCIAL_guest_get_place (struct GNUNET_SOCIAL_Host *guest)
+GNUNET_SOCIAL_guest_get_place (struct GNUNET_SOCIAL_Guest *gst)
{
- return NULL;
+ return &gst->plc;
}
@@ -671,6 +1680,4 @@
}
-
-
/* end of social_api.c */
Modified: gnunet/src/social/test_social.c
===================================================================
--- gnunet/src/social/test_social.c 2014-07-23 16:19:46 UTC (rev 34020)
+++ gnunet/src/social/test_social.c 2014-07-23 16:19:49 UTC (rev 34021)
@@ -17,7 +17,6 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
-
/**
* @file social/test_social.c
* @brief Tests for the Social API.
@@ -32,32 +31,132 @@
#include "gnunet_util_lib.h"
#include "gnunet_testing_lib.h"
#include "gnunet_env_lib.h"
+#include "gnunet_psyc_util_lib.h"
#include "gnunet_social_service.h"
+#include "gnunet_core_service.h"
+#include "gnunet_identity_service.h"
#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
#define DEBUG_SERVICE 0
+#define DATA2ARG(data) data, sizeof (data)
/**
* Return value from 'main'.
*/
-static int res;
+int res;
-static const struct GNUNET_CONFIGURATION_Handle *cfg;
-
/**
* Handle for task for timeout termination.
*/
-static GNUNET_SCHEDULER_TaskIdentifier end_badly_task;
+GNUNET_SCHEDULER_TaskIdentifier end_badly_task;
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+struct GNUNET_CORE_Handle *core;
+struct GNUNET_PeerIdentity this_peer;
+
+struct GNUNET_IDENTITY_Handle *id;
+
+const struct GNUNET_IDENTITY_Ego *host_ego;
+const struct GNUNET_IDENTITY_Ego *guest_ego;
+
+const char *host_name = "Host One";
+const char *guest_name = "Guest One";
+
+struct GNUNET_CRYPTO_EddsaPrivateKey *place_key;
+struct GNUNET_CRYPTO_EcdsaPrivateKey *guest_key;
+
+struct GNUNET_CRYPTO_EddsaPublicKey place_pub_key;
+struct GNUNET_CRYPTO_EcdsaPublicKey guest_pub_key;
+
+struct GNUNET_SOCIAL_Slicer *host_slicer;
+struct GNUNET_SOCIAL_Slicer *guest_slicer;
+
+struct GNUNET_SOCIAL_Host *hst;
+struct GNUNET_SOCIAL_Guest *gst;
+
+struct GuestEnterMessage
+{
+ struct GNUNET_PSYC_Message *msg;
+ const char *method_name;
+ struct GNUNET_ENV_Environment *env;
+ void *data;
+ uint16_t data_size;
+} guest_enter_msg;
+
+struct TransmitClosure
+{
+ struct GNUNET_SOCIAL_Announcement *host_ann;
+ struct GNUNET_SOCIAL_TalkRequest *guest_talk;
+ struct GNUNET_ENV_Environment *env;
+ char *data[16];
+ uint8_t data_delay[16];
+ uint8_t data_count;
+ uint8_t paused;
+ uint8_t n;
+} tmit;
+
+uint8_t join_req_count;
+struct GNUNET_PSYC_Message *join_resp;
+
+enum
+{
+ TEST_NONE = 0,
+ TEST_HOST_ANSWER_DOOR_REFUSE = 1,
+ TEST_GUEST_RECV_ENTRY_DCSN_REFUSE = 2,
+ TEST_HOST_ANSWER_DOOR_ADMIT = 3,
+ TEST_GUEST_RECV_ENTRY_DCSN_ADMIT = 4,
+ TEST_HOST_ANNOUNCE = 5,
+ TEST_HOST_ANNOUNCE_END = 6,
+ TEST_GUEST_TALK = 7,
+ TEST_GUEST_TALK_END = 8,
+ TEST_GUEST_LEAVE = 9,
+ TEST_HOST_LEAVE = 10,
+} test;
+
+
+void
+guest_enter ();
+
+
+void
+guest_talk ();
+
+
+void
+host_announce2 ();
+
+
/**
* Clean up all resources used.
*/
-static void
+void
cleanup ()
{
+ if (NULL != core)
+ {
+ GNUNET_CORE_disconnect (core);
+ core = NULL;
+ }
+ if (NULL != id)
+ {
+ GNUNET_IDENTITY_disconnect (id);
+ id = NULL;
+ }
+
+ if (NULL != gst)
+ {
+ GNUNET_SOCIAL_guest_leave (gst, GNUNET_NO, NULL, NULL);
+ gst = NULL;
+ }
+ if (NULL != hst)
+ {
+ GNUNET_SOCIAL_host_leave (hst, GNUNET_NO, NULL, NULL);
+ hst = NULL;
+ }
+ GNUNET_SCHEDULER_shutdown ();
}
@@ -67,7 +166,7 @@
* @param cls NULL
* @param tc scheduler context
*/
-static void
+void
end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
res = 1;
@@ -82,7 +181,7 @@
* @param cls NULL
* @param tc scheduler context
*/
-static void
+void
end_normally (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
res = 0;
@@ -94,7 +193,7 @@
/**
* Finish the test case (successfully).
*/
-static void
+void
end ()
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending tests.\n");
@@ -109,6 +208,564 @@
}
+static void
+transmit_resume (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission resumed.\n");
+ struct TransmitClosure *tmit = cls;
+ if (NULL != tmit->host_ann)
+ GNUNET_SOCIAL_host_announce_resume (tmit->host_ann);
+ else
+ GNUNET_SOCIAL_guest_talk_resume (tmit->guest_talk);
+}
+
+
+int
+notify_data (void *cls, uint16_t *data_size, void *data)
+{
+ struct TransmitClosure *tmit = cls;
+ if (NULL != tmit->env)
+ {
+ GNUNET_ENV_environment_destroy (tmit->env);
+ tmit->env = NULL;
+ }
+ if (0 == tmit->data_count)
+ {
+ *data_size = 0;
+ return GNUNET_YES;
+ }
+
+ uint16_t size = strlen (tmit->data[tmit->n]) + 1;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Transmit notify data: %u bytes available, "
+ "processing fragment %u/%u (size %u).\n",
+ *data_size, tmit->n + 1, tmit->data_count, size);
+ if (*data_size < size)
+ {
+ *data_size = 0;
+ GNUNET_assert (0);
+ return GNUNET_SYSERR;
+ }
+
+ if (GNUNET_YES != tmit->paused && 0 < tmit->data_delay[tmit->n])
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission paused.\n");
+ tmit->paused = GNUNET_YES;
+ GNUNET_SCHEDULER_add_delayed (
+ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
+ tmit->data_delay[tmit->n]),
+ &transmit_resume, tmit);
+ *data_size = 0;
+ return GNUNET_NO;
+ }
+ tmit->paused = GNUNET_NO;
+
+ *data_size = size;
+ memcpy (data, tmit->data[tmit->n], size);
+
+ return ++tmit->n < tmit->data_count ? GNUNET_NO : GNUNET_YES;
+}
+
+
+void host_left ()
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "The host has left the place.\n");
+ GNUNET_SOCIAL_slicer_destroy (host_slicer);
+ host_slicer = NULL;
+ hst = NULL;
+
+ end ();
+}
+
+
+void
+schedule_host_leave (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ test = TEST_HOST_LEAVE;
+ GNUNET_SOCIAL_host_leave (hst, GNUNET_NO, &host_left, NULL);
+}
+
+
+void
+host_farewell (void *cls,
+ struct GNUNET_SOCIAL_Nym *nym,
+ struct GNUNET_ENV_Environment *env,
+ size_t variable_count,
+ struct GNUNET_ENV_Modifier *variables)
+{
+ struct GNUNET_CRYPTO_EcdsaPublicKey *
+ nym_key = GNUNET_SOCIAL_nym_get_key (nym);
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Nym %s has left the place.\n",
+ GNUNET_CRYPTO_ecdsa_public_key_to_string (nym_key));
+ GNUNET_assert (0 == memcmp (&guest_pub_key, nym_key, sizeof (*nym_key)));
+
+ GNUNET_SCHEDULER_add_now (&schedule_host_leave, NULL);
+}
+
+
+void
+guest_left (void *cls)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "The guest has left the place.\n");
+ GNUNET_SOCIAL_slicer_destroy (guest_slicer);
+ guest_slicer = NULL;
+ gst = NULL;
+
+ GNUNET_SCHEDULER_add_now (&schedule_host_leave, NULL);
+}
+
+
+void
+schedule_guest_leave (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ test = TEST_GUEST_LEAVE;
+ /* FIXME test keep_active */
+ GNUNET_SOCIAL_guest_leave (gst, GNUNET_NO, &guest_left, NULL);
+}
+
+
+
+void
+guest_recv_method (void *cls,
+ const struct GNUNET_PSYC_MessageMethod *meth,
+ uint64_t message_id,
+ uint32_t flags,
+ const struct GNUNET_SOCIAL_Nym *nym,
+ const char *method_name)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Test #%u: Guest received method for message ID %" PRIu64 ":\n"
+ "%s\n",
+ test, message_id, method_name);
+ /* FIXME: check message */
+}
+
+
+void
+guest_recv_modifier (void *cls,
+ const struct GNUNET_PSYC_MessageModifier *mod,
+ uint64_t message_id,
+ enum GNUNET_ENV_Operator oper,
+ const char *name,
+ const void *value,
+ uint16_t value_size)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Test #%u: Guest received modifier for message ID %" PRIu64 ":\n"
+ "%c%s: %.*s\n",
+ test, message_id, oper, name, value_size, value);
+}
+
+
+void
+guest_recv_data (void *cls,
+ const struct GNUNET_MessageHeader *msg,
+ uint64_t message_id,
+ uint64_t data_offset,
+ const void *data,
+ uint16_t data_size)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Test #%u: Guest received data for message ID %" PRIu64 ":\n"
+ "%.*s\n",
+ test, message_id, data_size, data);
+}
+
+
+void
+guest_recv_eom (void *cls,
+ const struct GNUNET_MessageHeader *msg,
+ uint64_t message_id,
+ uint8_t cancelled)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Test #%u: Guest received end of message ID %" PRIu64
+ ", cancelled: %u\n",
+ test, message_id, cancelled);
+
+ switch (test)
+ {
+ case TEST_HOST_ANNOUNCE:
+ test = TEST_HOST_ANNOUNCE_END;
+ break;
+
+ case TEST_HOST_ANNOUNCE_END:
+ guest_talk ();
+ break;
+
+ case TEST_GUEST_TALK:
+ test = TEST_GUEST_TALK_END;
+ break;
+
+ case TEST_GUEST_TALK_END:
+ GNUNET_SCHEDULER_add_now (&schedule_guest_leave, NULL);
+ break;
+
+ default:
+ GNUNET_assert (0);
+ }
+}
+
+
+void
+host_recv_method (void *cls,
+ const struct GNUNET_PSYC_MessageMethod *meth,
+ uint64_t message_id,
+ uint32_t flags,
+ const struct GNUNET_SOCIAL_Nym *nym,
+ const char *method_name)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Test #%u: Host received method for message ID %" PRIu64 ":\n"
+ "%s\n",
+ test, message_id, method_name);
+ /* FIXME: check message */
+}
+
+
+void
+host_recv_modifier (void *cls,
+ const struct GNUNET_PSYC_MessageModifier *mod,
+ uint64_t message_id,
+ enum GNUNET_ENV_Operator oper,
+ const char *name,
+ const void *value,
+ uint16_t value_size)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Test #%u: Host received modifier for message ID %" PRIu64 ":\n"
+ "%c%s: %.*s\n",
+ test, message_id, oper, name, value_size, value);
+}
+
+
+void
+host_recv_data (void *cls,
+ const struct GNUNET_MessageHeader *msg,
+ uint64_t message_id,
+ uint64_t data_offset,
+ const void *data,
+ uint16_t data_size)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Test #%u: Host received data for message ID %" PRIu64 ":\n"
+ "%.*s\n",
+ test, message_id, data_size, data);
+}
+
+
+void
+host_recv_eom (void *cls,
+ const struct GNUNET_MessageHeader *msg,
+ uint64_t message_id,
+ uint8_t cancelled)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Test #%u: Host received end of message ID %" PRIu64
+ ", cancelled: %u\n",
+ test, message_id, cancelled);
+
+ switch (test)
+ {
+ case TEST_HOST_ANNOUNCE:
+ test = TEST_HOST_ANNOUNCE_END;
+ //host_announce2 ();
+ break;
+
+ case TEST_HOST_ANNOUNCE_END:
+ guest_talk ();
+ break;
+
+ case TEST_GUEST_TALK:
+ test = TEST_GUEST_TALK_END;
+ break;
+
+ case TEST_GUEST_TALK_END:
+ GNUNET_SCHEDULER_add_now (&schedule_guest_leave, NULL);
+ break;
+
+ default:
+ GNUNET_assert (0);
+ }
+}
+
+
+void
+guest_talk ()
+{
+ test = TEST_GUEST_TALK;
+
+ tmit = (struct TransmitClosure) {};
+ tmit.env = GNUNET_ENV_environment_create ();
+ GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
+ "_bar_foo", DATA2ARG ("one two three"));
+ GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
+ "_bar_baz", DATA2ARG ("four five"));
+ tmit.data[0] = "zzz xxx yyy";
+ tmit.data[1] = "zyx wvu tsr qpo";
+ tmit.data[2] = "testing ten nine eight";
+ tmit.data_count = 3;
+
+ tmit.host_ann
+ = GNUNET_SOCIAL_host_announce (hst, "_message_guest", tmit.env,
+ ¬ify_data, &tmit,
+ GNUNET_SOCIAL_TALK_NONE);
+}
+
+void
+host_announce ()
+{
+ test = TEST_HOST_ANNOUNCE;
+
+ tmit = (struct TransmitClosure) {};
+ tmit.env = GNUNET_ENV_environment_create ();
+ GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
+ "_foo", DATA2ARG ("bar baz"));
+ GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
+ "_foo_bar", DATA2ARG ("foo bar"));
+ GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
+ "_foo_bar_baz", DATA2ARG ("foo bar baz"));
+ tmit.data[0] = "aaa bbb ccc";
+ tmit.data[1] = "abc def ghi jkl";
+ tmit.data[2] = "testing one two three";
+ tmit.data[3] = "four five";
+ tmit.data_count = 4;
+
+ tmit.host_ann
+ = GNUNET_SOCIAL_host_announce (hst, "_message_host", tmit.env,
+ ¬ify_data, &tmit,
+ GNUNET_SOCIAL_ANNOUNCE_NONE);
+}
+
+void
+host_announce2 ()
+{
+ test = TEST_HOST_ANNOUNCE;
+
+ tmit = (struct TransmitClosure) {};
+ tmit.env = GNUNET_ENV_environment_create ();
+ GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
+ "_foo2", DATA2ARG ("BAR BAZ"));
+ GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
+ "_foo2_bar", DATA2ARG ("FOO BAR"));
+ GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
+ "_foo2_bar", DATA2ARG ("FOO BAR BAZ"));
+ tmit.data[0] = "AAA BBB CCC";
+ tmit.data[1] = "ABC DEF GHI JKL";
+ tmit.data[2] = "TESTING ONE TWO THREE";
+ tmit.data_count = 3;
+
+ tmit.host_ann
+ = GNUNET_SOCIAL_host_announce (hst, "_message_host_two", tmit.env,
+ ¬ify_data, &tmit,
+ GNUNET_SOCIAL_ANNOUNCE_NONE);
+}
+
+
+void
+guest_recv_entry_decision (void *cls,
+ int is_admitted,
+ const struct GNUNET_PSYC_Message *entry_resp)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Guest received entry decision (try %u): %d.\n",
+ join_req_count, is_admitted);
+
+ if (NULL != entry_resp)
+ {
+ struct GNUNET_ENV_Environment *env = GNUNET_ENV_environment_create ();
+ const char *method_name = NULL;
+ const void *data = NULL;
+ uint16_t data_size = 0;
+ GNUNET_PSYC_message_parse (entry_resp, &method_name, env, &data,
&data_size);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%s\n%.*s\n",
+ method_name, data_size, data);
+ /* FIXME: check response message */
+ }
+
+ switch (test)
+ {
+ case TEST_GUEST_RECV_ENTRY_DCSN_REFUSE:
+ GNUNET_assert (GNUNET_NO == is_admitted);
+ guest_enter ();
+ break;
+
+ case TEST_GUEST_RECV_ENTRY_DCSN_ADMIT:
+ GNUNET_assert (GNUNET_YES == is_admitted);
+ host_announce ();
+ break;
+
+ default:
+ GNUNET_assert (0);
+ }
+}
+
+
+void
+host_answer_door (void *cls,
+ struct GNUNET_SOCIAL_Nym *nym,
+ const char *method_name,
+ struct GNUNET_ENV_Environment *env,
+ size_t data_size,
+ const void *data)
+{
+ join_req_count++;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Host received entry request from guest (try %u).\n",
+ join_req_count);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%s\n%.*s\n",
+ method_name, data_size, data);
+
+ switch (test)
+ {
+ case TEST_HOST_ANSWER_DOOR_REFUSE:
+ test = TEST_GUEST_RECV_ENTRY_DCSN_REFUSE;
+ join_resp = GNUNET_PSYC_message_create ("_refuse_nym", env,
+ DATA2ARG ("Go away!"));
+ GNUNET_SOCIAL_host_entry_decision (hst, nym, GNUNET_NO, join_resp);
+ break;
+
+ case TEST_HOST_ANSWER_DOOR_ADMIT:
+ test = TEST_GUEST_RECV_ENTRY_DCSN_ADMIT;
+ join_resp = GNUNET_PSYC_message_create ("_admit_nym", env,
+ DATA2ARG ("Welcome, nym!"));
+ GNUNET_SOCIAL_host_entry_decision (hst, nym, GNUNET_YES, join_resp);
+ break;
+
+ default:
+ GNUNET_assert (0);
+ }
+}
+
+
+void
+guest_recv_local_enter (void *cls, int result, uint64_t max_message_id)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Guest entered to local place.\n");
+
+}
+
+
+void
+guest_enter ()
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Entering to place as guest.\n");
+
+ struct GuestEnterMessage *emsg = &guest_enter_msg;
+
+ emsg->method_name = "_request_enter";
+ emsg->env = GNUNET_ENV_environment_create ();
+ GNUNET_ENV_environment_add (emsg->env, GNUNET_ENV_OP_ASSIGN,
+ "_abc", "abc def", 7);
+ GNUNET_ENV_environment_add (emsg->env, GNUNET_ENV_OP_ASSIGN,
+ "_abc_def", "abc def ghi", 11);
+ emsg->data = "let me in";
+ emsg->data_size = strlen (emsg->data) + 1;
+ emsg->msg = GNUNET_PSYC_message_create (emsg->method_name, emsg->env,
+ emsg->data, emsg->data_size);
+
+ gst = GNUNET_SOCIAL_guest_enter (cfg, guest_ego, &place_pub_key,
+ &this_peer, 0, NULL, emsg->msg,
+ guest_slicer, &guest_recv_local_enter,
+ &guest_recv_entry_decision, NULL);
+}
+
+
+void id_guest_ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego)
+{
+ GNUNET_assert (NULL != ego);
+ guest_ego = ego;
+
+ guest_slicer = GNUNET_SOCIAL_slicer_create ();
+ GNUNET_SOCIAL_slicer_add (guest_slicer, "",
+ &guest_recv_method, &guest_recv_modifier,
+ &guest_recv_data, &guest_recv_eom, NULL);
+ test = TEST_HOST_ANSWER_DOOR_ADMIT;
+ //host_announce ();
+ guest_enter ();
+}
+
+
+void id_guest_created (void *cls, const char *emsg)
+{
+ if (NULL != emsg)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Could not create guest identity: %s\n", emsg);
+#if 0 == DEBUG_SERVICE
+ GNUNET_assert (0);
+#endif
+ }
+
+ GNUNET_IDENTITY_ego_lookup (cfg, guest_name, &id_guest_ego_cb, NULL);
+}
+
+
+void host_entered (void *cls, uint64_t max_message_id)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Host entered to place.\n");
+
+ GNUNET_IDENTITY_create (id, guest_name, &id_guest_created, NULL);
+}
+
+
+void id_host_ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego)
+{
+ GNUNET_assert (NULL != ego);
+ host_ego = ego;
+
+ host_slicer = GNUNET_SOCIAL_slicer_create ();
+ GNUNET_SOCIAL_slicer_add (host_slicer, "",
+ &host_recv_method, &host_recv_modifier,
+ &host_recv_data, &host_recv_eom, NULL);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Entering to place as host.\n");
+ hst = GNUNET_SOCIAL_host_enter (cfg, host_ego, place_key,
+ GNUNET_PSYC_CHANNEL_PRIVATE, host_slicer,
+ &host_entered, &host_answer_door,
+ &host_farewell, NULL);
+}
+
+
+void id_host_created (void *cls, const char *emsg)
+{
+ if (NULL != emsg)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Could not create host identity: %s\n", emsg);
+#if 0 == DEBUG_SERVICE
+ GNUNET_assert (0);
+#endif
+ }
+
+ GNUNET_IDENTITY_ego_lookup (cfg, host_name, &id_host_ego_cb, NULL);
+}
+
+
+void identity_ego_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego,
+ void **ctx, const char *name)
+{
+
+}
+
+
+void
+core_connected (void *cls, const struct GNUNET_PeerIdentity *my_identity)
+{
+ this_peer = *my_identity;
+
+ id = GNUNET_IDENTITY_connect (cfg, &identity_ego_cb, NULL);
+ GNUNET_IDENTITY_create (id, host_name, &id_host_created, NULL);
+}
+
+
/**
* Main function of the test, run from scheduler.
*
@@ -116,7 +773,7 @@
* @param cfg configuration we use (also to connect to Social service)
* @param peer handle to access more of the peer (not used)
*/
-static void
+void
#if DEBUG_SERVICE
run (void *cls, char *const *args, const char *cfgfile,
const struct GNUNET_CONFIGURATION_Handle *c)
@@ -129,9 +786,14 @@
cfg = c;
end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
- /* FIXME: add tests */
+ place_key = GNUNET_CRYPTO_eddsa_key_create ();
+ guest_key = GNUNET_CRYPTO_ecdsa_key_create ();
- end ();
+ GNUNET_CRYPTO_eddsa_key_get_public (place_key, &place_pub_key);
+ GNUNET_CRYPTO_ecdsa_key_get_public (guest_key, &guest_pub_key);
+
+ core = GNUNET_CORE_connect (cfg, NULL, &core_connected, NULL, NULL,
+ NULL, GNUNET_NO, NULL, GNUNET_NO, NULL);
}
Modified: gnunet/src/util/client_manager.c
===================================================================
--- gnunet/src/util/client_manager.c 2014-07-23 16:19:46 UTC (rev 34020)
+++ gnunet/src/util/client_manager.c 2014-07-23 16:19:49 UTC (rev 34021)
@@ -30,7 +30,7 @@
#include "platform.h"
#include "gnunet_util_lib.h"
-#define LOG(kind,...) GNUNET_log_from (kind, "util",__VA_ARGS__)
+#define LOG(kind,...) GNUNET_log_from (kind, "util-client-mgr", __VA_ARGS__)
/**
@@ -94,6 +94,16 @@
const struct GNUNET_CLIENT_MANAGER_MessageHandler *handlers;
/**
+ * Disconnect callback.
+ */
+ void (*disconnect_cb)(void *);
+
+ /**
+ * Disconnect closure.
+ */
+ void *disconnect_cls;
+
+ /**
* User context value.
* @see GNUNET_CLIENT_MANAGER_set_user_context()
* @see GNUNET_CLIENT_MANAGER_get_user_context()
@@ -125,7 +135,7 @@
* #GNUNET_YES if GNUNET_CLIENT_MANAGER_disconnect() was called
* and we're transmitting the last messages from the queue.
*/
- uint8_t disconnecting;
+ uint8_t is_disconnecting;
};
@@ -185,6 +195,15 @@
transmit_next (struct GNUNET_CLIENT_MANAGER_Connection *mgr);
+static void
+schedule_disconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct GNUNET_CLIENT_MANAGER_Connection *mgr = cls;
+ GNUNET_CLIENT_MANAGER_disconnect (mgr, GNUNET_NO,
+ mgr->disconnect_cb, mgr->disconnect_cls);
+}
+
+
/**
* Transmit next message to service.
*
@@ -221,7 +240,14 @@
GNUNET_free (mqi);
if (NULL != mgr->tmit_head)
+ {
transmit_next (mgr);
+ }
+ else if (GNUNET_YES == mgr->is_disconnecting)
+ {
+ GNUNET_SCHEDULER_add_now (&schedule_disconnect, mgr);
+ return size;
+ }
if (GNUNET_NO == mgr->in_receive)
{
@@ -247,8 +273,9 @@
if (NULL == mgr->tmit_head)
{
- if (GNUNET_YES == mgr->disconnecting)
- GNUNET_CLIENT_MANAGER_disconnect (mgr, GNUNET_NO);
+ if (GNUNET_YES == mgr->is_disconnecting)
+ GNUNET_CLIENT_MANAGER_disconnect (mgr, GNUNET_NO,
+ mgr->disconnect_cb,
mgr->disconnect_cls);
return;
}
@@ -269,7 +296,7 @@
* @param tc Scheduler context.
*/
static void
-reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+schedule_reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
struct GNUNET_CLIENT_MANAGER_Connection *mgr = cls;
mgr->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
@@ -305,7 +332,7 @@
mgr->service_name = service_name;
mgr->handlers = handlers;
mgr->reconnect_delay = GNUNET_TIME_UNIT_ZERO;
- mgr->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, mgr);
+ mgr->reconnect_task = GNUNET_SCHEDULER_add_now (&schedule_reconnect, mgr);
return mgr;
}
@@ -315,17 +342,25 @@
*
* @param mgr Client manager connection.
* @param transmit_queue Transmit pending messages in queue before
disconnecting.
+ * @param disconnect_cb Function called after disconnected from the service.
+ * @param disconnect_cls Closure for @a disconnect_cb.
*/
void
GNUNET_CLIENT_MANAGER_disconnect (struct GNUNET_CLIENT_MANAGER_Connection *mgr,
- int transmit_queue)
+ int transmit_queue,
+ GNUNET_ContinuationCallback disconnect_cb,
+ void *disconnect_cls)
{
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting (%d)\n", transmit_queue);
+ mgr->disconnect_cb = disconnect_cb;
+ mgr->disconnect_cls = disconnect_cls;
if (NULL != mgr->tmit_head)
{
if (GNUNET_YES == transmit_queue)
{
- mgr->disconnecting = GNUNET_YES;
+ mgr->is_disconnecting = GNUNET_YES;
transmit_next (mgr);
+ return;
}
else
{
@@ -350,7 +385,10 @@
GNUNET_CLIENT_disconnect (mgr->client);
mgr->client = NULL;
}
+ if (NULL != mgr->disconnect_cb)
+ mgr->disconnect_cb (mgr->disconnect_cls);
GNUNET_free (mgr);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnected.\n");
}
@@ -380,7 +418,7 @@
"Scheduling task to reconnect to service in %s.\n",
GNUNET_STRINGS_relative_time_to_string (mgr->reconnect_delay,
GNUNET_YES));
mgr->reconnect_task =
- GNUNET_SCHEDULER_add_delayed (mgr->reconnect_delay, &reconnect, mgr);
+ GNUNET_SCHEDULER_add_delayed (mgr->reconnect_delay, &schedule_reconnect,
mgr);
mgr->reconnect_delay = GNUNET_TIME_STD_BACKOFF (mgr->reconnect_delay);
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r34021 - in gnunet: contrib src/include src/multicast src/psyc src/social src/util,
gnunet <=