/**
 * 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;
  }

}
Beispiel #8
0
/**
 * 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,
                                    &notify_receive,
                                    &notify_connect,
                                    &notify_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);
}
Beispiel #18
0
/**
 * 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;
}
Beispiel #21
0
/**
 * 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);
}
Beispiel #27
0
/**
 * 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;
}
Beispiel #29
0
/**
 * 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;
}
Beispiel #30
0
/**
 * 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);
}