/** * Callback method used with libcurl * Method is called when libcurl needs to write data during sending * * @param stream pointer where to write data * @param size size of an individual element * @param nmemb count of elements that can be written to the buffer * @param cls destination pointer, passed to the libcurl handle * @return bytes read from stream */ static size_t client_receive (void *stream, size_t size, size_t nmemb, void *cls) { struct Session *s = cls; struct GNUNET_TIME_Absolute now; size_t len = size * nmemb; struct Plugin *plugin = s->plugin; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Client: Received %Zu bytes from peer `%s'\n", len, GNUNET_i2s (&s->target)); now = GNUNET_TIME_absolute_get (); if (now.abs_value < s->next_receive.abs_value) { struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); struct GNUNET_TIME_Relative delta = GNUNET_TIME_absolute_get_difference (now, s->next_receive); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Client: %p No inbound bandwidth available! Next read was delayed for %llu ms\n", s->client_get, delta.rel_value); if (s->recv_wakeup_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (s->recv_wakeup_task); s->recv_wakeup_task = GNUNET_SCHEDULER_NO_TASK; } s->recv_wakeup_task = GNUNET_SCHEDULER_add_delayed (delta, &client_wake_up, s); return CURLPAUSE_ALL; } if (NULL == s->msg_tk) s->msg_tk = GNUNET_SERVER_mst_create (&client_receive_mst_cb, s); GNUNET_SERVER_mst_receive (s->msg_tk, s, stream, len, GNUNET_NO, GNUNET_NO); return len; }
void http_check_ipv6 (struct Plugin *plugin) { struct GNUNET_NETWORK_Handle *desc = NULL; if (plugin->ipv6 == GNUNET_YES) { /* probe IPv6 support */ desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0); if (NULL == desc) { if ((errno == ENOBUFS) || (errno == ENOMEM) || (errno == ENFILE) || (errno == EACCES)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket"); } GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, plugin->name, _ ("Disabling IPv6 since it is not supported on this system!\n")); plugin->ipv6 = GNUNET_NO; } else { GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc)); desc = NULL; } GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Testing IPv6 on this system: %s\n", (plugin->ipv6 == GNUNET_YES) ? "successful" : "failed"); } }
/** * Function that can be used to force the plugin to disconnect * from the given peer and cancel all previous transmissions * (and their continuationc). * * @param cls closure * @param target peer from which to disconnect */ static void http_client_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) { struct HTTP_Client_Plugin *plugin = cls; struct Session *next = NULL; struct Session *pos = NULL; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Transport tells me to disconnect `%s'\n", GNUNET_i2s (target)); next = plugin->head; while (NULL != (pos = next)) { next = pos->next; if (0 == memcmp (target, &pos->target, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Disconnecting session %p to `%pos'\n", pos, GNUNET_i2s (target)); GNUNET_assert (GNUNET_OK == client_disconnect (pos)); } } }
/** * Function to log curl debug messages with GNUNET_log * @param curl handle * @param type curl_infotype * @param data data * @param size size * @param cls closure * @return 0 */ static int client_log (CURL * curl, curl_infotype type, char *data, size_t size, void *cls) { if (type == CURLINFO_TEXT) { char text[size + 2]; memcpy (text, data, size); if (text[size - 1] == '\n') text[size] = '\0'; else { text[size] = '\n'; text[size + 1] = '\0'; } #if BUILD_HTTPS GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-https", "Client: %p - %s", cls, text); #else GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-http", "Client: %p - %s", cls, text); #endif } return 0; }
/** * Clean up the transport testing * @param tth transport testing handle */ void GNUNET_TRANSPORT_TESTING_done (struct GNUNET_TRANSPORT_TESTING_handle *tth) { struct ConnectingContext *cc = tth->cc_head; struct ConnectingContext *ct = NULL; struct PeerContext *p = tth->p_head; struct PeerContext *t = NULL; GNUNET_assert (tth != NULL); while (cc != tth->cc_tail) { ct = cc->next; GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing", "Developer forgot to cancel connect request %p!\n", cc); GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = ct; } while (p != NULL) { t = p->next; GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing", "Developer forgot to stop peer!\n"); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p); p = t; } GNUNET_TESTING_system_destroy (tth->tl_system, GNUNET_YES); GNUNET_free (tth); tth = NULL; }
/** * Exit point from the plugin. * * @param cls the plugin context (as returned by "init") * @return always NULL */ void * libgnunet_plugin_datastore_sqlite_done (void *cls) { char *fn; struct GNUNET_DATASTORE_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "sqlite plugin is done\n"); fn = NULL; if (plugin->drop_on_shutdown) fn = GNUNET_strdup (plugin->fn); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Shutting down database\n"); database_shutdown (plugin); plugin->env = NULL; GNUNET_free (api); if (fn != NULL) { if (0 != UNLINK (fn)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn); GNUNET_free (fn); } GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "sqlite plugin is finished\n"); return NULL; }
static void nat_add_address (void *cls, int add_remove, const struct sockaddr *addr, socklen_t addrlen) { struct Plugin *plugin = cls; struct IPv4HttpAddressWrapper *w_t4 = NULL; struct IPv6HttpAddressWrapper *w_t6 = NULL; int af; af = addr->sa_family; switch (af) { case AF_INET: w_t4 = find_address (plugin, addr, addrlen); if (w_t4 == NULL) { struct sockaddr_in *a4 = (struct sockaddr_in *) addr; w_t4 = GNUNET_malloc (sizeof (struct IPv4HttpAddressWrapper)); memcpy (&w_t4->addr.ipv4_addr, &a4->sin_addr, sizeof (struct in_addr)); w_t4->addr.u4_port = a4->sin_port; GNUNET_CONTAINER_DLL_insert (plugin->ipv4_addr_head, plugin->ipv4_addr_tail, w_t4); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Notifying transport to add IPv4 address `%s'\n", http_plugin_address_to_string (NULL, &w_t4->addr, sizeof (struct IPv4HttpAddress))); plugin->env->notify_address (plugin->env->cls, add_remove, &w_t4->addr, sizeof (struct IPv4HttpAddress)); } break; case AF_INET6: w_t6 = find_address (plugin, addr, addrlen); if (w_t6 == NULL) { w_t6 = GNUNET_malloc (sizeof (struct IPv6HttpAddressWrapper)); struct sockaddr_in6 *a6 = (struct sockaddr_in6 *) addr; memcpy (&w_t6->addr6.ipv6_addr, &a6->sin6_addr, sizeof (struct in6_addr)); w_t6->addr6.u6_port = a6->sin6_port; GNUNET_CONTAINER_DLL_insert (plugin->ipv6_addr_head, plugin->ipv6_addr_tail, w_t6); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Notifying transport to add IPv6 address `%s'\n", http_plugin_address_to_string (NULL, &w_t6->addr6, sizeof (struct IPv6HttpAddress))); plugin->env->notify_address (plugin->env->cls, add_remove, &w_t6->addr6, sizeof (struct IPv6HttpAddress)); } break; default: return; } }
/** * Obtain the location of ".my.cnf". * * @param cfg our configuration * @param section the section * @return NULL on error */ static char * get_my_cnf_path (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section) { char *cnffile; char *home_dir; struct stat st; #ifndef WINDOWS struct passwd *pw; #endif int configured; #ifndef WINDOWS pw = getpwuid (getuid ()); if (!pw) { GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_ERROR, "mysql", "getpwuid"); return NULL; } if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (cfg, section, "CONFIG")) { GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, section, "CONFIG", &cnffile)); configured = GNUNET_YES; } else { home_dir = GNUNET_strdup (pw->pw_dir); GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir); GNUNET_free (home_dir); configured = GNUNET_NO; } #else home_dir = (char *) GNUNET_malloc (_MAX_PATH + 1); plibc_conv_to_win_path ("~/", home_dir); GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir); GNUNET_free (home_dir); configured = GNUNET_NO; #endif GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "mysql", _("Trying to use file `%s' for MySQL configuration.\n"), cnffile); if ((0 != STAT (cnffile, &st)) || (0 != ACCESS (cnffile, R_OK)) || (!S_ISREG (st.st_mode))) { if (configured == GNUNET_YES) GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "mysql", _("Could not access file `%s': %s\n"), cnffile, STRERROR (errno)); GNUNET_free (cnffile); return NULL; } return cnffile; }
/** * Restart the given peer * @param tth testing handle * @param p the peer * @param cfgname the cfg file used to restart * @param restart_cb callback to call when restarted * @param cb_cls callback closure * @return GNUNET_OK in success otherwise GNUNET_SYSERR */ int GNUNET_TRANSPORT_TESTING_restart_peer (struct GNUNET_TRANSPORT_TESTING_handle *tth, struct PeerContext *p, const char *cfgname, GNUNET_TRANSPORT_TESTING_start_cb restart_cb, void *cb_cls) { GNUNET_assert (tth != NULL); GNUNET_assert (p != NULL); GNUNET_assert (NULL != p->peer); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", "Restarting peer %u (`%s')\n", p->no, GNUNET_i2s (&p->id)); /* shutdown */ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", "Stopping peer %u (`%s')\n", p->no, GNUNET_i2s (&p->id)); if (NULL != p->ghh) GNUNET_TRANSPORT_get_hello_cancel (p->ghh); p->ghh = NULL; if (NULL != p->th) GNUNET_TRANSPORT_disconnect (p->th); if (GNUNET_SYSERR == GNUNET_TESTING_peer_stop(p->peer)) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing", "Failed to stop peer %u (`%s')\n", p->no, GNUNET_i2s (&p->id)); return GNUNET_SYSERR; } sleep (5); /* restart */ if (GNUNET_SYSERR == GNUNET_TESTING_peer_start(p->peer)) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing", "Failed to restart peer %u (`%s')\n", p->no, GNUNET_i2s (&p->id)); return GNUNET_SYSERR; } GNUNET_assert (p->th != NULL); GNUNET_assert (p->start_cb == NULL); p->start_cb = restart_cb; p->cb_cls = cb_cls; p->th = GNUNET_TRANSPORT_connect (p->cfg, NULL, p, ¬ify_receive, ¬ify_connect, ¬ify_disconnect); GNUNET_assert (NULL != p->th); p->ghh = GNUNET_TRANSPORT_get_hello (p->th, &get_hello, p); GNUNET_assert (p->ghh != NULL); return GNUNET_OK; }
/** * Connect both PUT and GET connection for a session * * @param s the session to connect * @return GNUNET_OK on success, GNUNET_SYSERR otherwise */ static int client_connect (struct Session *s) { struct HTTP_Client_Plugin *plugin = s->plugin; int res = GNUNET_OK; /* create url */ if (NULL == http_common_plugin_address_to_string (NULL, s->addr, s->addrlen)) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Invalid address peer `%s'\n", GNUNET_i2s (&s->target)); return GNUNET_SYSERR; } GNUNET_asprintf (&s->url, "%s/%s;%u", http_common_plugin_address_to_string (plugin, s->addr, s->addrlen), GNUNET_h2s_full (&plugin->env->my_identity->hashPubKey), plugin->last_tag); plugin->last_tag++; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Initiating outbound session peer `%s' using address `%s'\n", GNUNET_i2s (&s->target), s->url); if ((GNUNET_SYSERR == client_connect_get (s)) || (GNUNET_SYSERR == client_connect_put (s))) { GNUNET_break (0); return GNUNET_SYSERR; } GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Session %p: connected with connections GET %p and PUT %p\n", s, s->client_get, s->client_put); /* Perform connect */ plugin->cur_connections += 2; GNUNET_STATISTICS_set (plugin->env->stats, "# HTTP client connections", plugin->cur_connections, GNUNET_NO); /* Re-schedule since handles have changed */ if (plugin->client_perform_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (plugin->client_perform_task); plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK; } plugin->client_perform_task = GNUNET_SCHEDULER_add_now (client_run, plugin); return res; }
/** * Connect a HTTP put connection * * @param s the session to connect * @return GNUNET_SYSERR for hard failure, GNUNET_OK for ok */ static int client_connect_put (struct Session *s) { CURLMcode mret; /* create put connection */ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, "Session %p : Init PUT handle \n", s); s->client_put = curl_easy_init (); s->put.s = s; s->put.easyhandle = s->client_put; #if VERBOSE_CURL curl_easy_setopt (s->client_put, CURLOPT_VERBOSE, 1L); curl_easy_setopt (s->client_put, CURLOPT_DEBUGFUNCTION, &client_log); curl_easy_setopt (s->client_put, CURLOPT_DEBUGDATA, &s->put); #endif #if BUILD_HTTPS curl_easy_setopt (s->client_put, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); curl_easy_setopt (s->client_put, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt (s->client_put, CURLOPT_SSL_VERIFYHOST, 0); #endif curl_easy_setopt (s->client_put, CURLOPT_URL, s->url); curl_easy_setopt (s->client_put, CURLOPT_UPLOAD, 1L); //curl_easy_setopt (s->client_put, CURLOPT_HEADERFUNCTION, &client_curl_header); //curl_easy_setopt (s->client_put, CURLOPT_WRITEHEADER, ps); curl_easy_setopt (s->client_put, CURLOPT_READFUNCTION, client_send_cb); curl_easy_setopt (s->client_put, CURLOPT_READDATA, s); curl_easy_setopt (s->client_put, CURLOPT_WRITEFUNCTION, client_receive_put); curl_easy_setopt (s->client_put, CURLOPT_WRITEDATA, s); /* No timeout by default, timeout done with session timeout */ curl_easy_setopt (s->client_put, CURLOPT_TIMEOUT, 0); curl_easy_setopt (s->client_put, CURLOPT_PRIVATE, s); curl_easy_setopt (s->client_put, CURLOPT_CONNECTTIMEOUT_MS, (long) HTTP_CLIENT_NOT_VALIDATED_TIMEOUT.rel_value); curl_easy_setopt (s->client_put, CURLOPT_BUFFERSIZE, 2 * GNUNET_SERVER_MAX_MESSAGE_SIZE); #if CURL_TCP_NODELAY curl_easy_setopt (s->client_put, CURLOPT_TCP_NODELAY, 1); #endif mret = curl_multi_add_handle (s->plugin->curl_multi_handle, s->client_put); if (mret != CURLM_OK) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, s->plugin->name, "Session %p : Failed to add PUT handle to multihandle: `%s'\n", s, curl_multi_strerror (mret)); curl_easy_cleanup (s->client_put); s->client_put = NULL; s->put.easyhandle = NULL; s->put.s = NULL; s->put_tmp_disconnected = GNUNET_YES; return GNUNET_SYSERR; } s->put_tmp_disconnected = GNUNET_NO; return GNUNET_OK; }
static void nat_remove_address (void *cls, int add_remove, const struct sockaddr *addr, socklen_t addrlen) { struct Plugin *plugin = cls; struct IPv4HttpAddressWrapper *w_t4 = NULL; struct IPv6HttpAddressWrapper *w_t6 = NULL; int af; af = addr->sa_family; switch (af) { case AF_INET: w_t4 = find_address (plugin, addr, addrlen); if (w_t4 == NULL) return; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Notifying transport to remove IPv4 address `%s'\n", http_plugin_address_to_string (NULL, &w_t4->addr, sizeof (struct IPv4HttpAddress))); plugin->env->notify_address (plugin->env->cls, add_remove, &w_t4->addr, sizeof (struct IPv4HttpAddress)); GNUNET_CONTAINER_DLL_remove (plugin->ipv4_addr_head, plugin->ipv4_addr_tail, w_t4); GNUNET_free (w_t4); break; case AF_INET6: w_t6 = find_address (plugin, addr, addrlen); if (w_t6 == NULL) return; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Notifying transport to remove IPv6 address `%s'\n", http_plugin_address_to_string (NULL, &w_t6->addr6, sizeof (struct IPv6HttpAddress))); plugin->env->notify_address (plugin->env->cls, add_remove, &w_t6->addr6, sizeof (struct IPv6HttpAddress)); GNUNET_CONTAINER_DLL_remove (plugin->ipv6_addr_head, plugin->ipv6_addr_tail, w_t6); GNUNET_free (w_t6); break; default: return; } }
/** * Shutdown database connection and associate data * structures. * @param plugin the plugin context (state for this module) */ static void database_shutdown (struct Plugin *plugin) { int result; #if SQLITE_VERSION_NUMBER >= 3007000 sqlite3_stmt *stmt; #endif if (plugin->delRow != NULL) sqlite3_finalize (plugin->delRow); if (plugin->updPrio != NULL) sqlite3_finalize (plugin->updPrio); if (plugin->updRepl != NULL) sqlite3_finalize (plugin->updRepl); if (plugin->selRepl != NULL) sqlite3_finalize (plugin->selRepl); if (plugin->maxRepl != NULL) sqlite3_finalize (plugin->maxRepl); if (plugin->selExpi != NULL) sqlite3_finalize (plugin->selExpi); if (plugin->selZeroAnon != NULL) sqlite3_finalize (plugin->selZeroAnon); if (plugin->insertContent != NULL) sqlite3_finalize (plugin->insertContent); result = sqlite3_close (plugin->dbh); #if SQLITE_VERSION_NUMBER >= 3007000 if (result == SQLITE_BUSY) { GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite", _ ("Tried to close sqlite without finalizing all prepared statements.\n")); stmt = sqlite3_next_stmt (plugin->dbh, NULL); while (stmt != NULL) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Closing statement %p\n", stmt); result = sqlite3_finalize (stmt); if (result != SQLITE_OK) GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite", "Failed to close statement %p: %d\n", stmt, result); stmt = sqlite3_next_stmt (plugin->dbh, NULL); } result = sqlite3_close (plugin->dbh); } #endif if (SQLITE_OK != result) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close"); GNUNET_free_non_null (plugin->fn); }
/** * Loggging function * * @param curl the curl easy handle * @param type message type * @param data data to log, NOT a 0-terminated string * @param size data length * @param cls the closure * @return always 0 */ static int client_log (CURL *curl, curl_infotype type, const char *data, size_t size, void *cls) { struct ConnectionHandle *ch = cls; const char *ttype = "UNSPECIFIED"; if ((type == CURLINFO_TEXT) || (type == CURLINFO_HEADER_IN) || (type == CURLINFO_HEADER_OUT)) { char text[size + 2]; switch (type) { case CURLINFO_TEXT: ttype = "TEXT"; break; case CURLINFO_HEADER_IN: ttype = "HEADER_IN"; break; case CURLINFO_HEADER_OUT: ttype = "HEADER_OUT"; /* Overhead*/ GNUNET_assert (NULL != ch); GNUNET_assert (NULL != ch->easyhandle); GNUNET_assert (NULL != ch->s); ch->s->overhead += size; break; default: ttype = "UNSPECIFIED"; break; } memcpy (text, data, size); if (text[size - 1] == '\n') text[size] = '\0'; else { text[size] = '\n'; text[size + 1] = '\0'; } #if BUILD_HTTPS GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-https_client", "Connection %p %s: %s", ch->easyhandle, ttype, text); #else GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-http_client", "Connection %p %s: %s", ch->easyhandle, ttype, text); #endif } return 0; }
/** * Exit point from the plugin. * * @param cls api as closure * @return NULL */ void * LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls) { struct GNUNET_TRANSPORT_PluginFunctions *api = cls; struct HTTP_Client_Plugin *plugin = api->cls; struct Session *pos; struct Session *next; if (NULL == api->cls) { /* Stub shutdown */ GNUNET_free (api); return NULL; } GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, _("Shutting down plugin `%s'\n"), plugin->name); next = plugin->head; while (NULL != (pos = next)) { next = pos->next; client_disconnect (pos); } if (GNUNET_SCHEDULER_NO_TASK != plugin->client_perform_task) { GNUNET_SCHEDULER_cancel (plugin->client_perform_task); plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != plugin->curl_multi_handle) { curl_multi_cleanup (plugin->curl_multi_handle); plugin->curl_multi_handle = NULL; } curl_global_cleanup (); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, _("Shutdown for plugin `%s' complete\n"), plugin->name); GNUNET_free (plugin); GNUNET_free (api); return NULL; }
static void try_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ConnectingContext *cc = cls; struct PeerContext *p1 = cc->p1; struct PeerContext *p2 = cc->p2; cc->tct = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; GNUNET_assert (cc != NULL); GNUNET_assert (cc->p1 != NULL); GNUNET_assert (cc->p2 != NULL); char *p2_s = GNUNET_strdup (GNUNET_i2s (&p2->id)); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", "Asking peer %u (`%s') to connect peer %u (`%s'), providing HELLO with %u bytes\n", p1->no, GNUNET_i2s (&p1->id), p2->no, p2_s, GNUNET_HELLO_size (cc->p2->hello)); GNUNET_free (p2_s); GNUNET_TRANSPORT_offer_hello (cc->th_p1, (const struct GNUNET_MessageHeader *) cc-> p2->hello, NULL, NULL); GNUNET_TRANSPORT_try_connect (cc->th_p1, &p2->id, NULL, NULL); /*FIXME TRY_CONNECT change */ cc->tct = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &try_connect, cc); }
static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *p = cls; /* Find PeerContext */ int no = 0; struct PeerContext *p2 = NULL; if (p != NULL) { GNUNET_assert (p->tth != NULL); p2 = find_peer_context (p->tth, peer); no = p->no; } char *p2_s; if (p2 != NULL) GNUNET_asprintf (&p2_s, "%u (`%s')", p2->no, GNUNET_i2s (&p2->id)); else GNUNET_asprintf (&p2_s, "`%s'", GNUNET_i2s (peer)); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", "Peers %s disconnected from peer %u (`%s')\n", p2_s, no, GNUNET_i2s (&p->id)); GNUNET_free (p2_s); if (p == NULL) return; if (p->nd != NULL) p->nd (p->cb_cls, peer); }
/** * Entry point for the plugin. * * @param cls the `struct GNUNET_DATASTORE_PluginEnvironment*` * @return our `struct Plugin *` */ void * libgnunet_plugin_datastore_postgres_init (void *cls) { struct GNUNET_DATASTORE_PluginEnvironment *env = cls; struct GNUNET_DATASTORE_PluginFunctions *api; struct Plugin *plugin; plugin = GNUNET_new (struct Plugin); plugin->env = env; if (GNUNET_OK != init_connection (plugin)) { GNUNET_free (plugin); return NULL; } api = GNUNET_new (struct GNUNET_DATASTORE_PluginFunctions); api->cls = plugin; api->estimate_size = &postgres_plugin_estimate_size; api->put = &postgres_plugin_put; api->update = &postgres_plugin_update; api->get_key = &postgres_plugin_get_key; api->get_replication = &postgres_plugin_get_replication; api->get_expiration = &postgres_plugin_get_expiration; api->get_zero_anonymity = &postgres_plugin_get_zero_anonymity; api->get_keys = &postgres_plugin_get_keys; api->drop = &postgres_plugin_drop; GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "datastore-postgres", _("Postgres database running\n")); return api; }
/** * Get a random item that has expired or has low priority. * Call 'proc' with all values ZERO or NULL if the datastore is empty. * * @param cls closure * @param proc function to call the value (once only). * @param proc_cls closure for proc */ static void sqlite_plugin_get_expiration (void *cls, PluginDatumProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; sqlite3_stmt *stmt; struct GNUNET_TIME_Absolute now; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Getting random block based on expiration and priority order.\n"); now = GNUNET_TIME_absolute_get (); stmt = plugin->selExpi; if (SQLITE_OK != sqlite3_bind_int64 (stmt, 1, now.abs_value)) { LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (stmt)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } execute_get (plugin, stmt, proc, proc_cls); }
/** * Initiate a connection from p1 to p2 by offering p1 p2's HELLO message * * Remarks: start_peer's notify_connect callback can be called before. * * @param tth transport testing handle * @param p1 peer 1 * @param p2 peer 2 * @param cb the callback to call when both peers notified that they are connected * @param cls callback cls * @return a connect request handle */ GNUNET_TRANSPORT_TESTING_ConnectRequest GNUNET_TRANSPORT_TESTING_connect_peers (struct GNUNET_TRANSPORT_TESTING_handle *tth, struct PeerContext *p1, struct PeerContext *p2, GNUNET_TRANSPORT_TESTING_connect_cb cb, void *cls) { GNUNET_assert (tth != NULL); struct ConnectingContext *cc = GNUNET_new (struct ConnectingContext); GNUNET_assert (p1 != NULL); GNUNET_assert (p2 != NULL); cc->p1 = p1; cc->p2 = p2; cc->cb = cb; if (cls != NULL) cc->cb_cls = cls; else cc->cb_cls = cc; cc->th_p1 = p1->th; cc->th_p2 = p2->th; GNUNET_assert (cc->th_p1 != NULL); GNUNET_assert (cc->th_p2 != NULL); GNUNET_CONTAINER_DLL_insert (tth->cc_head, tth->cc_tail, cc); cc->tct = GNUNET_SCHEDULER_add_now (&try_connect, cc); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", "New connect request %p\n", cc); return cc; }
/** * Prepare a statement for running. * * @param mc mysql context * @param sh statement handle to prepare * @return #GNUNET_OK on success */ static int prepare_statement (struct GNUNET_MYSQL_StatementHandle *sh) { struct GNUNET_MYSQL_Context *mc = sh->mc; if (GNUNET_YES == sh->valid) return GNUNET_OK; if ((NULL == mc->dbf) && (GNUNET_OK != iopen (mc))) return GNUNET_SYSERR; sh->statement = mysql_stmt_init (mc->dbf); if (NULL == sh->statement) { GNUNET_MYSQL_statements_invalidate (mc); return GNUNET_SYSERR; } if (0 != mysql_stmt_prepare (sh->statement, sh->query, strlen (sh->query))) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "mysql", "prepare_statement: %s\n", sh->query); LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_stmt_prepare", mc); mysql_stmt_close (sh->statement); sh->statement = NULL; GNUNET_MYSQL_statements_invalidate (mc); return GNUNET_SYSERR; } sh->valid = GNUNET_YES; return GNUNET_OK; }
/** * Entry point for the plugin. * * @param cls the "struct GNUNET_DATASTORE_PluginEnvironment*" * @return our "struct Plugin*" */ void * libgnunet_plugin_datastore_heap_init (void *cls) { struct GNUNET_DATASTORE_PluginEnvironment *env = cls; struct GNUNET_DATASTORE_PluginFunctions *api; struct Plugin *plugin; unsigned long long esize; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (env->cfg, "datastore-heap", "HASHMAPSIZE", &esize)) esize = 128 * 1024; plugin = GNUNET_malloc (sizeof (struct Plugin)); plugin->env = env; plugin->keyvalue = GNUNET_CONTAINER_multihashmap_create (esize, GNUNET_YES); plugin->by_expiration = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); plugin->by_replication = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MAX); api = GNUNET_malloc (sizeof (struct GNUNET_DATASTORE_PluginFunctions)); api->cls = plugin; api->estimate_size = &heap_plugin_estimate_size; api->put = &heap_plugin_put; api->update = &heap_plugin_update; api->get_key = &heap_plugin_get_key; api->get_replication = &heap_plugin_get_replication; api->get_expiration = &heap_plugin_get_expiration; api->get_zero_anonymity = &heap_plugin_get_zero_anonymity; api->drop = &heap_plugin_drop; api->get_keys = &heap_get_keys; GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "heap", _("Heap database running\n")); return api; }
static int client_receive_mst_cb (void *cls, void *client, const struct GNUNET_MessageHeader *message) { struct Session *s = cls; struct GNUNET_TIME_Relative delay; if (GNUNET_YES != exist_session(p, s)) { GNUNET_break (0); return GNUNET_OK; } delay = http_plugin_receive (s, &s->target, message, s, s->addr, s->addrlen); s->next_receive = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), delay); if (GNUNET_TIME_absolute_get ().abs_value < s->next_receive.abs_value) { struct Plugin *plugin = s->plugin; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Client: peer `%s' address `%s' next read delayed for %llu ms\n", GNUNET_i2s (&s->target), GNUNET_a2s (s->addr, s->addrlen), delay); } return GNUNET_OK; }
/** * Entry point for the plugin. * * @param cls the "struct GNUNET_DATASTORE_PluginEnvironment*" * @return NULL on error, othrewise the plugin context */ void * libgnunet_plugin_datastore_sqlite_init (void *cls) { static struct Plugin plugin; struct GNUNET_DATASTORE_PluginEnvironment *env = cls; struct GNUNET_DATASTORE_PluginFunctions *api; if (plugin.env != NULL) return NULL; /* can only initialize once! */ memset (&plugin, 0, sizeof (struct Plugin)); plugin.env = env; if (GNUNET_OK != database_setup (env->cfg, &plugin)) { database_shutdown (&plugin); return NULL; } api = GNUNET_malloc (sizeof (struct GNUNET_DATASTORE_PluginFunctions)); api->cls = &plugin; api->estimate_size = &sqlite_plugin_estimate_size; api->put = &sqlite_plugin_put; api->update = &sqlite_plugin_update; api->get_key = &sqlite_plugin_get_key; api->get_replication = &sqlite_plugin_get_replication; api->get_expiration = &sqlite_plugin_get_expiration; api->get_zero_anonymity = &sqlite_plugin_get_zero_anonymity; api->get_keys = &sqlite_plugin_get_keys; api->drop = &sqlite_plugin_drop; GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "sqlite", _("Sqlite database running\n")); return api; }
struct Session * lookup_session_old (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target, struct Session *session, const void *addr, size_t addrlen, int force_address) { struct Session *t; int e_peer; int e_addr; for (t = plugin->head; NULL != t; t = t->next) { #if 0 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, "Comparing peer `%s' address `%s' len %i session %p to \n", GNUNET_i2s (target), GNUNET_a2s (addr, addrlen), addrlen, session); GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, "peer `%s' address `%s' len %i session %p \n\n", GNUNET_i2s (&t->target), GNUNET_a2s (t->addr, t->addrlen), t->addrlen, t); GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, "memcmp %i \n", memcmp (addr, t->addr, addrlen)); #endif e_peer = GNUNET_NO; e_addr = GNUNET_NO; if (0 == memcmp (target, &t->target, sizeof (struct GNUNET_PeerIdentity))) { e_peer = GNUNET_YES; if ( (addrlen == t->addrlen) && (0 == memcmp (addr, t->addr, addrlen)) ) e_addr = GNUNET_YES; if ( (t == session) && (t->addrlen == session->addrlen) && (0 == memcmp (session->addr, t->addr, t->addrlen)) ) e_addr = GNUNET_YES; } if ( ((e_peer == GNUNET_YES) && (force_address == GNUNET_NO)) || ((e_peer == GNUNET_YES) && (force_address == GNUNET_YES) && (e_addr == GNUNET_YES)) || ((e_peer == GNUNET_YES) && (force_address == GNUNET_SYSERR)) ) return t; } return NULL; }
/** * shutdown the given peer * @param tth testing handle * @param p the peer */ void GNUNET_TRANSPORT_TESTING_stop_peer (struct GNUNET_TRANSPORT_TESTING_handle *tth, struct PeerContext *p) { GNUNET_assert (p != NULL); if (p->ghh != NULL) { GNUNET_TRANSPORT_get_hello_cancel (p->ghh); p->ghh = NULL; } if (p->th != NULL) { GNUNET_TRANSPORT_disconnect (p->th); p->th = NULL; } if (p->peer != NULL) { if (GNUNET_OK != GNUNET_TESTING_peer_stop (p->peer)) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", "Testing lib failed to stop peer %u (`%s') \n", p->no, GNUNET_i2s (&p->id)); } GNUNET_TESTING_peer_destroy (p->peer); p->peer = NULL; } if (p->hello != NULL) { GNUNET_free (p->hello); p->hello = NULL; } if (p->cfg != NULL) { GNUNET_CONFIGURATION_destroy (p->cfg); p->cfg = NULL; } GNUNET_CONTAINER_DLL_remove (tth->p_head, tth->p_tail, p); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", "Peer %u (`%s') stopped \n", p->no, GNUNET_i2s (&p->id)); GNUNET_free (p); }
/** * Drop database. * * @param cls closure with the `struct Plugin *` */ static void postgres_plugin_drop (void *cls) { struct Plugin *plugin = cls; if (GNUNET_OK != GNUNET_POSTGRES_exec (plugin->dbh, "DROP TABLE gn090")) GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "postgres", _("Failed to drop table from database.\n")); }
/** * Callback method used with libcurl * Method is called when libcurl needs to read data during sending * * @param stream pointer where to write data * @param size size of an individual element * @param nmemb count of elements that can be written to the buffer * @param cls source pointer, passed to the libcurl handle * @return bytes written to stream, returning 0 will terminate connection! */ static size_t client_send_cb (void *stream, size_t size, size_t nmemb, void *cls) { struct Session *s = cls; struct Plugin *plugin = s->plugin; struct HTTP_Message *msg = s->msg_head; size_t len; if (GNUNET_YES != exist_session(plugin, s)) { GNUNET_break (0); return 0; } if (NULL == msg) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Client: %p Nothing to send! Suspending PUT handle!\n", s->client_put); s->client_put_paused = GNUNET_YES; return CURL_READFUNC_PAUSE; } /* data to send */ GNUNET_assert (msg->pos < msg->size); /* calculate how much fits in buffer */ len = GNUNET_MIN (msg->size - msg->pos, size * nmemb); memcpy (stream, &msg->buf[msg->pos], len); msg->pos += len; if (msg->pos == msg->size) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Client: %p Message with %u bytes sent, removing message from queue\n", s->client_put, msg->size, msg->pos); /* Calling transmit continuation */ GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg); if (NULL != msg->transmit_cont) msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_OK); GNUNET_free (msg); } return len; }
/** * Function called to notify a client about the connection * begin ready to queue more data. "buf" will be * NULL and "size" zero if the connection was closed for * writing in the meantime. * * @param cls closure * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t core_mq_ntr (void *cls, size_t size, void *buf) { struct GNUNET_MQ_Handle *mq = cls; struct CoreMQState *mqs = GNUNET_MQ_impl_state (mq); const struct GNUNET_MessageHeader *mh = GNUNET_MQ_impl_current (mq); size_t msg_size = ntohs (mh->size); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "core-mq", "ntr called (size %u, type %u)\n", msg_size, ntohs (mh->type)); mqs->th = NULL; if (NULL == buf) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "core-mq", "send error\n"); GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_WRITE); return 0; } memcpy (buf, mh, msg_size); GNUNET_MQ_impl_send_continue (mq); return msg_size; }
/** * Store an item in the datastore. * * @param cls closure with the `struct Plugin` * @param key key for the item * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param replication replication-level for the content * @param expiration expiration time for the content * @param cont continuation called with success or failure status * @param cont_cls continuation closure */ static void postgres_plugin_put (void *cls, const struct GNUNET_HashCode *key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, PluginPutCont cont, void *cont_cls) { struct Plugin *plugin = cls; uint32_t utype = type; struct GNUNET_HashCode vhash; PGresult *ret; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint32 (&replication), GNUNET_PQ_query_param_uint32 (&utype), GNUNET_PQ_query_param_uint32 (&priority), GNUNET_PQ_query_param_uint32 (&anonymity), GNUNET_PQ_query_param_absolute_time (&expiration), GNUNET_PQ_query_param_auto_from_type (key), GNUNET_PQ_query_param_auto_from_type (&vhash), GNUNET_PQ_query_param_fixed_size (data, size), GNUNET_PQ_query_param_end }; GNUNET_CRYPTO_hash (data, size, &vhash); ret = GNUNET_PQ_exec_prepared (plugin->dbh, "put", params); if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "PQexecPrepared", "put")) { cont (cont_cls, key, size, GNUNET_SYSERR, _("Postgress exec failure")); return; } PQclear (ret); plugin->env->duc (plugin->env->cls, size + GNUNET_DATASTORE_ENTRY_OVERHEAD); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "datastore-postgres", "Stored %u bytes in database\n", (unsigned int) size); cont (cont_cls, key, size, GNUNET_OK, NULL); }