X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fsocial%2Fgnunet-service-social.c;h=e6ee24a4fd5dbc2b5ef462b969590b5ea1b6f892;hb=2105059516320800eaa8fff1196b58f29a50ba7c;hp=d4dfe9b0f627723b74305a37cf70d38235533e72;hpb=50eaf8d7de763d25b7dae7ffdee8d7c6b5fe71ea;p=oweals%2Fgnunet.git diff --git a/src/social/gnunet-service-social.c b/src/social/gnunet-service-social.c index d4dfe9b0f..e6ee24a4f 100644 --- a/src/social/gnunet-service-social.c +++ b/src/social/gnunet-service-social.c @@ -1,6 +1,6 @@ /* * This file is part of GNUnet - * Copyright (C) 2013 Christian Grothoff (and other contributing authors) + * Copyright (C) 2013 GNUnet e.V. * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published @@ -31,7 +31,6 @@ #include "gnunet_util_lib.h" #include "gnunet_constants.h" #include "gnunet_protocols.h" -#include "gnunet_core_service.h" #include "gnunet_identity_service.h" #include "gnunet_namestore_service.h" #include "gnunet_gns_service.h" @@ -47,8 +46,12 @@ */ static const struct GNUNET_CONFIGURATION_Handle *cfg; +/** + * Service handle. + */ +static struct GNUNET_SERVICE_Handle *service; + /* Handles to other services */ -static struct GNUNET_CORE_Handle *core; static struct GNUNET_IDENTITY_Handle *id; static struct GNUNET_GNS_Handle *gns; static struct GNUNET_NAMESTORE_Handle *namestore; @@ -59,11 +62,6 @@ static struct GNUNET_STATISTICS_Handle *stats; */ static struct GNUNET_PeerIdentity this_peer; -/** - * Notification context, simplifies client broadcasts. - */ -static struct GNUNET_SERVER_NotificationContext *nc; - /** * All connected hosts. * H(place_pub_key) -> struct Host @@ -139,7 +137,7 @@ struct FragmentTransmitQueue struct FragmentTransmitQueue *prev; struct FragmentTransmitQueue *next; - struct GNUNET_SERVER_Client *client; + struct GNUNET_SERVICE_Client *client; /** * Pointer to the next message part inside the data after this struct. @@ -171,7 +169,7 @@ struct MessageTransmitQueue struct FragmentTransmitQueue *frags_head; struct FragmentTransmitQueue *frags_tail; - struct GNUNET_SERVER_Client *client; + struct GNUNET_SERVICE_Client *client; }; /** @@ -182,7 +180,7 @@ struct ClientListItem struct ClientListItem *prev; struct ClientListItem *next; - struct GNUNET_SERVER_Client *client; + struct GNUNET_SERVICE_Client *client; }; @@ -229,10 +227,10 @@ struct Place */ struct GNUNET_HashCode ego_pub_hash; - uint64_t file_message_id; - uint64_t file_fragment_offset; - uint64_t file_size; - uint64_t file_offset; + /** + * Slicer for processing incoming messages. + */ + struct GNUNET_PSYC_Slicer *slicer; /** * Last message ID received for the place. @@ -241,9 +239,14 @@ struct Place uint64_t max_message_id; /** - * Is this a host (#GNUNET_YES), or guest (#GNUNET_NO)? + * Offset where the file is currently being written. */ - uint8_t is_host; + uint64_t file_offset; + + /** + * Whether or not to save the file (#GNUNET_YES or #GNUNET_NO) + */ + uint8_t file_save; /** * Is this place ready to receive messages from client? @@ -256,6 +259,16 @@ struct Place * #GNUNET_YES or #GNUNET_NO */ uint8_t is_disconnected; + + /** + * Is this a host (#GNUNET_YES), or guest (#GNUNET_NO)? + */ + uint8_t is_host; + + union { + struct Host *host; + struct Guest *guest; + }; }; @@ -267,7 +280,7 @@ struct Host /** * Place struct common for Host and Guest */ - struct Place plc; + struct Place place; /** * Handle for the multicast origin. @@ -285,6 +298,11 @@ struct Host */ struct GNUNET_CONTAINER_MultiHashMap *join_reqs; + /** + * Messages being relayed. + */ + struct GNUNET_CONTAINER_MultiHashMap *relay_msgs; + /** * @see enum GNUNET_PSYC_Policy */ @@ -300,7 +318,7 @@ struct Guest /** * Place struct common for Host and Guest. */ - struct Place plc; + struct Place place; /** * Handle for the PSYC slave. @@ -349,10 +367,15 @@ struct Guest */ struct Client { + /** + * Client handle. + */ + struct GNUNET_SERVICE_Client *client; + /** * Place where the client entered. */ - struct Place *plc; + struct Place *place; /** * Message queue for the message currently being transmitted @@ -382,8 +405,7 @@ struct Ego { struct OperationClosure { - struct GNUNET_SERVER_Client *client; - struct Place *plc; + struct Client *client; uint64_t op_id; uint32_t flags; }; @@ -393,14 +415,32 @@ static int psyc_transmit_message (struct Place *plc); +/** + * Clean up place data structures after a client disconnected. + * + * @param cls the `struct Place` to clean up + */ static void -cleanup_place (struct Place *plc); +cleanup_place (void *cls); -int -place_entry_cleanup (void *cls, const struct GNUNET_HashCode *key, void *value) +static struct MessageTransmitQueue * +psyc_transmit_queue_message (struct Place *plc, + struct GNUNET_SERVICE_Client *client, + size_t data_size, + const void *data, + uint16_t first_ptype, uint16_t last_ptype, + struct MessageTransmitQueue *tmit_msg); + + +static int +place_entry_cleanup (void *cls, + const struct GNUNET_HashCode *key, + void *value) { - cleanup_place (value); + struct Place *plc = value; + + cleanup_place (plc); return GNUNET_YES; } @@ -409,24 +449,13 @@ place_entry_cleanup (void *cls, const struct GNUNET_HashCode *key, void *value) * Task run during shutdown. * * @param cls unused - * @param tc unused */ static void -shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +shutdown_task (void *cls) { GNUNET_CONTAINER_multihashmap_iterate (hosts, place_entry_cleanup, NULL); GNUNET_CONTAINER_multihashmap_iterate (guests, place_entry_cleanup, NULL); - if (NULL != nc) - { - GNUNET_SERVER_notification_context_destroy (nc); - nc = NULL; - } - if (NULL != core) - { - GNUNET_CORE_disconnect (core); - core = NULL; - } if (NULL != id) { GNUNET_IDENTITY_disconnect (id); @@ -456,11 +485,12 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) static void cleanup_host (struct Host *hst) { - struct Place *plc = &hst->plc; + struct Place *plc = &hst->place; if (NULL != hst->master) GNUNET_PSYC_master_stop (hst->master, GNUNET_NO, NULL, NULL); // FIXME GNUNET_CONTAINER_multihashmap_destroy (hst->join_reqs); + GNUNET_CONTAINER_multihashmap_destroy (hst->relay_msgs); GNUNET_CONTAINER_multihashmap_remove (hosts, &plc->pub_key_hash, plc); } @@ -471,10 +501,10 @@ cleanup_host (struct Host *hst) static void cleanup_guest (struct Guest *gst) { - struct Place *plc = &gst->plc; + struct Place *plc = &gst->place; struct GNUNET_CONTAINER_MultiHashMap * plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests, - &plc->pub_key_hash); + &plc->pub_key_hash); GNUNET_assert (NULL != plc_gst); // FIXME GNUNET_CONTAINER_multihashmap_remove (plc_gst, &plc->ego_pub_hash, gst); @@ -498,10 +528,14 @@ cleanup_guest (struct Guest *gst) /** * Clean up place data structures after a client disconnected. + * + * @param cls the `struct Place` to clean up */ static void -cleanup_place (struct Place *plc) +cleanup_place (void *cls) { + struct Place *plc = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Cleaning up place %s\n", plc, GNUNET_h2s (&plc->pub_key_hash)); @@ -509,14 +543,9 @@ cleanup_place (struct Place *plc) (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); + GNUNET_PSYC_slicer_destroy (plc->slicer); + GNUNET_free (plc); } @@ -524,30 +553,22 @@ schedule_cleanup_place (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc * Called whenever a client is disconnected. * Frees our resources associated with that client. * - * @param cls Closure. - * @param client Identification of the client. + * @param cls closure + * @param client identification of the client + * @param app_ctx must match @a client */ static void -client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) +client_notify_disconnect (void *cls, + struct GNUNET_SERVICE_Client *client, + void *app_ctx) { - if (NULL == client) - return; + struct Client *c = app_ctx; + struct Place *plc = c->place; - struct Client * - ctx = GNUNET_SERVER_client_get_user_context (client, struct Client); - if (NULL == ctx) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "%p User context is NULL in client_disconnect()\n", ctx); - return; - } - - struct Place *plc = ctx->plc; + if (NULL != c->app_id) + GNUNET_free (c->app_id); - if (NULL != ctx->app_id) - GNUNET_free (ctx->app_id); - - GNUNET_free (ctx); + GNUNET_free (c); if (NULL == plc) return; // application client, nothing to do @@ -571,15 +592,40 @@ client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) } +/** + * A new client connected. + * + * @param cls NULL + * @param client client to add + * @param mq message queue for @a client + * @return @a client + */ +static void * +client_notify_connect (void *cls, + struct GNUNET_SERVICE_Client *client, + struct GNUNET_MQ_Handle *mq) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connected: %p\n", client); + + struct Client *c = GNUNET_malloc (sizeof (*c)); + c->client = client; + + return c; +} + + /** * Send message to a client. */ static inline void -client_send_msg (struct GNUNET_SERVER_Client *client, +client_send_msg (struct GNUNET_SERVICE_Client *client, const struct GNUNET_MessageHeader *msg) { - GNUNET_SERVER_notification_context_add (nc, client); - GNUNET_SERVER_notification_context_unicast (nc, client, msg, GNUNET_NO); + struct GNUNET_MQ_Envelope * + env = GNUNET_MQ_msg_copy (msg); + + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), + env); } @@ -617,7 +663,7 @@ place_send_msg (const struct Place *plc, * Size of @a data. */ static void -client_send_result (struct GNUNET_SERVER_Client *client, uint64_t op_id, +client_send_result (struct GNUNET_SERVICE_Client *client, uint64_t op_id, int64_t result_code, const void *data, uint16_t data_size) { struct GNUNET_OperationResultMessage *res; @@ -628,7 +674,7 @@ client_send_result (struct GNUNET_SERVER_Client *client, uint64_t op_id, res->result_code = GNUNET_htonll (result_code); res->op_id = op_id; if (0 < data_size) - memcpy (&res[1], data, data_size); + GNUNET_memcpy (&res[1], data, data_size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Sending result to client for operation #%" PRIu64 ": " @@ -641,10 +687,10 @@ client_send_result (struct GNUNET_SERVER_Client *client, uint64_t op_id, static void -client_send_host_enter_ack (struct GNUNET_SERVER_Client *client, +client_send_host_enter_ack (struct GNUNET_SERVICE_Client *client, struct Host *hst, uint32_t result) { - struct Place *plc = &hst->plc; + struct Place *plc = &hst->place; struct HostEnterAck hack; hack.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK); @@ -667,7 +713,7 @@ static void psyc_master_started (void *cls, int result, uint64_t max_message_id) { struct Host *hst = cls; - struct Place *plc = &hst->plc; + struct Place *plc = &hst->place; plc->max_message_id = max_message_id; plc->is_ready = GNUNET_YES; @@ -690,7 +736,7 @@ psyc_recv_join_request (void *cls, 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); - place_send_msg (&hst->plc, &req->header); + place_send_msg (&hst->place, &req->header); } @@ -701,7 +747,7 @@ static void psyc_slave_connected (void *cls, int result, uint64_t max_message_id) { struct Guest *gst = cls; - struct Place *plc = &gst->plc; + struct Place *plc = &gst->place; plc->max_message_id = max_message_id; plc->is_ready = GNUNET_YES; @@ -725,99 +771,305 @@ psyc_recv_join_dcsn (void *cls, const struct GNUNET_PSYC_Message *join_msg) { struct Guest *gst = cls; - place_send_msg (&gst->plc, &dcsn->header); + place_send_msg (&gst->place, &dcsn->header); } + /** - * Save _file data to disk. + * Called when a PSYC master or slave receives a message. */ -void -psyc_recv_file (struct Place *plc, const struct GNUNET_PSYC_MessageHeader *msg, - uint32_t flags, uint64_t message_id, uint64_t fragment_offset, - const char *method_name, struct GNUNET_PSYC_Environment *env, - const void *data, uint16_t data_size) +static void +psyc_recv_message (void *cls, + const struct GNUNET_PSYC_MessageHeader *msg) +{ + struct Place *plc = cls; + + char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&msg->slave_pub_key); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "%p Received PSYC message of size %u from %s.\n", + plc, ntohs (msg->header.size), str); + GNUNET_free (str); + + GNUNET_PSYC_slicer_message (plc->slicer, msg); + + place_send_msg (plc, &msg->header); +} + + +/** + * Relay a message part received from a guest to the the place. + * + * @param hst + * Host. + * @param pmsg + * Message part. + * @param nym_pub_key + * Nym the message is received from. + */ +static void +host_relay_message_part (struct Host *hst, + const struct GNUNET_MessageHeader *pmsg, + const struct GNUNET_CRYPTO_EcdsaPublicKey *nym_pub_key) +{ + /* separate queue per nym */ + struct GNUNET_HashCode nym_pub_hash; + GNUNET_CRYPTO_hash (nym_pub_key, sizeof (*nym_pub_key), &nym_pub_hash); + + struct MessageTransmitQueue * + tmit_msg = GNUNET_CONTAINER_multihashmap_get (hst->relay_msgs, &nym_pub_hash); + + uint16_t ptype = ntohs (pmsg->type); + + if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == ptype) + { + /* FIXME: last message was unfinished, cancel & remove from queue */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "FIXME: last message was unfinished.\n"); + } + + tmit_msg = psyc_transmit_queue_message (&hst->place, NULL, ntohs (pmsg->size), + pmsg, ptype, ptype, tmit_msg); + + switch (ptype) + { + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD: + GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_put + (hst->relay_msgs, &nym_pub_hash, tmit_msg, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); + break; + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END: + case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL: + GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove + (hst->relay_msgs, &nym_pub_hash, tmit_msg)); + break; + } +} + + +/** + * Received a method to be relayed from a guest. + */ +static void +place_recv_relay_method (void *cls, + const struct GNUNET_PSYC_MessageHeader *msg, + const struct GNUNET_PSYC_MessageMethod *meth, + uint64_t message_id, + const char *method_name) +{ + struct Place *plc = cls; + + if (GNUNET_PSYC_MESSAGE_REQUEST & ntohs (msg->flags) + && GNUNET_YES == plc->is_host) + { + struct Host *hst = cls; + host_relay_message_part (hst, &meth->header, &msg->slave_pub_key); + } +} + + +/** + * Received a modifier to be relayed from a guest. + */ +static void +place_recv_relay_modifier (void *cls, + const struct GNUNET_PSYC_MessageHeader *msg, + const struct GNUNET_MessageHeader *pmsg, + uint64_t message_id, + enum GNUNET_PSYC_Operator oper, + const char *name, + const void *value, + uint16_t value_size, + uint16_t full_value_size) +{ + struct Place *plc = cls; + + if (GNUNET_PSYC_MESSAGE_REQUEST & ntohs (msg->flags) + && GNUNET_YES == plc->is_host) + { + struct Host *hst = cls; + host_relay_message_part (hst, pmsg, &msg->slave_pub_key); + } +} + +/** + * Received a data fragment to be relayed from a guest. + */ +static void +place_recv_relay_data (void *cls, + const struct GNUNET_PSYC_MessageHeader *msg, + const struct GNUNET_MessageHeader *pmsg, + uint64_t message_id, + const void *data, + uint16_t data_size) +{ + struct Place *plc = cls; + + if (GNUNET_PSYC_MESSAGE_REQUEST & ntohs (msg->flags) + && GNUNET_YES == plc->is_host) + { + struct Host *hst = cls; + host_relay_message_part (hst, pmsg, &msg->slave_pub_key); + } +} + + +/** + * Received end of message to be relayed from a guest. + */ +static void +place_recv_relay_eom (void *cls, + const struct GNUNET_PSYC_MessageHeader *msg, + const struct GNUNET_MessageHeader *pmsg, + uint64_t message_id, + uint8_t is_cancelled) +{ + struct Place *plc = cls; + + if (GNUNET_PSYC_MESSAGE_REQUEST & ntohs (msg->flags) + && GNUNET_YES == plc->is_host) + { + struct Host *hst = cls; + host_relay_message_part (hst, pmsg, &msg->slave_pub_key); + } +} + + +/** + * Received a method to be saved to disk. + * + * Create a new file for writing the data part of the message into, + * if the file does not yet exist. + */ +static void +place_recv_save_method (void *cls, + const struct GNUNET_PSYC_MessageHeader *msg, + const struct GNUNET_PSYC_MessageMethod *meth, + uint64_t message_id, + const char *method_name) { - if (plc->file_message_id != message_id) + struct Place *plc = cls; + plc->file_offset = 0; + plc->file_save = GNUNET_NO; + + char *place_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (&plc->pub_key); + char *filename = NULL; + GNUNET_asprintf (&filename, "%s%c" "%s%c" "%s%c" "%" PRIu64 ".part", + dir_social, DIR_SEPARATOR, + "files", DIR_SEPARATOR, + place_pub_str, DIR_SEPARATOR, + GNUNET_ntohll (msg->message_id)); + GNUNET_free (place_pub_str); + + /* save if does not already exist */ + if (GNUNET_YES != GNUNET_DISK_file_test (filename)) { - if (0 != fragment_offset) + if (0 == GNUNET_DISK_fn_write (filename, NULL, 0, + GNUNET_DISK_PERM_USER_READ + | GNUNET_DISK_PERM_USER_WRITE)) + { + plc->file_save = GNUNET_YES; + } + else { - /* unexpected message ID */ GNUNET_break (0); - return; } - - /* new file */ - plc->file_offset = 0; } + GNUNET_free (filename); +} - struct GNUNET_CRYPTO_HashAsciiEncoded place_pub_hash_ascii; - memcpy (&place_pub_hash_ascii.encoding, - GNUNET_h2s_full (&plc->pub_key_hash), sizeof (place_pub_hash_ascii)); +/** + * Received a data fragment to be saved to disk. + * + * Append data fragment to the file. + */ +static void +place_recv_save_data (void *cls, + const struct GNUNET_PSYC_MessageHeader *msg, + const struct GNUNET_MessageHeader *pmsg, + uint64_t message_id, + const void *data, + uint16_t data_size) +{ + struct Place *plc = cls; + if (GNUNET_YES != plc->file_save) + return; + + char *place_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (&plc->pub_key); char *filename = NULL; - GNUNET_asprintf (&filename, "%s%c%s%c%s%c%" PRIu64, + GNUNET_asprintf (&filename, "%s%c" "%s%c" "%s%c" "%" PRIu64 ".part", dir_social, DIR_SEPARATOR, "files", DIR_SEPARATOR, - place_pub_hash_ascii.encoding, DIR_SEPARATOR, - message_id); - GNUNET_DISK_directory_create_for_file (filename); + place_pub_str, DIR_SEPARATOR, + GNUNET_ntohll (msg->message_id)); + GNUNET_free (place_pub_str); + if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename)) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "create", filename); + GNUNET_free (filename); + return; + } + struct GNUNET_DISK_FileHandle * fh = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE, - GNUNET_DISK_PERM_USER_READ - | GNUNET_DISK_PERM_USER_WRITE); - GNUNET_free (filename); - - GNUNET_DISK_file_seek (fh, plc->file_offset, GNUNET_DISK_SEEK_SET); - GNUNET_DISK_file_write (fh, data, data_size); - GNUNET_DISK_file_close (fh); + GNUNET_DISK_PERM_NONE); + if (NULL != fh) + { + if (plc->file_offset != GNUNET_DISK_file_seek + (fh, plc->file_offset, GNUNET_DISK_SEEK_SET)) { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "seek", filename); + GNUNET_DISK_file_close (fh); + GNUNET_free (filename); + return; + } + GNUNET_DISK_file_write (fh, data, data_size); + GNUNET_DISK_file_close (fh); + GNUNET_free (filename); + } + else + { + GNUNET_free (filename); + GNUNET_break (0); + } plc->file_offset += data_size; } /** - * Called when a PSYC master or slave receives a message. + * Received end of message to be saved to disk. + * + * Remove .part ending from the filename. */ static void -psyc_recv_message (void *cls, - uint64_t message_id, - uint32_t flags, - const struct GNUNET_PSYC_MessageHeader *msg) +place_recv_save_eom (void *cls, + const struct GNUNET_PSYC_MessageHeader *msg, + const struct GNUNET_MessageHeader *pmsg, + uint64_t message_id, + uint8_t is_cancelled) { struct Place *plc = cls; + if (GNUNET_YES != plc->file_save) + return; - char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&msg->slave_key); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "%p Received PSYC message of size %u from %s.\n", - plc, ntohs (msg->header.size), str); - GNUNET_free (str); - - /* process message */ - /* FIXME: use slicer */ - const char *method_name = NULL; - struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create (); - const void *data = NULL; - uint16_t data_size = 0; + char *place_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (&plc->pub_key); + char *fn = NULL; + GNUNET_asprintf (&fn, "%s%c%s%c%s%c%" PRIu64, + dir_social, DIR_SEPARATOR, + "files", DIR_SEPARATOR, + place_pub_str, DIR_SEPARATOR, + GNUNET_ntohll (msg->message_id)); + GNUNET_free (place_pub_str); + char *fn_part = NULL; + GNUNET_asprintf (&fn_part, "%s.part", fn); - if (GNUNET_SYSERR == GNUNET_PSYC_message_parse (msg, &method_name, env, &data, &data_size)) - { - GNUNET_break (0); - } - else - { - char *method_found = strstr (method_name, "_file"); - if (method_name == method_found) - { - method_found += strlen ("_file"); - if (('\0' == *method_found) || ('_' == *method_found)) - { - psyc_recv_file (plc, msg, flags, message_id, GNUNET_ntohll (msg->fragment_offset), - method_name, env, data, data_size); - } - } + if (rename (fn_part, fn)) { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to rename %s into %s: %s (%d)\n", + fn_part, fn, strerror (errno), errno); } - GNUNET_PSYC_env_destroy (env); - place_send_msg (plc, &msg->header); + GNUNET_free (fn); + GNUNET_free (fn_part); } @@ -827,9 +1079,10 @@ psyc_recv_message (void *cls, static void place_init (struct Place *plc) { - + plc->slicer = GNUNET_PSYC_slicer_create (); } + /** * Add a place to the @e places hash map. * @@ -878,8 +1131,8 @@ place_add (const struct PlaceEnterRequest *ereq) * * @param app_id * Application ID. - * @param msg - * Entry message. + * @param ereq + * Entry request. * * @return #GNUNET_OK if the place was added * #GNUNET_NO if the place already exists in the hash map @@ -944,10 +1197,9 @@ app_place_add (const char *app_id, } } - - size_t app_id_size = strlen (app_id); + size_t app_id_size = strlen (app_id) + 1; void *app_id_value = GNUNET_malloc (app_id_size); - memcpy (app_id_value, app_id, app_id_size); + GNUNET_memcpy (app_id_value, app_id, app_id_size); if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (place_apps, &app_id_hash, app_id_value, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) @@ -964,8 +1216,8 @@ app_place_add (const char *app_id, * * @param app_id * Application ID. - * @param msg - * Entry message. + * @param ereq + * Entry request message. */ static int app_place_save (const char *app_id, @@ -976,26 +1228,14 @@ app_place_save (const char *app_id, if (NULL == dir_places) return GNUNET_SYSERR; - struct GNUNET_HashCode ego_pub_hash; - struct GNUNET_HashCode place_pub_hash; - GNUNET_CRYPTO_hash (&ereq->ego_pub_key, sizeof (ereq->ego_pub_key), - &ego_pub_hash); - GNUNET_CRYPTO_hash (&ereq->place_pub_key, sizeof (ereq->place_pub_key), - &place_pub_hash); - - struct GNUNET_CRYPTO_HashAsciiEncoded ego_pub_hash_ascii; - struct GNUNET_CRYPTO_HashAsciiEncoded place_pub_hash_ascii; - memcpy (&ego_pub_hash_ascii.encoding, - GNUNET_h2s_full (&ego_pub_hash), sizeof (ego_pub_hash_ascii)); - memcpy (&place_pub_hash_ascii.encoding, - GNUNET_h2s_full (&place_pub_hash), sizeof (place_pub_hash_ascii)); - + char *ego_pub_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&ereq->ego_pub_key); + char *place_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (&ereq->place_pub_key); char *filename = NULL; GNUNET_asprintf (&filename, "%s%c" "%s%c" "%s%c" "%s", dir_social, DIR_SEPARATOR, "places", DIR_SEPARATOR, - ego_pub_hash_ascii.encoding, DIR_SEPARATOR, - place_pub_hash_ascii.encoding); + ego_pub_str, DIR_SEPARATOR, + place_pub_str); int ret = GNUNET_DISK_directory_create_for_file (filename); if (GNUNET_OK != ret || 0 > GNUNET_DISK_fn_write (filename, ereq, ntohs (ereq->header.size), @@ -1013,8 +1253,8 @@ app_place_save (const char *app_id, dir_social, DIR_SEPARATOR, "apps", DIR_SEPARATOR, app_id, DIR_SEPARATOR, - ego_pub_hash_ascii.encoding, DIR_SEPARATOR, - place_pub_hash_ascii.encoding); + ego_pub_str, DIR_SEPARATOR, + place_pub_str); ret = GNUNET_DISK_directory_create_for_file (filename); if (GNUNET_OK != ret || 0 > GNUNET_DISK_fn_write (filename, "", 0, @@ -1026,28 +1266,34 @@ app_place_save (const char *app_id, } GNUNET_free (filename); } + GNUNET_free (ego_pub_str); + GNUNET_free (place_pub_str); return ret; } int app_place_remove (const char *app_id, + const struct GNUNET_CRYPTO_EcdsaPublicKey *ego_pub_key, const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key) { + struct GNUNET_HashCode ego_pub_hash; struct GNUNET_HashCode place_pub_hash; + GNUNET_CRYPTO_hash (ego_pub_key, sizeof (*ego_pub_key), &ego_pub_hash); GNUNET_CRYPTO_hash (place_pub_key, sizeof (*place_pub_key), &place_pub_hash); - struct GNUNET_CRYPTO_HashAsciiEncoded place_pub_hash_ascii; - memcpy (&place_pub_hash_ascii.encoding, - GNUNET_h2s_full (&place_pub_hash), sizeof (place_pub_hash_ascii)); - + char *ego_pub_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (ego_pub_key); + char *place_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (place_pub_key); char *app_place_filename = NULL; GNUNET_asprintf (&app_place_filename, - "%s%c" "%s%/", + "%s%c" "%s%c" "%s%c" "%s%c" "%s", dir_social, DIR_SEPARATOR, "apps", DIR_SEPARATOR, app_id, DIR_SEPARATOR, - place_pub_hash_ascii.encoding); + ego_pub_str, DIR_SEPARATOR, + place_pub_str); + GNUNET_free (ego_pub_str); + GNUNET_free (place_pub_str); struct GNUNET_HashCode app_id_hash; GNUNET_CRYPTO_hash (app_id, strlen (app_id) + 1, &app_id_hash); @@ -1065,31 +1311,32 @@ app_place_remove (const char *app_id, void *app_id_value = GNUNET_CONTAINER_multihashmap_get (place_apps, &app_id_hash); if (NULL != app_id_value) { + GNUNET_CONTAINER_multihashmap_remove (place_apps, &app_id_hash, app_id_value); GNUNET_free (app_id_value); - GNUNET_CONTAINER_multihashmap_remove_all (place_apps, &app_id_hash); } } + int ret = GNUNET_OK; - int ret = unlink (app_place_filename); - GNUNET_free (app_place_filename); - if (0 != ret) + if (0 != unlink (app_place_filename)) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Error removing app place: unlink returned %d\n", errno); - return GNUNET_SYSERR; + "Error removing app place file: %s: %s (%d)\n", + app_place_filename, strerror (errno), errno); + ret = GNUNET_SYSERR; } + GNUNET_free (app_place_filename); - return GNUNET_OK; + return ret; } /** * Enter place as host. * - * @param req - * Entry request. + * @param hreq + * Host entry request. * @param[out] ret_hst * Returned Host struct. * @@ -1112,26 +1359,155 @@ host_enter (const struct HostEnterRequest *hreq, struct Host **ret_hst) hst = GNUNET_new (struct Host); hst->policy = hreq->policy; hst->join_reqs = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); + hst->relay_msgs = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); + + struct Place *plc = &hst->place; + place_init (plc); + plc->is_host = GNUNET_YES; + plc->pub_key = hreq->place_pub_key; + plc->pub_key_hash = place_pub_hash; + + GNUNET_CONTAINER_multihashmap_put (hosts, &plc->pub_key_hash, plc, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); + hst->master = GNUNET_PSYC_master_start (cfg, &hreq->place_key, hst->policy, + &psyc_master_started, + &psyc_recv_join_request, + &psyc_recv_message, NULL, hst); + plc->channel = GNUNET_PSYC_master_get_channel (hst->master); + ret = GNUNET_YES; + } + + if (NULL != ret_hst) + *ret_hst = hst; + return ret; +} + + +static int +msg_proc_parse (const struct MsgProcRequest *mpreq, + uint32_t *flags, + const char **method_prefix, + struct GNUNET_HashCode *method_hash) +{ + uint8_t method_size = ntohs (mpreq->header.size) - sizeof (*mpreq); + uint16_t offset = GNUNET_STRINGS_buffer_tokenize ((const char *) &mpreq[1], + method_size, 1, method_prefix); + + if (0 == offset || offset != method_size || *method_prefix == NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "offset = %u, method_size = %u, method_name = %s\n", + offset, method_size, *method_prefix); + return GNUNET_SYSERR; + } + + GNUNET_CRYPTO_hash (*method_prefix, method_size, method_hash); + *flags = ntohl (mpreq->flags); + return GNUNET_OK; +} + + +static int +check_client_msg_proc_set (void *cls, + const struct MsgProcRequest *mpreq) +{ + return GNUNET_OK; +} + + +/** + * Handle a client setting message proccesing flags for a method prefix. + */ +static void +handle_client_msg_proc_set (void *cls, + const struct MsgProcRequest *mpreq) +{ + struct Client *c = cls; + struct GNUNET_SERVICE_Client *client = c->client; + struct Place *plc = c->place; + if (NULL == plc) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (client); + return; + } + + const char *method_prefix = NULL; + uint32_t flags = 0; + struct GNUNET_HashCode method_hash; + + if (GNUNET_OK != + msg_proc_parse (mpreq, &flags, &method_prefix, &method_hash)) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (client); + return; + } +#if 0 + GNUNET_PSYC_slicer_method_remove (plc->slicer, method_prefix, + place_recv_relay_method, + place_recv_relay_modifier, + place_recv_relay_data, + place_recv_relay_eom); + GNUNET_PSYC_slicer_method_remove (plc->slicer, method_prefix, + place_recv_save_method, + NULL, + place_recv_save_data, + place_recv_save_eom); +#endif + if (flags & GNUNET_SOCIAL_MSG_PROC_RELAY) + { + GNUNET_PSYC_slicer_method_add (plc->slicer, method_prefix, NULL, + place_recv_relay_method, + place_recv_relay_modifier, + place_recv_relay_data, + place_recv_relay_eom, + plc); + } + if (flags & GNUNET_SOCIAL_MSG_PROC_SAVE) + { + GNUNET_PSYC_slicer_method_add (plc->slicer, method_prefix, NULL, + place_recv_save_method, + NULL, + place_recv_save_data, + place_recv_save_eom, + plc); + } + + /** @todo Save flags to be able to resume relaying/saving after restart */ - struct Place *plc = &hst->plc; - place_init (plc); - plc->is_host = GNUNET_YES; - plc->pub_key = hreq->place_pub_key; - plc->pub_key_hash = place_pub_hash; + GNUNET_SERVICE_client_continue (client); +} - GNUNET_CONTAINER_multihashmap_put (hosts, &plc->pub_key_hash, plc, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - hst->master = GNUNET_PSYC_master_start (cfg, &hreq->place_key, hst->policy, - &psyc_master_started, - &psyc_recv_join_request, - &psyc_recv_message, NULL, hst); - hst->plc.channel = GNUNET_PSYC_master_get_channel (hst->master); - ret = GNUNET_YES; + +/** + * Handle a connecting client requesting to clear all relay rules. + */ +static void +handle_client_msg_proc_clear (void *cls, + const struct GNUNET_MessageHeader *msg) +{ + struct Client *c = cls; + struct GNUNET_SERVICE_Client *client = c->client; + struct Place *plc = c->place; + if (NULL == plc) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (client); + return; } - if (NULL != ret_hst) - *ret_hst = hst; - return ret; + GNUNET_PSYC_slicer_clear (plc->slicer); + + GNUNET_SERVICE_client_continue (client); +} + + +static int +check_client_host_enter (void *cls, + const struct HostEnterRequest *hr) +{ + return GNUNET_OK; } @@ -1139,11 +1515,14 @@ host_enter (const struct HostEnterRequest *hreq, struct Host **ret_hst) * 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) +handle_client_host_enter (void *cls, + const struct HostEnterRequest *hr) { - struct HostEnterRequest *hreq - = (struct HostEnterRequest *) GNUNET_copy_message (msg); + struct Client *c = cls; + struct GNUNET_SERVICE_Client *client = c->client; + + struct HostEnterRequest * + hreq = (struct HostEnterRequest *) GNUNET_copy_message (&hr->header); uint8_t app_id_size = ntohs (hreq->header.size) - sizeof (*hreq); const char *app_id = NULL; @@ -1155,7 +1534,7 @@ client_recv_host_enter (void *cls, struct GNUNET_SERVER_Client *client, "offset = %u, app_id_size = %u, app_id = %s\n", offset, app_id_size, app_id); GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } @@ -1181,12 +1560,14 @@ client_recv_host_enter (void *cls, struct GNUNET_SERVER_Client *client, switch (host_enter (hreq, &hst)) { case GNUNET_YES: - plc = &hst->plc; + plc = c->place = &hst->place; + plc->host = hst; break; case GNUNET_NO: { - plc = &hst->plc; + plc = c->place = &hst->place; + plc->host = hst; client_send_host_enter_ack (client, hst, GNUNET_OK); break; } @@ -1204,23 +1585,24 @@ client_recv_host_enter (void *cls, struct GNUNET_SERVER_Client *client, 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); + c->place = plc; } GNUNET_CRYPTO_eddsa_key_clear (&hreq->place_key); GNUNET_free (hreq); - GNUNET_SERVER_receive_done (client, ret); + + if (GNUNET_OK == ret) + GNUNET_SERVICE_client_continue (client); + else + GNUNET_SERVICE_client_drop (client); } /** * Enter place as guest. * - * @param req - * Entry request. + * @param greq + * Guest entry request. * @param[out] ret_gst * Returned Guest struct. * @@ -1267,6 +1649,7 @@ guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst) len = strnlen (app_id, remaining); if (len == remaining) { + GNUNET_free (gst); GNUNET_break (0); return GNUNET_SYSERR; } @@ -1277,6 +1660,7 @@ guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst) uint16_t relay_size = gst->relay_count * sizeof (*relays); if (remaining < relay_size) { + GNUNET_free (gst); GNUNET_break (0); return GNUNET_SYSERR; } @@ -1298,21 +1682,21 @@ guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst) if (0 != remaining) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "%u + %u + %u != %u\n", + "%zu + %u + %u != %u\n", sizeof (*greq), relay_size, join_msg_size, greq_size); - GNUNET_break (0); GNUNET_free (gst); + GNUNET_break (0); return GNUNET_SYSERR; } if (0 < relay_size) { gst->relays = GNUNET_malloc (relay_size); - memcpy (gst->relays, relays, relay_size); + GNUNET_memcpy (gst->relays, relays, relay_size); } gst->join_flags = ntohl (greq->flags); - struct Place *plc = &gst->plc; + struct Place *plc = &gst->place; place_init (plc); plc->is_host = GNUNET_NO; plc->pub_key = greq->place_pub_key; @@ -1339,7 +1723,7 @@ guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst) &psyc_slave_connected, &psyc_recv_join_dcsn, gst, join_msg); - gst->plc.channel = GNUNET_PSYC_slave_get_channel (gst->slave); + plc->channel = GNUNET_PSYC_slave_get_channel (gst->slave); ret = GNUNET_YES; } @@ -1349,15 +1733,23 @@ guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst) } +static int +check_client_guest_enter (void *cls, + const struct GuestEnterRequest *greq) +{ + return 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) +handle_client_guest_enter (void *cls, + const struct GuestEnterRequest *greq) { - const struct GuestEnterRequest * - greq = (const struct GuestEnterRequest *) msg; + struct Client *c = cls; + struct GNUNET_SERVICE_Client *client = c->client; uint16_t remaining = ntohs (greq->header.size) - sizeof (*greq); const char *app_id = NULL; @@ -1366,7 +1758,7 @@ client_recv_guest_enter (void *cls, struct GNUNET_SERVER_Client *client, if (0 == offset) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } @@ -1376,13 +1768,15 @@ client_recv_guest_enter (void *cls, struct GNUNET_SERVER_Client *client, switch (guest_enter (greq, &gst)) { case GNUNET_YES: - plc = &gst->plc; + plc = c->place = &gst->place; + plc->guest = gst; app_place_save (app_id, (const struct PlaceEnterRequest *) greq); break; case GNUNET_NO: { - plc = &gst->plc; + plc = c->place = &gst->place; + plc->guest = gst; struct GNUNET_PSYC_CountersResultMessage res; res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK); @@ -1398,7 +1792,7 @@ client_recv_guest_enter (void *cls, struct GNUNET_SERVER_Client *client, } case GNUNET_SYSERR: GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } @@ -1410,16 +1804,14 @@ client_recv_guest_enter (void *cls, struct GNUNET_SERVER_Client *client, 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); + c->place = plc; + GNUNET_SERVICE_client_continue (client); } struct GuestEnterByNameClosure { - struct GNUNET_SERVER_Client *client; + struct Client *client; char *app_id; char *password; struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key; @@ -1437,8 +1829,10 @@ gns_result_guest_enter (void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct GuestEnterByNameClosure *gcls = cls; + struct Client *c = gcls->client; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "%p GNS result: %u records.\n", gcls->client, rd_count); + "%p GNS result: %u records.\n", + c, rd_count); const struct GNUNET_GNSRECORD_PlaceData * rec = (const struct GNUNET_GNSRECORD_PlaceData *) rd->data; @@ -1446,7 +1840,7 @@ gns_result_guest_enter (void *cls, uint32_t rd_count, if (0 == rd_count || rd->data_size < sizeof (*rec)) { GNUNET_break (0); - GNUNET_SERVER_receive_done (gcls->client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (c->client); return; } @@ -1482,13 +1876,13 @@ gns_result_guest_enter (void *cls, uint32_t rd_count, greq->relay_count = rec->relay_count; void *p = &greq[1]; - memcpy (p, gcls->app_id, app_id_size); + GNUNET_memcpy (p, gcls->app_id, app_id_size); p += app_id_size; - memcpy (p, relays, relay_size); + GNUNET_memcpy (p, relays, relay_size); p += relay_size; - memcpy (p, gcls->join_msg, join_msg_size); + GNUNET_memcpy (p, gcls->join_msg, join_msg_size); - client_recv_guest_enter (NULL, gcls->client, &greq->header); + handle_client_guest_enter (c, greq); GNUNET_free (gcls->app_id); if (NULL != gcls->password) @@ -1500,20 +1894,28 @@ gns_result_guest_enter (void *cls, uint32_t rd_count, } +static int +check_client_guest_enter_by_name (void *cls, + const struct GuestEnterByNameRequest *greq) +{ + return GNUNET_OK; +} + + /** * Handle a connecting client entering a place as guest using a GNS address. * * Look up GNS address and generate a GuestEnterRequest from that. */ static void -client_recv_guest_enter_by_name (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *msg) +handle_client_guest_enter_by_name (void *cls, + const struct GuestEnterByNameRequest *greq) { - const struct GuestEnterByNameRequest * - greq = (const struct GuestEnterByNameRequest *) msg; + struct Client *c = cls; + struct GNUNET_SERVICE_Client *client = c->client; struct GuestEnterByNameClosure *gcls = GNUNET_malloc (sizeof (*gcls)); - gcls->client = client; + gcls->client = c; gcls->ego_pub_key = greq->ego_pub_key; const char *p = (const char *) &greq[1]; @@ -1536,20 +1938,21 @@ client_recv_guest_enter_by_name (void *cls, struct GNUNET_SERVER_Client *client, { if (NULL != gcls->join_msg) GNUNET_free (gcls->join_msg); + GNUNET_free (gcls); GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } uint16_t app_id_size = strlen (app_id) + 1; gcls->app_id = GNUNET_malloc (app_id_size); - memcpy (gcls->app_id, app_id, app_id_size); + GNUNET_memcpy (gcls->app_id, app_id, app_id_size); uint16_t password_size = strlen (password); if (0 < password_size++) { gcls->password = GNUNET_malloc (password_size); - memcpy (gcls->password, password, password_size); + GNUNET_memcpy (gcls->password, password, password_size); } GNUNET_GNS_lookup (gns, gns_name, &greq->ego_pub_key, @@ -1560,7 +1963,7 @@ client_recv_guest_enter_by_name (void *cls, struct GNUNET_SERVER_Client *client, void app_notify_place (struct GNUNET_MessageHeader *msg, - struct GNUNET_SERVER_Client *client) + struct GNUNET_SERVICE_Client *client) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Sending place notification of type %u to client.\n", @@ -1602,7 +2005,22 @@ app_notify_place (struct GNUNET_MessageHeader *msg, void -app_notify_ego (struct Ego *ego, struct GNUNET_SERVER_Client *client) +app_notify_place_end (struct GNUNET_SERVICE_Client *client) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "%p Sending end of place list notification to client\n", + client); + + struct GNUNET_MessageHeader msg; + msg.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_APP_PLACE_END); + msg.size = htons (sizeof (msg)); + + client_send_msg (client, &msg); +} + + +void +app_notify_ego (struct Ego *ego, struct GNUNET_SERVICE_Client *client) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Sending ego notification to client: %s\n", @@ -1614,13 +2032,28 @@ app_notify_ego (struct Ego *ego, struct GNUNET_SERVER_Client *client) emsg->header.size = htons (sizeof (*emsg) + name_size); GNUNET_CRYPTO_ecdsa_key_get_public (&ego->key, &emsg->ego_pub_key); - memcpy (&emsg[1], ego->name, name_size); + GNUNET_memcpy (&emsg[1], ego->name, name_size); client_send_msg (client, &emsg->header); GNUNET_free (emsg); } +void +app_notify_ego_end (struct GNUNET_SERVICE_Client *client) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "%p Sending end of ego list notification to client\n", + client); + + struct GNUNET_MessageHeader msg; + msg.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_APP_EGO_END); + msg.size = htons (sizeof (msg)); + + client_send_msg (client, &msg); +} + + int app_place_entry_notify (void *cls, const struct GNUNET_HashCode *key, void *value) { @@ -1640,15 +2073,23 @@ ego_entry (void *cls, const struct GNUNET_HashCode *key, void *value) } +static int +check_client_app_connect (void *cls, + const struct AppConnectRequest *creq) +{ + return GNUNET_OK; +} + + /** * Handle application connection. */ static void -client_recv_app_connect (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *msg) +handle_client_app_connect (void *cls, + const struct AppConnectRequest *creq) { - const struct AppConnectRequest *creq - = (const struct AppConnectRequest *) msg; + struct Client *c = cls; + struct GNUNET_SERVICE_Client *client = c->client; uint8_t app_id_size = ntohs (creq->header.size) - sizeof (*creq); const char *app_id = NULL; @@ -1657,7 +2098,7 @@ client_recv_app_connect (void *cls, struct GNUNET_SERVER_Client *client, if (0 == offset || offset != app_id_size) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } @@ -1665,11 +2106,13 @@ client_recv_app_connect (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_CRYPTO_hash (app_id, app_id_size, &app_id_hash); GNUNET_CONTAINER_multihashmap_iterate (egos, ego_entry, client); + app_notify_ego_end (client); struct GNUNET_CONTAINER_MultiHashMap * app_places = GNUNET_CONTAINER_multihashmap_get (apps_places, &app_id_hash); if (NULL != app_places) GNUNET_CONTAINER_multihashmap_iterate (app_places, app_place_entry_notify, client); + app_notify_place_end (client); struct ClientListItem *cli = GNUNET_new (struct ClientListItem); cli->client = client; @@ -1685,12 +2128,10 @@ client_recv_app_connect (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Application %s connected.\n", app, app_id); - struct Client *ctx = GNUNET_new (struct Client); - ctx->app_id = GNUNET_malloc (app_id_size); - memcpy (ctx->app_id, app_id, app_id_size); + c->app_id = GNUNET_malloc (app_id_size); + GNUNET_memcpy (c->app_id, app_id, app_id_size); - GNUNET_SERVER_client_set_user_context (client, ctx); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); } @@ -1698,42 +2139,45 @@ client_recv_app_connect (void *cls, struct GNUNET_SERVER_Client *client, * Handle application detach request. */ static void -client_recv_app_detach (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *msg) +handle_client_app_detach (void *cls, + const struct AppDetachRequest *req) { - struct Client * - ctx = GNUNET_SERVER_client_get_user_context (client, struct Client); - GNUNET_assert (NULL != ctx); + struct Client *c = cls; + struct GNUNET_SERVICE_Client *client = c->client; - const struct AppDetachRequest *req - = (const struct AppDetachRequest *) msg; - - int ret = app_place_remove (ctx->app_id, &req->place_pub_key); + int ret = app_place_remove (c->app_id, &req->ego_pub_key, &req->place_pub_key); client_send_result (client, req->op_id, ret, NULL, 0); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); } int app_places_entry_remove (void *cls, const struct GNUNET_HashCode *key, void *value) { - app_place_remove (value, cls); + struct Place *plc = cls; + const char *app_id = value; + app_place_remove (app_id, &plc->ego_pub_key, &plc->pub_key); return GNUNET_YES; } /** - * Handle application detach request. + * Handle application leave request. */ static void -client_recv_place_leave (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *msg) +handle_client_place_leave (void *cls, + 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; + struct Client *c = cls; + struct GNUNET_SERVICE_Client *client = c->client; + struct Place *plc = c->place; + if (NULL == plc) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (client); + return; + } /* FIXME: remove all app subscriptions and leave this place */ @@ -1741,7 +2185,7 @@ client_recv_place_leave (void *cls, struct GNUNET_SERVER_Client *client, place_apps = GNUNET_CONTAINER_multihashmap_get (places_apps, &plc->pub_key_hash); if (NULL != place_apps) { - GNUNET_CONTAINER_multihashmap_iterate (place_apps, app_places_entry_remove, &plc->pub_key); + GNUNET_CONTAINER_multihashmap_iterate (place_apps, app_places_entry_remove, plc); } /* FIXME: disconnect from the network, but keep local connection for history access */ @@ -1751,7 +2195,7 @@ client_recv_place_leave (void *cls, struct GNUNET_SERVER_Client *client, while (NULL != cli) { GNUNET_CONTAINER_DLL_remove (plc->clients_head, plc->clients_tail, cli); - GNUNET_SERVER_client_disconnect (cli->client); + GNUNET_SERVICE_client_drop (cli->client); next = cli->next; GNUNET_free (cli); cli = next; @@ -1794,44 +2238,55 @@ psyc_send_join_decision (void *cls, const struct GNUNET_HashCode *pub_key_hash, } +static int +check_client_join_decision (void *cls, + const struct GNUNET_PSYC_JoinDecisionMessage *dcsn) +{ + return GNUNET_OK; +} + + /** * Handle an entry decision from a host client. */ static void -client_recv_join_decision (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *msg) +handle_client_join_decision (void *cls, + const struct GNUNET_PSYC_JoinDecisionMessage *dcsn) { - 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 Client *c = cls; + struct GNUNET_SERVICE_Client *client = c->client; + struct Place *plc = c->place; + if (NULL == plc || GNUNET_YES != plc->is_host) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (client); + return; + } + struct Host *hst = plc->host; - 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)) + = (sizeof (*dcsn) + sizeof (*jcls.msg) <= ntohs (dcsn->header.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); + struct GNUNET_HashCode slave_pub_hash; + GNUNET_CRYPTO_hash (&dcsn->slave_pub_key, sizeof (dcsn->slave_pub_key), + &slave_pub_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)); + hst, GNUNET_h2s (&slave_pub_hash)); - GNUNET_CONTAINER_multihashmap_get_multiple (hst->join_reqs, &slave_key_hash, + GNUNET_CONTAINER_multihashmap_get_multiple (hst->join_reqs, &slave_pub_hash, &psyc_send_join_decision, &jcls); - GNUNET_CONTAINER_multihashmap_remove_all (hst->join_reqs, &slave_key_hash); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_CONTAINER_multihashmap_remove_all (hst->join_reqs, &slave_pub_hash); + + GNUNET_SERVICE_client_continue (client); } @@ -1843,7 +2298,7 @@ client_recv_join_decision (void *cls, struct GNUNET_SERVER_Client *client, * @param plc The place struct for the client. */ static void -send_message_ack (struct Place *plc, struct GNUNET_SERVER_Client *client) +send_message_ack (struct Place *plc, struct GNUNET_SERVICE_Client *client) { struct GNUNET_MessageHeader res; res.size = htons (sizeof (res)); @@ -1955,7 +2410,7 @@ psyc_transmit_notify_data (void *cls, uint16_t *data_size, void *data) plc, pdata_size); *data_size = pdata_size; - memcpy (data, &pmsg[1], *data_size); + GNUNET_memcpy (data, &pmsg[1], *data_size); ret = GNUNET_NO; break; @@ -1981,8 +2436,8 @@ psyc_transmit_notify_data (void *cls, uint16_t *data_size, void *data) *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); + GNUNET_SERVICE_client_drop (tmit_frag->client); + GNUNET_SCHEDULER_add_now (&cleanup_place, plc); return ret; } else @@ -2090,7 +2545,7 @@ psyc_transmit_notify_mod (void *cls, uint16_t *data_size, void *data, *full_value_size = ntohl (pmod->value_size); *oper = pmod->oper; *data_size = mod_size; - memcpy (data, &pmod[1], mod_size); + GNUNET_memcpy (data, &pmod[1], mod_size); ret = GNUNET_NO; break; } @@ -2116,7 +2571,7 @@ psyc_transmit_notify_mod (void *cls, uint16_t *data_size, void *data, "%p psyc_transmit_notify_mod: sending %u bytes.\n", plc, mod_size); *data_size = mod_size; - memcpy (data, &pmsg[1], *data_size); + GNUNET_memcpy (data, &pmsg[1], *data_size); ret = GNUNET_NO; break; } @@ -2141,8 +2596,8 @@ psyc_transmit_notify_mod (void *cls, uint16_t *data_size, void *data, 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); + GNUNET_SERVICE_client_drop (tmit_frag->client); + GNUNET_SCHEDULER_add_now (&cleanup_place, plc); } else { @@ -2231,18 +2686,15 @@ guest_transmit_notify_mod (void *cls, uint16_t *data_size, void *data, /** * 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. + * @param plc + * Place * * @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) +static struct GNUNET_PSYC_MessageMethod * +psyc_transmit_queue_next_method (struct Place *plc) { struct MessageTransmitQueue *tmit_msg = plc->tmit_msgs_head; if (NULL == tmit_msg) @@ -2263,25 +2715,28 @@ psyc_transmit_queue_next_method (struct Place *plc, "%p psyc_transmit_queue_next_method: unexpected message part of type %u.\n", plc, NULL != pmsg ? ntohs (pmsg->type) : 0); GNUNET_break (0); - return GNUNET_SYSERR; + return NULL; } uint16_t psize = ntohs (pmsg->size); - *pmeth = (struct GNUNET_PSYC_MessageMethod *) pmsg; - if (psize < sizeof (**pmeth) + 1 || '\0' != *((char *) *pmeth + psize - 1)) + struct GNUNET_PSYC_MessageMethod * + pmeth = (struct GNUNET_PSYC_MessageMethod *) GNUNET_copy_message (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)); + plc); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "%u <= %u || NUL != %u\n", - sizeof (**pmeth), psize, *((char *) *pmeth + psize - 1)); + "%zu <= %u || NUL != %u\n", + sizeof (*pmeth), psize, *((char *) pmeth + psize - 1)); GNUNET_break (0); - return GNUNET_SYSERR; + GNUNET_free (pmeth); + return NULL; } psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag); - return GNUNET_OK; + return pmeth; } @@ -2291,19 +2746,24 @@ psyc_transmit_queue_next_method (struct Place *plc, static int psyc_master_transmit_message (struct Host *hst) { + struct Place *plc = &hst->place; 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; + struct GNUNET_PSYC_MessageMethod * + pmeth = psyc_transmit_queue_next_method (plc); + if (NULL == pmeth) + return GNUNET_SYSERR; - hst->tmit_handle - = GNUNET_PSYC_master_transmit (hst->master, (const char *) &pmeth[1], - &host_transmit_notify_mod, - &host_transmit_notify_data, hst, - pmeth->flags); + hst->tmit_handle = (void *) &hst->tmit_handle; + struct GNUNET_PSYC_MasterTransmitHandle * + tmit_handle = GNUNET_PSYC_master_transmit (hst->master, (const char *) &pmeth[1], + &host_transmit_notify_mod, + &host_transmit_notify_data, hst, + pmeth->flags); + if (NULL != hst->tmit_handle) + hst->tmit_handle = tmit_handle; + GNUNET_free (pmeth); } else { @@ -2319,18 +2779,24 @@ psyc_master_transmit_message (struct Host *hst) static int psyc_slave_transmit_message (struct Guest *gst) { + struct Place *plc = &gst->place; + 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; + struct GNUNET_PSYC_MessageMethod * + pmeth = psyc_transmit_queue_next_method (plc); + if (NULL == pmeth) + return GNUNET_SYSERR; - gst->tmit_handle - = GNUNET_PSYC_slave_transmit (gst->slave, (const char *) &pmeth[1], - &guest_transmit_notify_mod, - &guest_transmit_notify_data, gst, - pmeth->flags); + gst->tmit_handle = (void *) &gst->tmit_handle; + struct GNUNET_PSYC_SlaveTransmitHandle * + tmit_handle = GNUNET_PSYC_slave_transmit (gst->slave, (const char *) &pmeth[1], + &guest_transmit_notify_mod, + &guest_transmit_notify_data, gst, + pmeth->flags); + if (NULL != gst->tmit_handle) + gst->tmit_handle = tmit_handle; + GNUNET_free (pmeth); } else { @@ -2365,7 +2831,7 @@ psyc_transmit_message (struct Place *plc) */ static struct MessageTransmitQueue * psyc_transmit_queue_message (struct Place *plc, - struct GNUNET_SERVER_Client *client, + struct GNUNET_SERVICE_Client *client, size_t data_size, const void *data, uint16_t first_ptype, uint16_t last_ptype, @@ -2383,7 +2849,7 @@ psyc_transmit_queue_message (struct Place *plc, struct FragmentTransmitQueue * tmit_frag = GNUNET_malloc (sizeof (*tmit_frag) + data_size); - memcpy (&tmit_frag[1], data, data_size); + GNUNET_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; @@ -2401,7 +2867,7 @@ psyc_transmit_queue_message (struct Place *plc, * @param client Client the message originates from. */ static void -psyc_transmit_cancel (struct Place *plc, struct GNUNET_SERVER_Client *client) +psyc_transmit_cancel (struct Place *plc, struct GNUNET_SERVICE_Client *client) { uint16_t type = GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL; @@ -2416,17 +2882,31 @@ psyc_transmit_cancel (struct Place *plc, struct GNUNET_SERVER_Client *client) } +static int +check_client_psyc_message (void *cls, + const struct GNUNET_MessageHeader *msg) +{ + return GNUNET_OK; +} + + /** * Handle an incoming message from a client, to be transmitted to the place. */ static void -client_recv_psyc_message (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *msg) +handle_client_psyc_message (void *cls, + 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; + struct Client *c = cls; + struct GNUNET_SERVICE_Client *client = c->client; + struct Place *plc = c->place; + if (NULL == plc) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (client); + return; + } + int ret = GNUNET_SYSERR; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -2438,7 +2918,7 @@ client_recv_psyc_message (void *cls, struct GNUNET_SERVER_Client *client, 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); + GNUNET_SERVICE_client_drop (client); return; } @@ -2452,7 +2932,7 @@ client_recv_psyc_message (void *cls, struct GNUNET_SERVER_Client *client, plc, psize); GNUNET_break (0); psyc_transmit_cancel (plc, client); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } @@ -2465,20 +2945,20 @@ client_recv_psyc_message (void *cls, struct GNUNET_SERVER_Client *client, "%p Received invalid message part from client.\n", plc); GNUNET_break (0); psyc_transmit_cancel (plc, client); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); 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 + c->tmit_msg = psyc_transmit_queue_message (plc, client, psize, &msg[1], - first_ptype, last_ptype, ctx->tmit_msg); - if (NULL != ctx->tmit_msg) + first_ptype, last_ptype, c->tmit_msg); + if (NULL != c->tmit_msg) { if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= last_ptype) - ctx->tmit_msg = NULL; + c->tmit_msg = NULL; ret = psyc_transmit_message (plc); } @@ -2490,7 +2970,11 @@ client_recv_psyc_message (void *cls, struct GNUNET_SERVER_Client *client, psyc_transmit_cancel (plc, client); ret = GNUNET_SYSERR; } - GNUNET_SERVER_receive_done (client, ret); + + if (GNUNET_OK == ret) + GNUNET_SERVICE_client_continue (client); + else + GNUNET_SERVICE_client_drop (client); } @@ -2498,15 +2982,15 @@ client_recv_psyc_message (void *cls, struct GNUNET_SERVER_Client *client, * A historic message arrived from PSYC. */ static void -psyc_recv_history_message (void *cls, uint64_t message_id, uint32_t flags, - const struct GNUNET_PSYC_MessageHeader *msg) +psyc_recv_history_message (void *cls, const struct GNUNET_PSYC_MessageHeader *msg) { struct OperationClosure *opcls = cls; - struct Place *plc = opcls->plc; + struct Client *c = opcls->client; + struct Place *plc = c->place; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Received historic message #%" PRId64 " (flags: %x)\n", - plc, message_id, flags); + plc, GNUNET_ntohll (msg->message_id), ntohl (msg->flags)); uint16_t size = ntohs (msg->header.size); @@ -2517,10 +3001,12 @@ psyc_recv_history_message (void *cls, uint64_t message_id, uint32_t flags, res->op_id = opcls->op_id; res->result_code = GNUNET_htonll (GNUNET_OK); - memcpy (&res[1], msg, size); + GNUNET_memcpy (&res[1], msg, size); /** @todo FIXME: send only to requesting client */ place_send_msg (plc, &res->header); + + GNUNET_free (res); } @@ -2532,13 +3018,25 @@ psyc_recv_history_result (void *cls, int64_t result, const void *err_msg, uint16_t err_msg_size) { struct OperationClosure *opcls = cls; + struct Client *c = opcls->client; + struct Place *plc = c->place; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p History replay #%" PRIu64 ": " "PSYCstore returned %" PRId64 " (%.*s)\n", - opcls->plc, GNUNET_ntohll (opcls->op_id), result, err_msg_size, err_msg); + plc, GNUNET_ntohll (opcls->op_id), result, + err_msg_size, (const char *) err_msg); // FIXME: place might have been destroyed - client_send_result (opcls->client, opcls->op_id, result, err_msg, err_msg_size); + client_send_result (c->client, opcls->op_id, result, err_msg, err_msg_size); +} + + +static int +check_client_history_replay (void *cls, + const struct GNUNET_PSYC_HistoryRequestMessage *req) +{ + return GNUNET_OK; } @@ -2546,17 +3044,20 @@ psyc_recv_history_result (void *cls, int64_t result, * Client requests channel history. */ static void -client_recv_history_replay (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *msg) +handle_client_history_replay (void *cls, + const struct GNUNET_PSYC_HistoryRequestMessage *req) { - struct Client * - ctx = GNUNET_SERVER_client_get_user_context (client, struct Client); - GNUNET_assert (NULL != ctx); - struct Place *plc = ctx->plc; + struct Client *c = cls; + struct GNUNET_SERVICE_Client *client = c->client; + struct Place *plc = c->place; + if (NULL == plc) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (client); + return; + } - const struct GNUNET_PSYC_HistoryRequestMessage * - req = (const struct GNUNET_PSYC_HistoryRequestMessage *) msg; - uint16_t size = ntohs (msg->size); + uint16_t size = ntohs (req->header.size); const char *method_prefix = (const char *) &req[1]; if (size < sizeof (*req) + 1 @@ -2564,16 +3065,15 @@ client_recv_history_replay (void *cls, struct GNUNET_SERVER_Client *client, { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%p History replay #%" PRIu64 ": " - "invalid method prefix. size: %u < %u?\n", + "invalid method prefix. size: %u < %zu?\n", plc, GNUNET_ntohll (req->op_id), size, sizeof (*req) + 1); GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } struct OperationClosure *opcls = GNUNET_malloc (sizeof (*opcls)); - opcls->client = client; - opcls->plc = plc; + opcls->client = c; opcls->op_id = req->op_id; opcls->flags = ntohl (req->flags); @@ -2582,16 +3082,16 @@ client_recv_history_replay (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_ntohll (req->start_message_id), GNUNET_ntohll (req->end_message_id), method_prefix, opcls->flags, - &psyc_recv_history_message, NULL, - &psyc_recv_history_result, opcls); + psyc_recv_history_message, NULL, + psyc_recv_history_result, opcls); else GNUNET_PSYC_channel_history_replay_latest (plc->channel, GNUNET_ntohll (req->message_limit), method_prefix, opcls->flags, - &psyc_recv_history_message, NULL, - &psyc_recv_history_result, opcls); + psyc_recv_history_message, NULL, + psyc_recv_history_result, opcls); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); } @@ -2607,7 +3107,8 @@ psyc_recv_state_var (void *cls, uint32_t full_value_size) { struct OperationClosure *opcls = cls; - struct Place *plc = opcls->plc; + struct Client *c = opcls->client; + struct Place *plc = c->place; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Received state variable %s from PSYC\n", @@ -2622,10 +3123,12 @@ psyc_recv_state_var (void *cls, res->op_id = opcls->op_id; res->result_code = GNUNET_htonll (GNUNET_OK); - memcpy (&res[1], mod, size); + GNUNET_memcpy (&res[1], mod, size); /** @todo FIXME: send only to requesting client */ place_send_msg (plc, &res->header); + + GNUNET_free (res); } @@ -2637,13 +3140,25 @@ psyc_recv_state_result (void *cls, int64_t result, const void *err_msg, uint16_t err_msg_size) { struct OperationClosure *opcls = cls; + struct Client *c = opcls->client; + struct Place *plc = c->place; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p State get #%" PRIu64 ": " "PSYCstore returned %" PRId64 " (%.*s)\n", - opcls->plc, GNUNET_ntohll (opcls->op_id), result, err_msg_size, err_msg); + plc, GNUNET_ntohll (opcls->op_id), result, + err_msg_size, (const char *) err_msg); // FIXME: place might have been destroyed - client_send_result (opcls->client, opcls->op_id, result, err_msg, err_msg_size); + client_send_result (c->client, opcls->op_id, result, err_msg, err_msg_size); +} + + +static int +check_client_state_get (void *cls, + const struct GNUNET_PSYC_StateRequestMessage *req) +{ + return GNUNET_OK; } @@ -2651,17 +3166,20 @@ psyc_recv_state_result (void *cls, int64_t result, * Client requests channel history. */ static void -client_recv_state_get (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *msg) +handle_client_state_get (void *cls, + const struct GNUNET_PSYC_StateRequestMessage *req) { - struct Client * - ctx = GNUNET_SERVER_client_get_user_context (client, struct Client); - GNUNET_assert (NULL != ctx); - struct Place *plc = ctx->plc; + struct Client *c = cls; + struct GNUNET_SERVICE_Client *client = c->client; + struct Place *plc = c->place; + if (NULL == plc) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (client); + return; + } - const struct GNUNET_PSYC_StateRequestMessage * - req = (const struct GNUNET_PSYC_StateRequestMessage *) msg; - uint16_t size = ntohs (msg->size); + uint16_t size = ntohs (req->header.size); const char *name = (const char *) &req[1]; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -2673,19 +3191,18 @@ client_recv_state_get (void *cls, struct GNUNET_SERVER_Client *client, { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%p State get #%" PRIu64 ": " - "invalid name. size: %u < %u?\n", + "invalid name. size: %u < %zu?\n", plc, GNUNET_ntohll (req->op_id), size, sizeof (*req) + 1); GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } struct OperationClosure *opcls = GNUNET_malloc (sizeof (*opcls)); - opcls->client = client; - opcls->plc = plc; + opcls->client = c; opcls->op_id = req->op_id; - switch (ntohs (msg->type)) + switch (ntohs (req->header.type)) { case GNUNET_MESSAGE_TYPE_PSYC_STATE_GET: GNUNET_PSYC_channel_state_get (plc->channel, name, @@ -2703,18 +3220,33 @@ client_recv_state_get (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_assert (0); } - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); } +#define check_client_state_get_prefix check_client_state_get +#define handle_client_state_get_prefix handle_client_state_get + + static void namestore_recv_records_store_result (void *cls, int32_t result, const char *err_msg) { - struct OperationClosure *ocls = cls; - client_send_result (ocls->client, ocls->op_id, result, err_msg, + struct OperationClosure *opcls = cls; + struct Client *c = opcls->client; + + // FIXME: client might have been disconnected + client_send_result (c->client, opcls->op_id, result, err_msg, (NULL != err_msg) ? strlen (err_msg) : 0); - GNUNET_free (ocls); + GNUNET_free (opcls); +} + + +static int +check_client_zone_add_place (void *cls, + const struct ZoneAddPlaceRequest *preq) +{ + return GNUNET_OK; } @@ -2722,11 +3254,11 @@ namestore_recv_records_store_result (void *cls, int32_t result, * Handle request to add PLACE record to GNS zone. */ static void -client_recv_zone_add_place (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *msg) +handle_client_zone_add_place (void *cls, + const struct ZoneAddPlaceRequest *preq) { - const struct ZoneAddPlaceRequest *preq - = (const struct ZoneAddPlaceRequest *) msg; + struct Client *c = cls; + struct GNUNET_SERVICE_Client *client = c->client; uint16_t remaining = ntohs (preq->header.size) - sizeof (*preq); const char *p = (const char *) &preq[1]; @@ -2743,7 +3275,7 @@ client_recv_zone_add_place (void *cls, struct GNUNET_SERVER_Client *client, { GNUNET_break (0); client_send_result (client, preq->op_id, GNUNET_SYSERR, NULL, 0); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_drop (client); return; } @@ -2757,7 +3289,7 @@ client_recv_zone_add_place (void *cls, struct GNUNET_SERVER_Client *client, rec->place_pub_key = preq->place_pub_key; rec->origin = this_peer; rec->relay_count = preq->relay_count; - memcpy (&rec[1], relays, relay_size); + GNUNET_memcpy (&rec[1], relays, relay_size); rd.data = rec; rd.data_size = sizeof (*rec) + relay_size; @@ -2771,14 +3303,23 @@ client_recv_zone_add_place (void *cls, struct GNUNET_SERVER_Client *client, } else { - struct OperationClosure *ocls = GNUNET_malloc (sizeof (*ocls)); - ocls->client = client; - ocls->op_id = preq->op_id; + struct OperationClosure *opcls = GNUNET_malloc (sizeof (*opcls)); + opcls->client = c; + opcls->op_id = preq->op_id; GNUNET_NAMESTORE_records_store (namestore, &ego->key, name, 1, &rd, - namestore_recv_records_store_result, ocls); + namestore_recv_records_store_result, opcls); + /** @todo refresh stored records later */ } - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); +} + + +static int +check_client_zone_add_nym (void *cls, + const struct ZoneAddNymRequest *nreq) +{ + return GNUNET_OK; } @@ -2786,11 +3327,11 @@ client_recv_zone_add_place (void *cls, struct GNUNET_SERVER_Client *client, * Handle request to add PLACE record to GNS zone. */ static void -client_recv_zone_add_nym (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *msg) +handle_client_zone_add_nym (void *cls, + const struct ZoneAddNymRequest *nreq) { - const struct ZoneAddNymRequest *nreq - = (const struct ZoneAddNymRequest *) msg; + struct Client *c = cls; + struct GNUNET_SERVICE_Client *client = c->client; uint16_t name_size = ntohs (nreq->header.size) - sizeof (*nreq); const char *name = NULL; @@ -2800,7 +3341,7 @@ client_recv_zone_add_nym (void *cls, struct GNUNET_SERVER_Client *client, { GNUNET_break (0); client_send_result (client, nreq->op_id, GNUNET_SYSERR, NULL, 0); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); return; } @@ -2820,61 +3361,18 @@ client_recv_zone_add_nym (void *cls, struct GNUNET_SERVER_Client *client, } else { - struct OperationClosure *ocls = GNUNET_malloc (sizeof (*ocls)); - ocls->client = client; - ocls->op_id = nreq->op_id; + struct OperationClosure *opcls = GNUNET_malloc (sizeof (*opcls)); + opcls->client = c; + opcls->op_id = nreq->op_id; GNUNET_NAMESTORE_records_store (namestore, &ego->key, - name, 1, &rd, - namestore_recv_records_store_result, ocls); + name, 1, &rd, + namestore_recv_records_store_result, opcls); + /** @todo refresh stored records later */ } - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_continue (client); } -static const struct GNUNET_SERVER_MessageHandler handlers[] = { - { &client_recv_host_enter, NULL, - GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER, 0 }, - - { &client_recv_guest_enter, NULL, - GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER, 0 }, - - { &client_recv_guest_enter_by_name, NULL, - GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_BY_NAME, 0 }, - - { &client_recv_join_decision, NULL, - GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION, 0 }, - - { &client_recv_psyc_message, NULL, - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE, 0 }, - - { &client_recv_history_replay, NULL, - GNUNET_MESSAGE_TYPE_PSYC_HISTORY_REPLAY, 0 }, - - { &client_recv_state_get, NULL, - GNUNET_MESSAGE_TYPE_PSYC_STATE_GET, 0 }, - - { &client_recv_state_get, NULL, - GNUNET_MESSAGE_TYPE_PSYC_STATE_GET_PREFIX, 0 }, - - { &client_recv_zone_add_place, NULL, - GNUNET_MESSAGE_TYPE_SOCIAL_ZONE_ADD_PLACE, 0 }, - - { &client_recv_zone_add_nym, NULL, - GNUNET_MESSAGE_TYPE_SOCIAL_ZONE_ADD_NYM, 0 }, - - { &client_recv_app_connect, NULL, - GNUNET_MESSAGE_TYPE_SOCIAL_APP_CONNECT, 0 }, - - { &client_recv_app_detach, NULL, - GNUNET_MESSAGE_TYPE_SOCIAL_APP_DETACH, 0 }, - - { &client_recv_place_leave, NULL, - GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE, 0 }, - - { NULL, NULL, 0, 0 } -}; - - const char * path_basename (const char *path) { @@ -2892,110 +3390,109 @@ path_basename (const char *path) struct PlaceLoadClosure { const char *app_id; - const char *ego_pub_hash_str; + const char *ego_pub_str; }; /** Load a place file */ int -file_place_load (void *cls, const char *filename) +file_place_load (void *cls, const char *place_filename) { - char *app_id = cls; + struct PlaceLoadClosure *plcls = cls; + + const char *place_pub_str = path_basename (place_filename); + if (NULL == place_pub_str) + { + GNUNET_break (0); + return GNUNET_OK; + } + + char *filename = NULL; + GNUNET_asprintf (&filename, "%s%c" "%s%c" "%s%c" "%s", + dir_social, DIR_SEPARATOR, + "places", DIR_SEPARATOR, + plcls->ego_pub_str, DIR_SEPARATOR, + place_pub_str); + uint64_t file_size = 0; if (GNUNET_OK != GNUNET_DISK_file_size (filename, &file_size, GNUNET_YES, GNUNET_YES) - || file_size < sizeof (struct HostEnterRequest)) + || file_size < sizeof (struct PlaceEnterRequest)) + { + GNUNET_free (filename); return GNUNET_OK; + } struct PlaceEnterRequest *ereq = GNUNET_malloc (file_size); ssize_t read_size = GNUNET_DISK_fn_read (filename, ereq, file_size); + GNUNET_free (filename); if (read_size < 0 || read_size < sizeof (*ereq)) + { + GNUNET_free (ereq); return GNUNET_OK; + } uint16_t ereq_size = ntohs (ereq->header.size); if (read_size != ereq_size) + { + GNUNET_free (ereq); return GNUNET_OK; + } switch (ntohs (ereq->header.type)) { case GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER: if (ereq_size < sizeof (struct HostEnterRequest)) + { + GNUNET_free (ereq); return GNUNET_OK; + } struct HostEnterRequest *hreq = (struct HostEnterRequest *) ereq; host_enter (hreq, NULL); break; case GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER: if (ereq_size < sizeof (struct GuestEnterRequest)) + { + GNUNET_free (ereq); return GNUNET_OK; + } struct GuestEnterRequest *greq = (struct GuestEnterRequest *) ereq; guest_enter (greq, NULL); break; default: + GNUNET_free (ereq); return GNUNET_OK; } - app_place_add (app_id, ereq); - return GNUNET_OK; -} - - -/** Load an ego place file */ -int -file_ego_place_load (void *cls, const char *place_filename) -{ - struct PlaceLoadClosure *plcls = cls; - - const char *place_pub_hash_str = path_basename (place_filename); - if (NULL == place_pub_hash_str) - { - GNUNET_break (0); - return GNUNET_OK; - } - - char *filename = NULL; - GNUNET_asprintf (&filename, "%s%c" "%s%c" "%s%c" "%s", - dir_social, DIR_SEPARATOR, - "places", DIR_SEPARATOR, - plcls->ego_pub_hash_str, DIR_SEPARATOR, - place_pub_hash_str); - - struct PlaceEnterRequest ereq[GNUNET_SERVER_MAX_MESSAGE_SIZE]; - - int read_size = GNUNET_DISK_fn_read (filename, &ereq, - GNUNET_SERVER_MAX_MESSAGE_SIZE); - GNUNET_free (filename); - - if (read_size < (ssize_t) sizeof (ereq)) - return GNUNET_OK; - app_place_add (plcls->app_id, ereq); + GNUNET_free (ereq); return GNUNET_OK; } /** - * Read @e place_pub_hash_str entries in @a dir_ego + * Read @e place_pub_str entries in @a dir_ego * * @param dir_ego * Data directory of an application ego. - * $GNUNET_DATA_HOME/social/apps/$app_id/$ego_pub_hash_str/ + * $GNUNET_DATA_HOME/social/apps/$app_id/$ego_pub_str/ */ int scan_app_ego_dir (void *cls, const char *dir_ego) { struct PlaceLoadClosure *plcls = cls; - plcls->ego_pub_hash_str = path_basename (dir_ego); + plcls->ego_pub_str = path_basename (dir_ego); - if (NULL != plcls->ego_pub_hash_str) - GNUNET_DISK_directory_scan (dir_ego, file_ego_place_load, plcls); + if (NULL != plcls->ego_pub_str) + GNUNET_DISK_directory_scan (dir_ego, file_place_load, plcls); return GNUNET_OK; } /** - * Read @e ego_pub_hash_str entries in @a dir_app + * Read @e ego_pub_str entries in @a dir_app * * @param dir_app * Data directory of an application. @@ -3050,21 +3547,13 @@ identity_recv_ego (void *cls, struct GNUNET_IDENTITY_Ego *id_ego, ego->key = *(GNUNET_IDENTITY_ego_get_private_key (id_ego)); size_t name_size = strlen (name) + 1; ego->name = GNUNET_malloc (name_size); - memcpy (ego->name, name, name_size); + GNUNET_memcpy (ego->name, name, name_size); GNUNET_CONTAINER_multihashmap_put (egos, &ego_pub_hash, ego, GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); } -} - -/** - * Connected to core service. - */ -static void -core_connected (void *cls, const struct GNUNET_PeerIdentity *my_identity) -{ - this_peer = *my_identity; + // FIXME: notify clients about changed ego } @@ -3076,10 +3565,13 @@ core_connected (void *cls, const struct GNUNET_PeerIdentity *my_identity) * @param c Configuration to use. */ static void -run (void *cls, struct GNUNET_SERVER_Handle *server, - const struct GNUNET_CONFIGURATION_Handle *c) +run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *c, + struct GNUNET_SERVICE_Handle *svc) { cfg = c; + service = svc; + GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer); hosts = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); guests = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); @@ -3091,8 +3583,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, apps_places = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO); places_apps = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO); - core = GNUNET_CORE_connect (cfg, NULL, core_connected, NULL, NULL, - NULL, GNUNET_NO, NULL, GNUNET_NO, NULL); id = GNUNET_IDENTITY_connect (cfg, &identity_recv_ego, NULL); gns = GNUNET_GNS_connect (cfg); namestore = GNUNET_NAMESTORE_connect (cfg); @@ -3114,28 +3604,79 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, GNUNET_DISK_directory_scan (dir_apps, scan_app_dir, NULL); - nc = GNUNET_SERVER_notification_context_create (server, 1); - GNUNET_SERVER_add_handlers (server, handlers); - GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL); - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, - &shutdown_task, NULL); -} - - -/** - * The main function for the service. - * - * @param argc number of arguments from the command line - * @param argv command line arguments - * @return 0 ok, 1 on error - */ -int -main (int argc, char *const *argv) -{ - return (GNUNET_OK == - GNUNET_SERVICE_run (argc, argv, "social", - GNUNET_SERVICE_OPTION_NONE, - &run, NULL)) ? 0 : 1; -} + GNUNET_SCHEDULER_add_shutdown (shutdown_task, NULL); +} + + +/** + * Define "main" method using service macro. + */ +GNUNET_SERVICE_MAIN +("social", + GNUNET_SERVICE_OPTION_NONE, + run, + client_notify_connect, + client_notify_disconnect, + NULL, + GNUNET_MQ_hd_var_size (client_host_enter, + GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER, + struct HostEnterRequest, + NULL), + GNUNET_MQ_hd_var_size (client_guest_enter, + GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER, + struct GuestEnterRequest, + NULL), + GNUNET_MQ_hd_var_size (client_guest_enter_by_name, + GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_BY_NAME, + struct GuestEnterByNameRequest, + NULL), + GNUNET_MQ_hd_var_size (client_join_decision, + GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION, + struct GNUNET_PSYC_JoinDecisionMessage, + NULL), + GNUNET_MQ_hd_var_size (client_psyc_message, + GNUNET_MESSAGE_TYPE_PSYC_MESSAGE, + struct GNUNET_MessageHeader, + NULL), + GNUNET_MQ_hd_var_size (client_history_replay, + GNUNET_MESSAGE_TYPE_PSYC_HISTORY_REPLAY, + struct GNUNET_PSYC_HistoryRequestMessage, + NULL), + GNUNET_MQ_hd_var_size (client_state_get, + GNUNET_MESSAGE_TYPE_PSYC_STATE_GET, + struct GNUNET_PSYC_StateRequestMessage, + NULL), + GNUNET_MQ_hd_var_size (client_state_get_prefix, + GNUNET_MESSAGE_TYPE_PSYC_STATE_GET_PREFIX, + struct GNUNET_PSYC_StateRequestMessage, + NULL), + GNUNET_MQ_hd_var_size (client_zone_add_place, + GNUNET_MESSAGE_TYPE_SOCIAL_ZONE_ADD_PLACE, + struct ZoneAddPlaceRequest, + NULL), + GNUNET_MQ_hd_var_size (client_zone_add_nym, + GNUNET_MESSAGE_TYPE_SOCIAL_ZONE_ADD_NYM, + struct ZoneAddNymRequest, + NULL), + GNUNET_MQ_hd_var_size (client_app_connect, + GNUNET_MESSAGE_TYPE_SOCIAL_APP_CONNECT, + struct AppConnectRequest, + NULL), + GNUNET_MQ_hd_fixed_size (client_app_detach, + GNUNET_MESSAGE_TYPE_SOCIAL_APP_DETACH, + struct AppDetachRequest, + NULL), + GNUNET_MQ_hd_fixed_size (client_place_leave, + GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE, + struct GNUNET_MessageHeader, + NULL), + GNUNET_MQ_hd_var_size (client_msg_proc_set, + GNUNET_MESSAGE_TYPE_SOCIAL_MSG_PROC_SET, + struct MsgProcRequest, + NULL), + GNUNET_MQ_hd_fixed_size (client_msg_proc_clear, + GNUNET_MESSAGE_TYPE_SOCIAL_MSG_PROC_CLEAR, + struct GNUNET_MessageHeader, + NULL)); /* end of gnunet-service-social.c */