From b5e08fdd9c1663e81afef784a6e3bd6b4552e23e Mon Sep 17 00:00:00 2001 From: Gabor X Toth <*@tg-x.net> Date: Tue, 8 Sep 2015 01:36:44 +0000 Subject: social: guest_enter_by_name(); zone_add_pkey(); join_msg fixes --- src/include/gnunet_psyc_util_lib.h | 9 +- src/include/gnunet_social_service.h | 63 ++++++-- src/multicast/gnunet-service-multicast.c | 2 +- src/multicast/multicast_api.c | 1 + src/psyc/gnunet-service-psyc.c | 6 +- src/psyc/psyc_api.c | 11 +- src/psycstore/gnunet-service-psycstore.c | 2 +- src/psycstore/psyc_util_lib.c | 46 ++++-- src/psycstore/psycstore_api.c | 2 +- src/social/gnunet-service-social.c | 4 +- src/social/social_api.c | 251 +++++++++++++++++++------------ src/social/test_social.c | 103 +++++++++++-- 12 files changed, 344 insertions(+), 156 deletions(-) diff --git a/src/include/gnunet_psyc_util_lib.h b/src/include/gnunet_psyc_util_lib.h index 504476573..10cfc68d9 100644 --- a/src/include/gnunet_psyc_util_lib.h +++ b/src/include/gnunet_psyc_util_lib.h @@ -79,7 +79,7 @@ GNUNET_PSYC_message_create (const char *method_name, * #GNUNET_SYSERR on parse error. */ int -GNUNET_PSYC_message_parse (const struct GNUNET_PSYC_Message *msg, +GNUNET_PSYC_message_parse (const struct GNUNET_PSYC_MessageHeader *msg, const char **method_name, struct GNUNET_ENV_Environment *env, const void **data, @@ -247,6 +247,13 @@ GNUNET_PSYC_message_header_create (const struct GNUNET_MULTICAST_MessageHeader * uint32_t flags); +/** + * Create a new PSYC message header from a PSYC message. + */ +struct GNUNET_PSYC_MessageHeader * +GNUNET_PSYC_message_header_create_from_psyc (const struct GNUNET_PSYC_Message *msg); + + #if 0 /* keep Emacsens' auto-indent happy */ { #endif diff --git a/src/include/gnunet_social_service.h b/src/include/gnunet_social_service.h index 0af48d168..edb762a1e 100644 --- a/src/include/gnunet_social_service.h +++ b/src/include/gnunet_social_service.h @@ -494,6 +494,7 @@ GNUNET_SOCIAL_nym_get_key_hash (const struct GNUNET_SOCIAL_Nym *nym); * Expiration time of the record, use 0 to remove the record. * @param password * Password used to encrypt the record. + * FIXME: not implemented yet. * @param result_cb * Function called with the result of the operation. * @param result_cls @@ -502,9 +503,9 @@ GNUNET_SOCIAL_nym_get_key_hash (const struct GNUNET_SOCIAL_Nym *nym); void GNUNET_SOCIAL_host_advertise (struct GNUNET_SOCIAL_Host *host, const char *name, - size_t peer_count, + uint32_t peer_count, const struct GNUNET_PeerIdentity *peers, - struct GNUNET_TIME_Relative expiration_time, + struct GNUNET_TIME_Absolute expiration_time, const char *password, GNUNET_NAMESTORE_ContinuationWithStatus result_cb, void *result_cls); @@ -702,27 +703,35 @@ GNUNET_SOCIAL_guest_enter (const struct GNUNET_CONFIGURATION_Handle *cfg, /** - * Request entry to a place as a guest using a GNS name. + * Request entry to a place by name as a guest. * - * @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 + * @param cfg + * Configuration to contact the social service. + * @param ego + * Identity of the guest. + * @param gns_name + * 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. - * @param data_size Number of bytes in @a data. - * @param slicer Slicer to use for processing incoming requests from guests. + * @param password + * Password to decrypt the record, or NULL for cleartext records. + * @param join_msg + * Entry request message. + * @param slicer + * Slicer to use for processing incoming requests from guests. + * @param local_enter_cb + * Called upon connection established to the social service. + * @param entry_decision_cb + * Called upon receiving entry decision. * * @return NULL on errors, otherwise handle for the guest. */ struct GNUNET_SOCIAL_Guest * GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_IDENTITY_Ego *ego, - char *gns_name, + const struct GNUNET_IDENTITY_Ego *ego, + const char *gns_name, const char *password, const struct GNUNET_PSYC_Message *join_msg, struct GNUNET_SOCIAL_Slicer *slicer, GNUNET_SOCIAL_GuestEnterCallback local_enter_cb, @@ -964,6 +973,34 @@ void GNUNET_SOCIAL_place_look_cancel (struct GNUNET_SOCIAL_LookHandle *lh); +/** + * Add public key to the GNS zone of the @e ego. + * + * @param cfg + * Configuration. + * @param ego + * Ego. + * @param name + * The name for the PKEY record to put in the zone. + * @param pub_key + * Public key to add. + * @param expiration_time + * Expiration time of the record, use 0 to remove the record. + * @param result_cb + * Function called with the result of the operation. + * @param result_cls + * Closure for @a result_cb + */ +void +GNUNET_SOCIAL_zone_add_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg, + const struct GNUNET_IDENTITY_Ego *ego, + const char *name, + const struct GNUNET_CRYPTO_EcdsaPublicKey *pub_key, + struct GNUNET_TIME_Absolute expiration_time, + GNUNET_NAMESTORE_ContinuationWithStatus result_cb, + void *result_cls); + + #if 0 /* keep Emacsens' auto-indent happy */ { #endif diff --git a/src/multicast/gnunet-service-multicast.c b/src/multicast/gnunet-service-multicast.c index a9b15cef1..fbf3c159c 100644 --- a/src/multicast/gnunet-service-multicast.c +++ b/src/multicast/gnunet-service-multicast.c @@ -807,7 +807,7 @@ client_recv_member_join (void *cls, struct GNUNET_SERVER_Client *client, else if (grp->clients_head == grp->clients_tail) { /* First client of the group, send join request. */ struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1]; - uint32_t relay_count = ntohs (msg->relay_count); + uint32_t relay_count = ntohl (msg->relay_count); uint16_t relay_size = relay_count * sizeof (*relays); struct GNUNET_MessageHeader *join_msg = NULL; uint16_t join_msg_size = 0; diff --git a/src/multicast/multicast_api.c b/src/multicast/multicast_api.c index 5cd729203..c8d82e892 100644 --- a/src/multicast/multicast_api.c +++ b/src/multicast/multicast_api.c @@ -802,6 +802,7 @@ GNUNET_MULTICAST_member_join (const struct GNUNET_CONFIGURATION_Handle *cfg, join->group_key = *group_key; join->member_key = *member_key; join->origin = *origin; + join->relay_count = ntohl (relay_count); if (0 < relay_size) memcpy (&join[1], relays, relay_size); if (0 < join_msg_size) diff --git a/src/psyc/gnunet-service-psyc.c b/src/psyc/gnunet-service-psyc.c index 070fd8e47..1f7e7c23c 100644 --- a/src/psyc/gnunet-service-psyc.c +++ b/src/psyc/gnunet-service-psyc.c @@ -1792,9 +1792,11 @@ client_recv_slave_join (void *cls, struct GNUNET_SERVER_Client *client, if (sizeof (*req) + relay_size + sizeof (struct GNUNET_MessageHeader) <= req_size) { - join_msg_size = ntohs (slv->join_msg->header.size); + struct GNUNET_PSYC_Message * + join_msg = (struct GNUNET_PSYC_Message *) (((char *) &req[1]) + relay_size); + join_msg_size = ntohs (join_msg->header.size); slv->join_msg = GNUNET_malloc (join_msg_size); - memcpy (slv->join_msg, ((char *) &req[1]) + relay_size, join_msg_size); + memcpy (slv->join_msg, join_msg, join_msg_size); } if (sizeof (*req) + relay_size + join_msg_size != req_size) { diff --git a/src/psyc/psyc_api.c b/src/psyc/psyc_api.c index b862eee9c..6128e4d82 100644 --- a/src/psyc/psyc_api.c +++ b/src/psyc/psyc_api.c @@ -669,7 +669,7 @@ GNUNET_PSYC_master_start (const struct GNUNET_CONFIGURATION_Handle *cfg, req->channel_key = *channel_key; req->policy = policy; - chn->connect_msg = (struct GNUNET_MessageHeader *) req; + chn->connect_msg = &req->header; chn->cfg = cfg; chn->is_master = GNUNET_YES; @@ -896,8 +896,7 @@ GNUNET_PSYC_slave_join (const struct GNUNET_CONFIGURATION_Handle *cfg, else join_msg_size = ntohs (join_msg->header.size); req = GNUNET_malloc (sizeof (*req) + relay_size + join_msg_size); - req->header.size = htons (sizeof (*req) - + relay_count * sizeof (*relays)); + req->header.size = htons (sizeof (*req) + relay_size + join_msg_size); req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN); req->channel_key = *channel_key; req->slave_key = *slave_key; @@ -908,11 +907,9 @@ GNUNET_PSYC_slave_join (const struct GNUNET_CONFIGURATION_Handle *cfg, memcpy (&req[1], relays, relay_size); if (NULL != join_msg) - memcpy ((char *) &req[1] + relay_size, - join_msg, - join_msg_size); + memcpy ((char *) &req[1] + relay_size, join_msg, join_msg_size); - chn->connect_msg = (struct GNUNET_MessageHeader *) req; + chn->connect_msg = &req->header; chn->cfg = cfg; chn->is_master = GNUNET_NO; diff --git a/src/psycstore/gnunet-service-psycstore.c b/src/psycstore/gnunet-service-psycstore.c index 01eb5d707..44103c6a0 100644 --- a/src/psycstore/gnunet-service-psycstore.c +++ b/src/psycstore/gnunet-service-psycstore.c @@ -479,7 +479,7 @@ handle_counters_get (void *cls, res.header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_COUNTERS); res.header.size = htons (sizeof (res)); - res.result_code = htonl (ret - INT32_MIN); + res.result_code = htonl (ret); res.op_id = req->op_id; res.max_fragment_id = GNUNET_htonll (res.max_fragment_id); res.max_message_id = GNUNET_htonll (res.max_message_id); diff --git a/src/psycstore/psyc_util_lib.c b/src/psycstore/psyc_util_lib.c index e45bcafb3..80e84f29c 100644 --- a/src/psycstore/psyc_util_lib.c +++ b/src/psycstore/psyc_util_lib.c @@ -198,11 +198,11 @@ GNUNET_PSYC_message_create (const char *method_name, if (method_name_size == 1) return NULL; - uint16_t msg_size = sizeof (*msg) /* header */ - + sizeof (*pmeth) + method_name_size /* method */ - + env_size /* modifiers */ - + ((0 < data_size) ? sizeof (*pmsg) + data_size : 0)/* data */ - + sizeof (*pmsg); /* end of message */ + uint16_t msg_size = sizeof (*msg) /* header */ + + sizeof (*pmeth) + method_name_size /* method */ + + env_size /* modifiers */ + + ((0 < data_size) ? sizeof (*pmsg) + data_size : 0) /* data */ + + sizeof (*pmsg); /* end of message */ msg = GNUNET_malloc (msg_size); msg->header.size = htons (msg_size); msg->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE); /* FIXME */ @@ -225,6 +225,10 @@ GNUNET_PSYC_message_create (const char *method_name, p += pmod->header.size; pmod->header.size = htons (pmod->header.size); + pmod->oper = mod->oper; + pmod->name_size = htons (mod_name_size); + pmod->value_size = htonl (mod->value_size); + memcpy (&pmod[1], mod->name, mod_name_size); if (0 < mod->value_size) memcpy ((char *) &pmod[1] + mod_name_size, mod->value, mod->value_size); @@ -1192,9 +1196,9 @@ parse_message_part_cb (void *cls, pmod = (struct GNUNET_PSYC_MessageModifier *) msg; const char *name = (const char *) &pmod[1]; - const void *value = name + pmod->name_size; + const void *value = name + ntohs (pmod->name_size); GNUNET_ENV_environment_add (pmc->env, pmod->oper, name, value, - pmod->value_size); + ntohl (pmod->value_size)); pmc->msg_state = GNUNET_PSYC_MESSAGE_STATE_MODIFIER; break; } @@ -1233,7 +1237,7 @@ parse_message_part_cb (void *cls, * #GNUNET_SYSERR on parse error. */ int -GNUNET_PSYC_message_parse (const struct GNUNET_PSYC_Message *msg, +GNUNET_PSYC_message_parse (const struct GNUNET_PSYC_MessageHeader *msg, const char **method_name, struct GNUNET_ENV_Environment *env, const void **data, @@ -1245,16 +1249,10 @@ GNUNET_PSYC_message_parse (const struct GNUNET_PSYC_Message *msg, 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_message (recv, msg); GNUNET_PSYC_receive_destroy (recv); - GNUNET_free (pmsg); return (GNUNET_PSYC_MESSAGE_STATE_END == cls.msg_state) ? GNUNET_OK @@ -1284,7 +1282,7 @@ GNUNET_PSYC_message_header_init (struct GNUNET_PSYC_MessageHeader *pmsg, /** - * Create a new PSYC message header from a multicast message for sending it to clients. + * Create a new PSYC message header from a multicast message. */ struct GNUNET_PSYC_MessageHeader * GNUNET_PSYC_message_header_create (const struct GNUNET_MULTICAST_MessageHeader *mmsg, @@ -1298,3 +1296,19 @@ GNUNET_PSYC_message_header_create (const struct GNUNET_MULTICAST_MessageHeader * GNUNET_PSYC_message_header_init (pmsg, mmsg, flags); return pmsg; } + + +/** + * Create a new PSYC message header from a PSYC message. + */ +struct GNUNET_PSYC_MessageHeader * +GNUNET_PSYC_message_header_create_from_psyc (const struct GNUNET_PSYC_Message *msg) +{ + uint16_t msg_size = ntohs (msg->header.size); + struct GNUNET_PSYC_MessageHeader * + pmsg = GNUNET_malloc (sizeof (*pmsg) + msg_size - sizeof (*msg)); + pmsg->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE); + pmsg->header.size = htons (sizeof (*pmsg) + msg_size - sizeof (*msg)); + memcpy (&pmsg[1], &msg[1], msg_size - sizeof (*msg)); + return pmsg; +} diff --git a/src/psycstore/psycstore_api.c b/src/psycstore/psycstore_api.c index 214d8ba5d..f378be210 100644 --- a/src/psycstore/psycstore_api.c +++ b/src/psycstore/psycstore_api.c @@ -346,7 +346,7 @@ message_handler (void *cls, const struct GNUNET_MessageHeader *msg) if (NULL != op->data_cb) ((GNUNET_PSYCSTORE_CountersCallback) op->data_cb) (op->cls, - ntohl (cres->result_code) + INT32_MIN, + ntohl (cres->result_code), GNUNET_ntohll (cres->max_fragment_id), GNUNET_ntohll (cres->max_message_id), GNUNET_ntohll (cres->max_group_generation), diff --git a/src/social/gnunet-service-social.c b/src/social/gnunet-service-social.c index 3f558730e..bf147d3ba 100644 --- a/src/social/gnunet-service-social.c +++ b/src/social/gnunet-service-social.c @@ -528,7 +528,7 @@ psyc_master_started (void *cls, int result, uint64_t max_message_id) struct GNUNET_PSYC_CountersResultMessage res; res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK); res.header.size = htons (sizeof (res)); - res.result_code = htonl (result - INT32_MIN); + res.result_code = htonl (result); res.max_message_id = GNUNET_htonll (plc->max_message_id); client_send_msg (plc, &res.header); @@ -568,7 +568,7 @@ psyc_slave_connected (void *cls, int result, uint64_t max_message_id) struct GNUNET_PSYC_CountersResultMessage res; res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK); res.header.size = htons (sizeof (res)); - res.result_code = htonl (result - INT32_MIN); + res.result_code = htonl (result); res.max_message_id = GNUNET_htonll (plc->max_message_id); client_send_msg (plc, &res.header); diff --git a/src/social/social_api.c b/src/social/social_api.c index a49f1160d..17e5a3bfc 100644 --- a/src/social/social_api.c +++ b/src/social/social_api.c @@ -470,7 +470,6 @@ host_recv_notice_place_leave_method (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "_notice_place_leave: got method from nym %s (%s).\n", GNUNET_h2s (&hst->notice_place_leave_nym->pub_key_hash), str); - GNUNET_break (0); } @@ -1251,7 +1250,7 @@ host_recv_enter_ack (void *cls, struct GNUNET_PSYC_CountersResultMessage * cres = (struct GNUNET_PSYC_CountersResultMessage *) msg; - int32_t result = ntohl (cres->result_code) + INT32_MIN; + int32_t result = ntohl (cres->result_code); if (NULL != hst->enter_cb) hst->enter_cb (hst->cb_cls, result, GNUNET_ntohll (cres->max_message_id)); } @@ -1270,6 +1269,7 @@ host_recv_enter_request (void *cls, const char *method_name = NULL; struct GNUNET_ENV_Environment *env = NULL; + struct GNUNET_PSYC_MessageHeader *entry_pmsg; const void *data = NULL; uint16_t data_size = 0; char *str; @@ -1277,34 +1277,38 @@ host_recv_enter_request (void *cls, 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)) + do { - 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)) + if (sizeof (*req) + sizeof (*entry_msg) <= ntohs (req->header.size)) { - GNUNET_break_op (0); - str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&req->slave_key); - LOG (GNUNET_ERROR_TYPE_WARNING, - "Ignoring invalid entry request from nym %s.\n", - str); - GNUNET_free (str); - GNUNET_ENV_environment_destroy (env); - return; + 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 (); + entry_pmsg = GNUNET_PSYC_message_header_create_from_psyc (entry_msg); + if (GNUNET_OK != GNUNET_PSYC_message_parse (entry_pmsg, &method_name, env, + &data, &data_size)) + { + GNUNET_break_op (0); + str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&req->slave_key); + LOG (GNUNET_ERROR_TYPE_WARNING, + "Ignoring invalid entry request from nym %s.\n", + str); + GNUNET_free (str); + break; + } } - } - 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); + 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); + } while (0); if (NULL != env) GNUNET_ENV_environment_destroy (env); + GNUNET_free (entry_pmsg); } @@ -1319,7 +1323,7 @@ guest_recv_enter_ack (void *cls, struct GNUNET_PSYC_CountersResultMessage * cres = (struct GNUNET_PSYC_CountersResultMessage *) msg; - int32_t result = ntohl (cres->result_code) + INT32_MIN; + int32_t result = ntohl (cres->result_code); if (NULL != gst->enter_cb) gst->enter_cb (gst->cb_cls, result, GNUNET_ntohll (cres->max_message_id)); } @@ -1424,11 +1428,30 @@ static struct GNUNET_CLIENT_MANAGER_MessageHandler guest_handlers[] = 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->tmit) + GNUNET_PSYC_transmit_destroy (plc->tmit); + if (NULL != plc->recv) + GNUNET_PSYC_receive_destroy (plc->recv); + if (NULL != plc->connect_msg) + GNUNET_free (plc->connect_msg); if (NULL != plc->disconnect_cb) plc->disconnect_cb (plc->disconnect_cls); + + if (NULL != core) + { + GNUNET_CORE_disconnect (core); + core = NULL; + } + if (NULL != namestore) + { + GNUNET_NAMESTORE_disconnect (namestore); + namestore = NULL; + } + if (NULL != gns) + { + GNUNET_GNS_disconnect (gns); + gns = NULL; + } } @@ -1508,7 +1531,6 @@ GNUNET_SOCIAL_host_enter (const struct GNUNET_CONFIGURATION_Handle *cfg, 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); @@ -1521,7 +1543,9 @@ GNUNET_SOCIAL_host_enter (const struct GNUNET_CONFIGURATION_Handle *cfg, plc->is_host = GNUNET_YES; plc->slicer = slicer; - hst->plc.ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego); + plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego); + GNUNET_CRYPTO_eddsa_key_get_public (place_key, &plc->pub_key); + hst->enter_cb = enter_cb; hst->answer_door_cb = answer_door_cb; hst->farewell_cb = farewell_cb; @@ -1744,7 +1768,7 @@ core_connected_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity) * @param expiration_time * Expiration time of the record, use 0 to remove the record. * @param password - * Password used to encrypt the record. + * Password used to encrypt the record or NULL to keep it cleartext. * @param result_cb * Function called with the result of the operation. * @param result_cls @@ -1753,9 +1777,9 @@ core_connected_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity) void GNUNET_SOCIAL_host_advertise (struct GNUNET_SOCIAL_Host *hst, const char *name, - size_t peer_count, + uint32_t peer_count, const struct GNUNET_PeerIdentity *peers, - struct GNUNET_TIME_Relative expiration_time, + struct GNUNET_TIME_Absolute expiration_time, const char *password, GNUNET_NAMESTORE_ContinuationWithStatus result_cb, void *result_cls) @@ -1767,19 +1791,20 @@ GNUNET_SOCIAL_host_advertise (struct GNUNET_SOCIAL_Host *hst, 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 }; + struct GNUNET_GNSRECORD_Data rd = { }; 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; + rd.expiration_time = expiration_time.abs_value_us; - struct GNUNET_GNSRECORD_PlaceData *rec = GNUNET_malloc (sizeof (*rec)); + struct GNUNET_GNSRECORD_PlaceData * + rec = GNUNET_malloc (sizeof (*rec) + peer_count * sizeof (*peers)); rec->place_key = plc->pub_key; rec->origin = this_peer; - rec->relay_count = htons (0); // FIXME + rec->relay_count = htonl (peer_count); + memcpy (&rec[1], peers, peer_count * sizeof (*peers)); - rd.data_size = sizeof (*rec); rd.data = rec; + rd.data_size = sizeof (*rec) + peer_count * sizeof (*peers); GNUNET_NAMESTORE_records_store (namestore, &hst->plc.ego_key, name, 1, &rd, result_cb, result_cls); @@ -1907,7 +1932,7 @@ guest_enter_request_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *guest_ke req->place_key = *place_key; req->guest_key = *guest_key; req->origin = *origin; - req->relay_count = relay_count; + req->relay_count = htonl (relay_count); uint16_t p = sizeof (*req); if (0 < relay_size) @@ -1990,6 +2015,9 @@ gns_result_guest_enter (void *cls, uint32_t rd_count, struct GNUNET_SOCIAL_Guest *gst = cls; struct GNUNET_SOCIAL_Place *plc = &gst->plc; + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "%p GNS result: %u records.\n", gst, rd_count); + const struct GNUNET_GNSRECORD_PlaceData * rec = (const struct GNUNET_GNSRECORD_PlaceData *) rd->data; @@ -2000,7 +2028,6 @@ gns_result_guest_enter (void *cls, uint32_t rd_count, return; } - if (rd->data_size < sizeof (*rec)) { GNUNET_break_op (0); @@ -2009,80 +2036,67 @@ gns_result_guest_enter (void *cls, uint32_t rd_count, return; } - struct GuestEnterRequest * - req = (struct GuestEnterRequest *) plc->connect_msg; - uint16_t req_size = ntohs (req->header.size); - uint16_t relay_count = ntohs (rec->relay_count); + uint16_t relay_count = ntohl (rec->relay_count); + struct GNUNET_PeerIdentity *relays = NULL; if (0 < relay_count) { if (rd->data_size == sizeof (*rec) + relay_count * sizeof (struct GNUNET_PeerIdentity)) { - struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &rec[1]; - 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; + relays = (struct GNUNET_PeerIdentity *) &rec[1]; } else { + relay_count = 0; GNUNET_break_op (0); } } - 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)); - + struct GuestEnterRequest * + req = guest_enter_request_create (&plc->ego_key, &rec->place_key, + &rec->origin, relay_count, relays, + (struct GNUNET_PSYC_Message *) plc->connect_msg); + GNUNET_free (plc->connect_msg); 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); + plc->recv = GNUNET_PSYC_receive_create (NULL, slicer_message, plc->slicer); place_send_connect_msg (plc); } + /** - * Request entry to a place as a guest. + * Request entry to a place by name as a guest. * - * @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 + * @param cfg + * Configuration to contact the social service. + * @param ego + * Identity of the guest. + * @param gns_name + * 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. - * @param data_size Number of bytes in @a data. - * @param slicer Slicer to use for processing incoming requests from guests. + * @param password + * Password to decrypt the record, or NULL for cleartext records. + * @param join_msg + * Entry request message. + * @param slicer + * Slicer to use for processing incoming requests from guests. + * @param local_enter_cb + * Called upon connection established to the social service. + * @param entry_decision_cb + * Called upon receiving entry decision. * * @return NULL on errors, otherwise handle for the guest. */ struct GNUNET_SOCIAL_Guest * GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_IDENTITY_Ego *ego, - char *gns_name, + const struct GNUNET_IDENTITY_Ego *ego, + const char *gns_name, const char *password, const struct GNUNET_PSYC_Message *join_msg, struct GNUNET_SOCIAL_Slicer *slicer, GNUNET_SOCIAL_GuestEnterCallback local_enter_cb, @@ -2092,7 +2106,10 @@ GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_CONFIGURATION_Handle *cfg struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst)); struct GNUNET_SOCIAL_Place *plc = &gst->plc; + GNUNET_assert (NULL != join_msg); + gst->enter_cb = local_enter_cb; + gst->entry_dcsn_cb = entry_decision_cb; gst->cb_cls = cls; plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego); @@ -2100,14 +2117,10 @@ GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_CONFIGURATION_Handle *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; + uint16_t join_msg_size = ntohs (join_msg->header.size); + plc->connect_msg = GNUNET_malloc (join_msg_size); + memcpy (plc->connect_msg, join_msg, join_msg_size); - /* 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); @@ -2119,7 +2132,6 @@ GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_CONFIGURATION_Handle *cfg 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; } @@ -2151,10 +2163,13 @@ GNUNET_SOCIAL_guest_talk (struct GNUNET_SOCIAL_Guest *gst, void *notify_data_cls, enum GNUNET_SOCIAL_TalkFlags flags) { + struct GNUNET_SOCIAL_Place *plc = &gst->plc; + GNUNET_assert (NULL != plc->tmit); + if (GNUNET_OK == - GNUNET_PSYC_transmit_message (gst->plc.tmit, method_name, env, + GNUNET_PSYC_transmit_message (plc->tmit, method_name, env, NULL, notify_data, notify_data_cls, flags)); - return (struct GNUNET_SOCIAL_TalkRequest *) gst->plc.tmit; + return (struct GNUNET_SOCIAL_TalkRequest *) plc->tmit; } @@ -2209,13 +2224,14 @@ GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Guest *gst, { 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; - if (GNUNET_NO == keep_active) + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Guest: leaving place.\n"); + + if (GNUNET_NO == keep_active && NULL != plc->tmit) { GNUNET_SOCIAL_guest_talk (gst, "_notice_place_leave", env, NULL, NULL, GNUNET_SOCIAL_TALK_NONE); @@ -2471,4 +2487,47 @@ GNUNET_SOCIAL_place_look_cancel (struct GNUNET_SOCIAL_LookHandle *look) } +/** + * Add public key to the GNS zone of the @e ego. + * + * @param cfg + * Configuration. + * @param ego + * Ego. + * @param name + * The name for the PKEY record to put in the zone. + * @param pub_key + * Public key to add. + * @param expiration_time + * Expiration time of the record, use 0 to remove the record. + * @param result_cb + * Function called with the result of the operation. + * @param result_cls + * Closure for @a result_cb + */ +void +GNUNET_SOCIAL_zone_add_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg, + const struct GNUNET_IDENTITY_Ego *ego, + const char *name, + const struct GNUNET_CRYPTO_EcdsaPublicKey *pub_key, + struct GNUNET_TIME_Absolute expiration_time, + GNUNET_NAMESTORE_ContinuationWithStatus result_cb, + void *result_cls) +{ + if (NULL == namestore) + namestore = GNUNET_NAMESTORE_connect (cfg); + + struct GNUNET_GNSRECORD_Data rd = { }; + rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY; + rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; + rd.expiration_time = expiration_time.abs_value_us; + rd.data = pub_key; + rd.data_size = sizeof (*pub_key); + + GNUNET_NAMESTORE_records_store (namestore, + GNUNET_IDENTITY_ego_get_private_key (ego), + name, 1, &rd, result_cb, result_cls); +} + + /* end of social_api.c */ diff --git a/src/social/test_social.c b/src/social/test_social.c index 50150449c..5a224c4ae 100644 --- a/src/social/test_social.c +++ b/src/social/test_social.c @@ -68,6 +68,7 @@ struct GNUNET_CRYPTO_EcdsaPrivateKey *guest_key; struct GNUNET_CRYPTO_EddsaPublicKey place_pub_key; struct GNUNET_CRYPTO_EcdsaPublicKey guest_pub_key; +struct GNUNET_CRYPTO_EcdsaPublicKey host_pub_key; struct GNUNET_SOCIAL_Slicer *host_slicer; struct GNUNET_SOCIAL_Slicer *guest_slicer; @@ -110,6 +111,8 @@ struct GNUNET_PSYC_Message *join_resp; uint32_t counter; +uint8_t guest_pkey_added = GNUNET_NO; + enum { TEST_NONE = 0, @@ -136,11 +139,12 @@ enum static void guest_enter (); +static void +guest_enter_by_name (); static void guest_talk (); - static void host_announce2 (); @@ -308,11 +312,26 @@ schedule_host_leave (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } +static void +id_guest_ego_cb2 (void *cls, const struct GNUNET_IDENTITY_Ego *ego) +{ + GNUNET_assert (NULL != ego); + guest_ego = ego; + + guest_enter_by_name (); +} + + static void host_recv_advertise_result (void *cls, int32_t success, const char *emsg) { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Test #%u: Advertise result: %d (%s).\n", + test, success, emsg); GNUNET_assert (GNUNET_YES == success); - GNUNET_SCHEDULER_add_now (&schedule_host_leave, NULL); + + GNUNET_assert (GNUNET_YES == guest_pkey_added); + GNUNET_IDENTITY_ego_lookup (cfg, guest_name, id_guest_ego_cb2, NULL); } @@ -320,10 +339,12 @@ static void host_advertise () { test = TEST_HOST_ADVERTISE; - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Test #%u: Advertising place.\n", test); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Test #%u: Advertising place.\n", test); + GNUNET_SOCIAL_host_advertise (hst, "home", 1, &this_peer, - GNUNET_TIME_UNIT_MINUTES, "let.me*in!", - host_recv_advertise_result, hst); + GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES), + "let.me*in!", host_recv_advertise_result, hst); } @@ -714,10 +735,9 @@ host_recv_eom (void *cls, guest_history_replay (); break; - case TEST_GUEST_LEAVE: - break; - default: + if (TEST_GUEST_LEAVE <= test) + break; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "invalid test: %d\n", test); GNUNET_assert (0); } @@ -811,19 +831,22 @@ host_announce2 () static void guest_recv_entry_decision (void *cls, int is_admitted, - const struct GNUNET_PSYC_Message *entry_resp) + const struct GNUNET_PSYC_Message *entry_msg) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Test #%u: Guest received entry decision (try %u): %d.\n", test, join_req_count, is_admitted); - if (NULL != entry_resp) + if (NULL != entry_msg) { 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); + struct GNUNET_PSYC_MessageHeader * + pmsg = GNUNET_PSYC_message_header_create_from_psyc (entry_msg); + GNUNET_PSYC_message_parse (pmsg, &method_name, env, &data, &data_size); + GNUNET_free (pmsg); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s\n%.*s\n", @@ -843,6 +866,10 @@ guest_recv_entry_decision (void *cls, host_announce (); break; + case TEST_GUEST_ENTER_BY_NAME: + GNUNET_SCHEDULER_add_now (schedule_host_leave, NULL); + break; + default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "invalid test: %d\n", test); GNUNET_assert (0); @@ -878,6 +905,7 @@ host_answer_door (void *cls, case TEST_HOST_ANSWER_DOOR_ADMIT: test = TEST_GUEST_RECV_ENTRY_DCSN_ADMIT; + case TEST_GUEST_ENTER_BY_NAME: join_resp = GNUNET_PSYC_message_create ("_admit_nym", env, DATA2ARG ("Welcome, nym!")); GNUNET_SOCIAL_host_entry_decision (hst, nym, GNUNET_YES, join_resp); @@ -894,8 +922,9 @@ static void guest_recv_local_enter (void *cls, int result, uint64_t max_message_id) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Test #%u: Guest entered to local place.\n", test); - + "Test #%u: Guest entered to local place: %d\n", + test, result); + GNUNET_assert (0 <= result); } @@ -919,13 +948,50 @@ guest_enter () 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); + &this_peer, 0, NULL, emsg->msg, guest_slicer, + guest_recv_local_enter, + guest_recv_entry_decision, NULL); + gst_plc = GNUNET_SOCIAL_guest_get_place (gst); +} + + +static void +guest_enter_by_name () +{ + test = TEST_GUEST_ENTER_BY_NAME; + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Test #%u: Entering to place by name as guest.\n", test); + + 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_by_name (cfg, guest_ego, + "home.host.gnu", "let.me*in!", + emsg->msg, guest_slicer, + guest_recv_local_enter, + guest_recv_entry_decision, NULL); gst_plc = GNUNET_SOCIAL_guest_get_place (gst); } +static void +guest_recv_add_pkey_result (void *cls, int32_t success, const char *emsg) +{ + GNUNET_assert (GNUNET_YES == success); + guest_pkey_added = GNUNET_YES; +} + + static void id_guest_ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego) { @@ -941,6 +1007,10 @@ id_guest_ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego) guest_recv_mod_foo_bar, &mod_foo_bar_rcls); test = TEST_HOST_ANSWER_DOOR_ADMIT; + GNUNET_SOCIAL_zone_add_pkey (cfg, guest_ego, "host", &host_pub_key, + GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES), + guest_recv_add_pkey_result, NULL); + guest_enter (); } @@ -975,6 +1045,7 @@ id_host_ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego) { GNUNET_assert (NULL != ego); host_ego = ego; + GNUNET_IDENTITY_ego_get_public_key (ego, &host_pub_key); host_slicer = GNUNET_SOCIAL_slicer_create (); GNUNET_SOCIAL_slicer_method_add (host_slicer, "", -- cgit v1.2.3