/** * Broadcast information about the given entry to all * clients that care. * * @param entry entry to broadcast about */ static void notify_all (struct HostEntry *entry) { struct InfoMessage *msg_pub; struct InfoMessage *msg_friend; struct NotificationContext *cur; msg_pub = make_info_message (entry, GNUNET_NO); msg_friend = make_info_message (entry, GNUNET_YES); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Notifying all clients about peer `%s'\n", GNUNET_i2s(&entry->identity)); for (cur = nc_head; NULL != cur; cur = cur->next) { if (GNUNET_NO == cur->include_friend_only) { GNUNET_SERVER_notification_context_unicast (notify_list, cur->client, &msg_pub->header, GNUNET_NO); } if (GNUNET_YES == cur->include_friend_only) { GNUNET_SERVER_notification_context_unicast (notify_list, cur->client, &msg_friend->header, GNUNET_NO); } } GNUNET_free (msg_pub); GNUNET_free (msg_friend); }
/** * Handler for START message from client, sends information * about all identities to the client immediately and * adds the client to the notification context for future * updates. * * @param cls unused * @param client who sent the message * @param message the message received */ static void handle_start_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct GNUNET_IDENTITY_UpdateMessage *um; struct GNUNET_IDENTITY_UpdateMessage ume; struct Ego *ego; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received START message from client\n"); GNUNET_SERVER_notification_context_add (nc, client); for (ego = ego_head; NULL != ego; ego = ego->next) { um = create_update_message (ego); GNUNET_SERVER_notification_context_unicast (nc, client, &um->header, GNUNET_NO); GNUNET_free (um); } memset (&ume, 0, sizeof (ume)); ume.header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE); ume.header.size = htons (sizeof (struct GNUNET_IDENTITY_UpdateMessage)); ume.end_of_list = htons (GNUNET_YES); ume.name_len = htons (0); GNUNET_SERVER_notification_context_unicast (nc, client, &ume.header, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); }
/** * Send shorten response back to client * * @param cls the closure containing a client shorten handle * @param name the shortened name result or NULL if cannot be shortened */ static void send_shorten_response(void* cls, const char* name) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %s\n", "SHORTEN_RESULT", name); struct GNUNET_GNS_ClientShortenResultMessage *rmsg; struct ClientShortenHandle *csh = (struct ClientShortenHandle *)cls; if (name == NULL) { name = ""; } rmsg = GNUNET_malloc(sizeof(struct GNUNET_GNS_ClientShortenResultMessage) + strlen(name) + 1); rmsg->id = csh->unique_id; rmsg->header.type = htons(GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT); rmsg->header.size = htons(sizeof(struct GNUNET_GNS_ClientShortenResultMessage) + strlen(name) + 1); strcpy((char*)&rmsg[1], name); GNUNET_SERVER_notification_context_unicast (nc, csh->client, (const struct GNUNET_MessageHeader *) rmsg, GNUNET_NO); GNUNET_SERVER_receive_done (csh->client, GNUNET_OK); GNUNET_free(rmsg); GNUNET_free_non_null(csh->name); GNUNET_free_non_null(csh->zone_key); GNUNET_free(csh); }
/** * Send a result code back to the client. * * @param client client that should receive the result code * @param result_code code to transmit * @param emsg error message to include (or NULL for none) */ static void send_result_code (struct GNUNET_SERVER_Client *client, uint32_t result_code, const char *emsg) { struct GNUNET_IDENTITY_ResultCodeMessage *rcm; size_t elen; if (NULL == emsg) elen = 0; else elen = strlen (emsg) + 1; rcm = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_ResultCodeMessage) + elen); rcm->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE); rcm->header.size = htons (sizeof (struct GNUNET_IDENTITY_ResultCodeMessage) + elen); rcm->result_code = htonl (result_code); if (0 < elen) memcpy (&rcm[1], emsg, elen); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending result %d (%s) to client\n", (int) result_code, emsg); GNUNET_SERVER_notification_context_unicast (nc, client, &rcm->header, GNUNET_NO); GNUNET_free (rcm); }
/** * Broadcast the new active address to all clients monitoring the peer. * * @param peer peer this update is about (never NULL) * @param address address, NULL on disconnect * @param state the current state of the peer * @param state_timeout the time out for the state */ void GST_clients_broadcast_peer_notification (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout) { struct PeerIterateResponseMessage *msg; struct MonitoringClient *mc; static struct GNUNET_PeerIdentity all_zeros; msg = compose_address_iterate_response_message (peer, address); msg->state = htonl (state); msg->state_timeout = GNUNET_TIME_absolute_hton (state_timeout); mc = peer_monitoring_clients_head; while (mc != NULL) { if ((0 == memcmp (&mc->peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity))) || (0 == memcmp (&mc->peer, peer, sizeof (struct GNUNET_PeerIdentity)))) { GNUNET_SERVER_notification_context_unicast (peer_nc, mc->client, &msg->header, GNUNET_NO); } mc = mc->next; } GNUNET_free (msg); }
/** * Send a message to one of our clients. * * @param client target for the message * @param msg message to transmit * @param can_drop could this message be dropped if the * client's queue is getting too large? */ static void send_to_client (struct GSC_Client *client, const struct GNUNET_MessageHeader *msg, int can_drop) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Preparing to send %u bytes of message of type %u to client.\n", (unsigned int) ntohs (msg->size), (unsigned int) ntohs (msg->type)); GNUNET_SERVER_notification_context_unicast (notifier, client->client_handle, msg, can_drop); }
/** * FIXME. */ static int do_notify_entry (void *cls, const GNUNET_HashCode * key, void *value) { struct GNUNET_SERVER_Client *client = cls; struct HostEntry *he = value; struct InfoMessage *msg; msg = make_info_message (he); GNUNET_SERVER_notification_context_unicast (notify_list, client, &msg->header, GNUNET_NO); GNUNET_free (msg); return GNUNET_YES; }
/** * Handle result, pass it back to the client. * * @param cls the struct ClientEntry of the client searching * @param id Peer providing a regex that matches the string. * @param get_path Path of the get request. * @param get_path_length Lenght of @a get_path. * @param put_path Path of the put request. * @param put_path_length Length of the @a put_path. */ static void handle_search_result (void *cls, const struct GNUNET_PeerIdentity *id, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length) { struct ClientEntry *ce = cls; struct ResultMessage *result; struct GNUNET_PeerIdentity *gp; uint16_t size; if ( (get_path_length >= 65536) || (put_path_length >= 65536) || ( (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity)) + sizeof (struct ResultMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } size = (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity) + sizeof (struct ResultMessage); result = GNUNET_malloc (size); result->header.size = htons (size); result->header.type = htons (GNUNET_MESSAGE_TYPE_REGEX_RESULT); result->get_path_length = htons ((uint16_t) get_path_length); result->put_path_length = htons ((uint16_t) put_path_length); result->id = *id; gp = &result->id; GNUNET_memcpy (&gp[1], get_path, get_path_length * sizeof (struct GNUNET_PeerIdentity)); GNUNET_memcpy (&gp[1 + get_path_length], put_path, put_path_length * sizeof (struct GNUNET_PeerIdentity)); GNUNET_SERVER_notification_context_unicast (nc, ce->client, &result->header, GNUNET_NO); GNUNET_free (result); }
/** * Send get authority response back to client * * @param cls the closure containing a client get auth handle * @param name the shortened name result or NULL if cannot be shortened */ static void send_get_auth_response(void *cls, const char* name) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %s\n", "GET_AUTH_RESULT", name); struct GNUNET_GNS_ClientGetAuthResultMessage *rmsg; struct ClientGetAuthHandle *cah = (struct ClientGetAuthHandle *)cls; if (name == NULL) { name = ""; } rmsg = GNUNET_malloc(sizeof(struct GNUNET_GNS_ClientGetAuthResultMessage) + strlen(name) + 1); rmsg->id = cah->unique_id; rmsg->header.type = htons(GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT); rmsg->header.size = htons(sizeof(struct GNUNET_GNS_ClientGetAuthResultMessage) + strlen(name) + 1); strcpy((char*)&rmsg[1], name); GNUNET_SERVER_notification_context_unicast (nc, cah->client, (const struct GNUNET_MessageHeader *) rmsg, GNUNET_NO); GNUNET_SERVER_receive_done (cah->client, GNUNET_OK); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up handles...\n"); GNUNET_free(rmsg); GNUNET_free_non_null(cah->name); GNUNET_free(cah); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done.\n"); }
/** * Broadcast the new validation changes to all clients monitoring the peer. * * @param peer peer this update is about (never NULL) * @param address address, NULL on disconnect * @param last_validation point in time when last validation was performed * @param valid_until point in time how long address is valid * @param next_validation point in time when next validation will be performed * @param state state of validation notification */ void GST_clients_broadcast_validation_notification ( const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute last_validation, struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute next_validation, enum GNUNET_TRANSPORT_ValidationState state) { struct ValidationIterateResponseMessage *msg; struct MonitoringClient *mc; static struct GNUNET_PeerIdentity all_zeros; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending information about for validation entry for peer `%s' using address `%s'\n", GNUNET_i2s(peer), (address != NULL) ? GST_plugins_a2s (address) : "<none>"); msg = compose_validation_iterate_response_message (peer, address); msg->last_validation = GNUNET_TIME_absolute_hton(last_validation); msg->valid_until = GNUNET_TIME_absolute_hton(valid_until); msg->next_validation = GNUNET_TIME_absolute_hton(next_validation); msg->state = htonl ((uint32_t) state); mc = val_monitoring_clients_head; while (mc != NULL) { if ((0 == memcmp (&mc->peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity))) || (0 == memcmp (&mc->peer, peer, sizeof (struct GNUNET_PeerIdentity)))) { GNUNET_SERVER_notification_context_unicast (val_nc, mc->client, &msg->header, GNUNET_NO); } mc = mc->next; } GNUNET_free (msg); }
/** * Reply to client with the result from our lookup. * * @param cls the closure (our client lookup handle) * @param rd_count the number of records * @param rd the record data */ static void send_lookup_response(void* cls, uint32_t rd_count, const struct GNUNET_NAMESTORE_RecordData *rd) { struct ClientLookupHandle* clh = (struct ClientLookupHandle*)cls; struct GNUNET_GNS_ClientLookupResultMessage *rmsg; size_t len; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %d results\n", "LOOKUP_RESULT", rd_count); len = GNUNET_NAMESTORE_records_get_size (rd_count, rd); rmsg = GNUNET_malloc(len+sizeof(struct GNUNET_GNS_ClientLookupResultMessage)); rmsg->id = clh->unique_id; rmsg->rd_count = htonl(rd_count); rmsg->header.type = htons(GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT); rmsg->header.size = htons(len+sizeof(struct GNUNET_GNS_ClientLookupResultMessage)); GNUNET_NAMESTORE_records_serialize (rd_count, rd, len, (char*)&rmsg[1]); GNUNET_SERVER_notification_context_unicast (nc, clh->client, (const struct GNUNET_MessageHeader *) rmsg, GNUNET_NO); GNUNET_SERVER_receive_done (clh->client, GNUNET_OK); GNUNET_free(rmsg); GNUNET_free(clh->name); if (NULL != clh->zone_key) GNUNET_free(clh->zone_key); GNUNET_free(clh); }
/** * Handler for GET_DEFAULT message from client, returns * default identity for some service. * * @param cls unused * @param client who sent the message * @param message the message received */ static void handle_get_default_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_IDENTITY_GetDefaultMessage *gdm; struct GNUNET_IDENTITY_SetDefaultMessage *sdm; uint16_t size; uint16_t name_len; struct Ego *ego; const char *name; char *identifier; size = ntohs (message->size); if (size <= sizeof (struct GNUNET_IDENTITY_GetDefaultMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } gdm = (const struct GNUNET_IDENTITY_GetDefaultMessage *) message; name = (const char *) &gdm[1]; name_len = ntohs (gdm->name_len); if ( (name_len + sizeof (struct GNUNET_IDENTITY_GetDefaultMessage) != size) || (0 != ntohs (gdm->reserved)) || ('\0' != name[name_len - 1]) ) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received GET_DEFAULT for service `%s' from client\n", name); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (subsystem_cfg, name, "DEFAULT_IDENTIFIER", &identifier)) { send_result_code (client, 1, gettext_noop ("no default known")); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } for (ego = ego_head; NULL != ego; ego = ego->next) { if (0 == strcmp (ego->identifier, identifier)) { sdm = create_set_default_message (ego, name); GNUNET_SERVER_notification_context_unicast (nc, client, &sdm->header, GNUNET_NO); GNUNET_free (sdm); GNUNET_SERVER_receive_done (client, GNUNET_OK); GNUNET_free (identifier); return; } } GNUNET_free (identifier); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to find ego `%s'\n", name); send_result_code (client, 1, gettext_noop ("default configured, but ego unknown (internal error)")); GNUNET_SERVER_receive_done (client, GNUNET_OK); }