/** * We've validated the hash of the file we're about to index. Signal * success to the client and update our internal data structures. * * @param ii the index info entry for the request */ static void signal_index_ok (struct IndexInfo *ii) { struct IndexInfo *ir; if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_put (ifm, &ii->file_id, ii, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) { ir = GNUNET_CONTAINER_multihashmap_get (ifm, &ii->file_id); GNUNET_assert (NULL != ir); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Index request received for file `%s' is already indexed as `%s'. Permitting anyway.\n"), ii->filename, ir->filename); GNUNET_SERVER_transmit_context_append_data (ii->tc, NULL, 0, GNUNET_MESSAGE_TYPE_FS_INDEX_START_OK); GNUNET_SERVER_transmit_context_run (ii->tc, GNUNET_TIME_UNIT_MINUTES); GNUNET_free (ii); return; } GNUNET_CONTAINER_DLL_insert (indexed_files_head, indexed_files_tail, ii); write_index_list (); GNUNET_SERVER_transmit_context_append_data (ii->tc, NULL, 0, GNUNET_MESSAGE_TYPE_FS_INDEX_START_OK); GNUNET_SERVER_transmit_context_run (ii->tc, GNUNET_TIME_UNIT_MINUTES); ii->tc = NULL; }
/** * Handle INDEX_LIST_GET-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ void GNUNET_FS_handle_index_list_get (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct GNUNET_SERVER_TransmitContext *tc; struct IndexInfoMessage *iim; char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN; size_t slen; const char *fn; struct IndexInfo *pos; tc = GNUNET_SERVER_transmit_context_create (client); iim = (struct IndexInfoMessage *) buf; for (pos = indexed_files_head; NULL != pos; pos = pos->next) { fn = pos->filename; slen = strlen (fn) + 1; if (slen + sizeof (struct IndexInfoMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); break; } iim->header.type = htons (GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_ENTRY); iim->header.size = htons (slen + sizeof (struct IndexInfoMessage)); iim->reserved = 0; iim->file_id = pos->file_id; memcpy (&iim[1], fn, slen); GNUNET_SERVER_transmit_context_append_message (tc, &iim->header); } GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_END); GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_MINUTES); }
/** * Convert a string to an IP address. * * @param client where to send the IP address * @param hostname the hostname to resolve * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any" */ static void get_ip_from_hostname (struct GNUNET_SERVER_Client *client, const char *hostname, int af) { int ret; struct GNUNET_SERVER_TransmitContext *tc; tc = GNUNET_SERVER_transmit_context_create (client); ret = GNUNET_NO; #if HAVE_GETADDRINFO if (ret == GNUNET_NO) ret = getaddrinfo_resolve (tc, hostname, af); #endif #if HAVE_GETHOSTBYNAME2 if (ret == GNUNET_NO) ret = gethostbyname2_resolve (tc, hostname, af); #endif #if HAVE_GETHOSTBYNAME if ((ret == GNUNET_NO) && ((af == AF_UNSPEC) || (af == PF_INET))) gethostbyname_resolve (tc, hostname); #endif GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); }
/** * Client asked to resolve an address. Process the request. * * @param cls unused * @param client the client * @param message the resolution request */ static void clients_handle_address_to_string (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct AddressLookupMessage *alum; struct GNUNET_TRANSPORT_PluginFunctions *papi; const char *plugin_name; const char *address; uint32_t address_len; uint16_t size; struct GNUNET_SERVER_TransmitContext *tc; struct AddressToStringContext *actx; struct GNUNET_TIME_Relative rtimeout; int32_t numeric; size = ntohs (message->size); if (size < sizeof (struct AddressLookupMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } alum = (const struct AddressLookupMessage *) message; address_len = ntohs (alum->addrlen); if (size <= sizeof (struct AddressLookupMessage) + address_len) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } address = (const char *) &alum[1]; plugin_name = (const char *) &address[address_len]; if ('\0' != plugin_name[size - sizeof (struct AddressLookupMessage) - address_len - 1]) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } rtimeout = GNUNET_TIME_relative_ntoh (alum->timeout); numeric = ntohs (alum->numeric_only); tc = GNUNET_SERVER_transmit_context_create (client); papi = GST_plugins_printer_find (plugin_name); if (NULL == papi) { GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY); GNUNET_SERVER_transmit_context_run (tc, rtimeout); return; } actx = GNUNET_new (struct AddressToStringContext); actx->tc = tc; GNUNET_CONTAINER_DLL_insert (a2s_head, a2s_tail, actx); GNUNET_SERVER_disable_receive_done_warning (client); papi->address_pretty_printer (papi->cls, plugin_name, address, address_len, numeric, rtimeout, &transmit_address_to_client, actx); }
/** * Handle GET-ALL-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_get_all (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct GNUNET_SERVER_TransmitContext *tc; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s' message received\n", "GET_ALL"); tc = GNUNET_SERVER_transmit_context_create (client); GNUNET_CONTAINER_multihashmap_iterate (hostmap, &add_to_tc, tc); GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END); GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); }
/** * Take the given address and append it to the set of results sent back to * the client. * * @param cls the transmission context used ('struct GNUNET_SERVER_TransmitContext*') * @param buf text to transmit */ static void transmit_address_to_client (void *cls, const char *buf) { struct AddressToStringContext *actx = cls; if (NULL == buf) { GNUNET_SERVER_transmit_context_append_data (actx->tc, NULL, 0, GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY); GNUNET_SERVER_transmit_context_run (actx->tc, GNUNET_TIME_UNIT_FOREVER_REL); GNUNET_CONTAINER_DLL_remove (a2s_head, a2s_tail, actx); GNUNET_free (actx); return; } GNUNET_SERVER_transmit_context_append_data (actx->tc, buf, strlen (buf) + 1, GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY); }
/** * Handle GET-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_get (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct ListPeerMessage *lpm; struct GNUNET_SERVER_TransmitContext *tc; lpm = (const struct ListPeerMessage *) message; GNUNET_break (0 == ntohl (lpm->reserved)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s' message received for peer `%4s'\n", "GET", GNUNET_i2s (&lpm->peer)); tc = GNUNET_SERVER_transmit_context_create (client); GNUNET_CONTAINER_multihashmap_get_multiple (hostmap, &lpm->peer.hashPubKey, &add_to_tc, tc); GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END); GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); }
/** * Handle UNINDEX-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ void GNUNET_FS_handle_unindex (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct UnindexMessage *um; struct IndexInfo *pos; struct GNUNET_SERVER_TransmitContext *tc; int found; um = (const struct UnindexMessage *) message; if (0 != um->reserved) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } found = GNUNET_NO; for (pos = indexed_files_head; NULL != pos; pos = pos->next) { if (0 == memcmp (&pos->file_id, &um->file_id, sizeof (struct GNUNET_HashCode))) { GNUNET_CONTAINER_DLL_remove (indexed_files_head, indexed_files_tail, pos); GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (ifm, &pos->file_id, pos)); GNUNET_free (pos); found = GNUNET_YES; break; } } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client requested unindexing of file `%s': %s\n", GNUNET_h2s (&um->file_id), found ? "found" : "not found"); if (GNUNET_YES == found) write_index_list (); tc = GNUNET_SERVER_transmit_context_create (client); GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, GNUNET_MESSAGE_TYPE_FS_UNINDEX_OK); GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_MINUTES); }
/** * Function called once the hash computation over an * indexed file has completed. * * @param cls closure, our publishing context * @param res resulting hash, NULL on error */ static void hash_for_index_val (void *cls, const struct GNUNET_HashCode * res) { struct IndexInfo *ii = cls; ii->fhc = NULL; if ((res == NULL) || (0 != memcmp (res, &ii->file_id, sizeof (struct GNUNET_HashCode)))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Hash mismatch trying to index file `%s' which has hash `%s'\n"), ii->filename, GNUNET_h2s (res)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Wanted `%s'\n", GNUNET_h2s (&ii->file_id)); GNUNET_SERVER_transmit_context_append_data (ii->tc, NULL, 0, GNUNET_MESSAGE_TYPE_FS_INDEX_START_FAILED); GNUNET_SERVER_transmit_context_run (ii->tc, GNUNET_TIME_UNIT_MINUTES); GNUNET_free (ii); return; } signal_index_ok (ii); }
/** * Get an IP address as a string (works for both IPv4 and IPv6). Note * that the resolution happens asynchronously and that the first call * may not immediately result in the FQN (but instead in a * human-readable IP address). * * @param client handle to the client making the request (for sending the reply) * @param af AF_INET or AF_INET6 * @param ip `struct in_addr` or `struct in6_addr` */ static void get_ip_as_string (struct GNUNET_SERVER_Client *client, int af, const void *ip) { struct IPCache *pos; struct IPCache *next; struct GNUNET_TIME_Absolute now; struct GNUNET_SERVER_TransmitContext *tc; size_t ip_len; struct in6_addr ix; switch (af) { case AF_INET: ip_len = sizeof (struct in_addr); break; case AF_INET6: ip_len = sizeof (struct in6_addr); break; default: GNUNET_assert (0); } now = GNUNET_TIME_absolute_get (); next = cache_head; while ( (NULL != (pos = next)) && ( (pos->af != af) || (pos->ip_len != ip_len) || (0 != memcmp (pos->ip, ip, ip_len))) ) { next = pos->next; if (GNUNET_TIME_absolute_get_duration (pos->last_request).rel_value_us < 60 * 60 * 1000 * 1000LL) { GNUNET_CONTAINER_DLL_remove (cache_head, cache_tail, pos); GNUNET_free_non_null (pos->addr); GNUNET_free (pos); continue; } } if (NULL != pos) { if ( (1 == inet_pton (af, pos->ip, &ix)) && (GNUNET_TIME_absolute_get_duration (pos->last_request).rel_value_us > 120 * 1000 * 1000LL) ) { /* try again if still numeric AND 2 minutes have expired */ GNUNET_free_non_null (pos->addr); pos->addr = NULL; cache_resolve (pos); pos->last_request = now; } } else { pos = GNUNET_malloc (sizeof (struct IPCache) + ip_len); pos->ip = &pos[1]; memcpy (&pos[1], ip, ip_len); pos->last_request = now; pos->last_refresh = now; pos->ip_len = ip_len; pos->af = af; GNUNET_CONTAINER_DLL_insert (cache_head, cache_tail, pos); cache_resolve (pos); } tc = GNUNET_SERVER_transmit_context_create (client); if (NULL != pos->addr) GNUNET_SERVER_transmit_context_append_data (tc, pos->addr, strlen (pos->addr) + 1, GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reverse lookup failed\n"); GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); }
/** * Client asked to obtain information about a specific or all validation * processes * * @param cls unused * @param client the client * @param message the peer address information request */ static void clients_handle_monitor_validation (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { static struct GNUNET_PeerIdentity all_zeros; struct GNUNET_SERVER_TransmitContext *tc; struct PeerMonitorMessage *msg; struct IterationContext pc; if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if (ntohs (message->size) != sizeof (struct ValidationMonitorMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (struct PeerMonitorMessage *) message; if ( (GNUNET_YES != ntohl (msg->one_shot)) && (NULL != lookup_monitoring_client (val_monitoring_clients_head, client)) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "ServerClient %p tried to start monitoring twice\n", client); GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_SERVER_disable_receive_done_warning (client); pc.tc = tc = GNUNET_SERVER_transmit_context_create (client); /* Send initial list */ if (0 == memcmp (&msg->peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity))) { /* iterate over all neighbours */ pc.all = GNUNET_YES; pc.id = msg->peer; } else { /* just return one neighbour */ pc.all = GNUNET_NO; pc.id = msg->peer; } GST_validation_iterate (&send_validation_information, &pc); if (GNUNET_YES != ntohl (msg->one_shot)) { setup_val_monitoring_client (client, &msg->peer); } else { GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE); } GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); }