/**
 * Iterate over all nodes in the tree.
 *
 * @param tree Tree to use..
 * @param cb Callback to call over each child.
 * @param cb_cls Closure for @c cb.
 *
 * TODO: recursive implementation? (s/heap/stack/g)
 */
void
tree_iterate_all (struct MeshTunnelTree *tree,
                  MeshWholeTreeCallback cb,
                  void *cb_cls)
{
  struct MeshTunnelTreeNode *parent;
  struct MeshTunnelTreeNode *n;
  struct MeshTreePendingNode *head;
  struct MeshTreePendingNode *tail;
  struct MeshTreePendingNode *pending;

  cb (cb_cls, tree->root->peer, 0);
  pending = GNUNET_malloc (sizeof (struct MeshTreePendingNode));
  pending->node = tree->root;
  head = tail = NULL;
  GNUNET_CONTAINER_DLL_insert (head, tail, pending);

  while (NULL != head)
  {
    pending = head;
    parent = pending->node;
    GNUNET_CONTAINER_DLL_remove (head, tail, pending);
    GNUNET_free (pending);
    for (n = parent->children_head; NULL != n; n = n->next)
    {
      cb (cb_cls, n->peer, parent->peer);
      pending = GNUNET_malloc (sizeof (struct MeshTreePendingNode));
      pending->node = n;
      /* Insert_tail: breadth first, Insert: depth first */
      GNUNET_CONTAINER_DLL_insert (head, tail, pending);
    }
  }
}
/**
 * Notifies a tree that a connection it might be using is broken.
 * Marks all peers down the paths as disconnected and notifies the client.
 *
 * @param t Tree to use.
 * @param p1 Short id of one of the peers (order unimportant)
 * @param p2 Short id of one of the peers (order unimportant)
 * @param cb Function to call for every peer that is marked as disconnected.
 * @param cbcls Closure for cb.
 *
 * @return Short ID of the first disconnected peer in the tree.
 */
GNUNET_PEER_Id
tree_notify_connection_broken (struct MeshTunnelTree *t, GNUNET_PEER_Id p1,
                               GNUNET_PEER_Id p2, MeshTreeCallback cb,
                               void *cbcls)
{
  struct MeshTunnelTreeNode *n;
  struct MeshTunnelTreeNode *c;

  n = tree_find_peer (t, p1);
  if (NULL == n)
    return 0;
  if (NULL != n->parent && n->parent->peer == p2)
  {
    tree_mark_peers_disconnected (t, n, cb, cbcls);
    GNUNET_CONTAINER_DLL_remove (n->parent->children_head,
                                 n->parent->children_tail, n);
    GNUNET_CONTAINER_DLL_insert (t->disconnected_head, t->disconnected_tail, n);
    return p1;
  }
  for (c = n->children_head; NULL != c; c = c->next)
  {
    if (c->peer == p2)
    {
      tree_mark_peers_disconnected (t, c, cb, cbcls);
      GNUNET_CONTAINER_DLL_remove (n->children_head, n->children_tail, c);
      GNUNET_CONTAINER_DLL_insert (t->disconnected_head, t->disconnected_tail,
                                   c);
      return p2;
    }
  }
  return 0;
}
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;
  }

}
Example #4
0
/**
 * Start monitoring the local DHT service.
 *
 * @param handle Handle to the DHT service.
 * @param type Type of blocks that are of interest.
 * @param key Key of data of interest, NULL for all.
 * @param get_cb Callback to process monitored get messages.
 * @param get_resp_cb Callback to process monitored get response messages.
 * @param put_cb Callback to process monitored put messages.
 * @param cb_cls Closure for cb.
 *
 * @return Handle to stop monitoring.
 */
struct GNUNET_DHT_MonitorHandle *
GNUNET_DHT_monitor_start (struct GNUNET_DHT_Handle *handle,
                          enum GNUNET_BLOCK_Type type,
                          const GNUNET_HashCode *key,
                          GNUNET_DHT_MonitorGetCB get_cb,
                          GNUNET_DHT_MonitorGetRespCB get_resp_cb,
                          GNUNET_DHT_MonitorPutCB put_cb,
                          void *cb_cls)
{
  struct GNUNET_DHT_MonitorHandle *h;
  struct GNUNET_DHT_MonitorStartStopMessage *m;
  struct PendingMessage *pending;

  h = GNUNET_malloc (sizeof (struct GNUNET_DHT_MonitorHandle));
  GNUNET_CONTAINER_DLL_insert(handle->monitor_head, handle->monitor_tail, h);

  h->get_cb = get_cb;
  h->get_resp_cb = get_resp_cb;
  h->put_cb = put_cb;
  h->cb_cls = cb_cls;
  h->type = type;
  h->dht_handle = handle;
  if (NULL != key)
  {
    h->key = GNUNET_malloc (sizeof(GNUNET_HashCode));
    memcpy (h->key, key, sizeof(GNUNET_HashCode));
  }

  pending = GNUNET_malloc (sizeof (struct GNUNET_DHT_MonitorStartStopMessage) +
                           sizeof (struct PendingMessage));
  m = (struct GNUNET_DHT_MonitorStartStopMessage *) &pending[1];
  pending->msg = &m->header;
  pending->handle = handle;
  pending->free_on_send = GNUNET_YES;
  m->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_MONITOR_START);
  m->header.size = htons (sizeof (struct GNUNET_DHT_MonitorStartStopMessage));
  m->type = htonl(type);
  m->get = htons(NULL != get_cb);
  m->get_resp = htons(NULL != get_resp_cb);
  m->put = htons(NULL != put_cb);
  if (NULL != key) {
    m->filter_key = htons(1);
    memcpy (&m->key, key, sizeof(GNUNET_HashCode));
  }
  GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail,
                               pending);
  pending->in_pending_queue = GNUNET_YES;
  process_pending_messages (handle);

  return h;
}
Example #5
0
/**
 * Try again to connect to the identity service.
 *
 * @param cls handle to the identity service.
 * @param tc scheduler context
 */
static void
reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct GNUNET_IDENTITY_Handle *h = cls;
  struct GNUNET_IDENTITY_Operation *op;
  struct GNUNET_MessageHeader msg;

  h->reconnect_task = NULL;
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Connecting to identity service.\n");
  GNUNET_assert (NULL == h->client);
  h->client = GNUNET_CLIENT_connect ("identity", h->cfg);
  GNUNET_assert (NULL != h->client);
  if ( (NULL == h->op_head) ||
       (GNUNET_MESSAGE_TYPE_IDENTITY_START != ntohs (h->op_head->msg->type)) )
  {
    op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Operation) +
			sizeof (struct GNUNET_MessageHeader));
    op->h = h;
    op->msg = (const struct GNUNET_MessageHeader *) &op[1];
    msg.size = htons (sizeof (msg));
    msg.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_START);
    memcpy (&op[1], &msg, sizeof (msg));
    GNUNET_CONTAINER_DLL_insert (h->op_head,
				 h->op_tail,
				 op);
  }
  transmit_next (h);
  GNUNET_assert (NULL != h->th);
}
static int
iface_proc (void *cls, const char *name, int isDefault,
            const struct sockaddr *addr, const struct sockaddr *broadcast_addr,
            const struct sockaddr *netmask, socklen_t addrlen)
{
  struct Plugin *plugin = cls;

  if (addr != NULL)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "address %s for interface %s %p\n ",
                GNUNET_a2s (addr, addrlen), name, addr);
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "broadcast address %s for interface %s %p\n ",
                GNUNET_a2s (broadcast_addr, addrlen), name, broadcast_addr);
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "netmask %s for interface %s %p\n ",
                GNUNET_a2s (netmask, addrlen), name, netmask);

    /* Collecting broadcast addresses */
    if (broadcast_addr != NULL)
    {
      struct BroadcastAddress *ba =
          GNUNET_malloc (sizeof (struct BroadcastAddress));
      ba->addr = GNUNET_malloc (addrlen);
      memcpy (ba->addr, broadcast_addr, addrlen);
      ba->addrlen = addrlen;
      GNUNET_CONTAINER_DLL_insert (plugin->ipv4_broadcast_head,
                                   plugin->ipv4_broadcast_tail, ba);
    }
  }
  return GNUNET_OK;
}
/**
 * Store an item in the datastore.
 *
 * @param cls closure
 * @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 msg set to error message
 * @return GNUNET_OK on success
 */
static int
heap_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, char **msg)
{
  struct Plugin *plugin = cls;
  struct Value *value;

  value = GNUNET_malloc (sizeof (struct Value) + size);
  value->key = *key;
  value->data = &value[1];
  value->expire_heap = GNUNET_CONTAINER_heap_insert (plugin->by_expiration,
						     value,
						     expiration.abs_value);
  value->replication_heap = GNUNET_CONTAINER_heap_insert (plugin->by_replication,
							  value,
							  replication);
  value->expiration = expiration;
  if (0 == anonymity)
  {
    struct ZeroAnonByType *zabt;

    for (zabt = plugin->zero_head; NULL != zabt; zabt = zabt->next)
      if (zabt->type == type)
	break;
    if (NULL == zabt)
    {
      zabt = GNUNET_malloc (sizeof (struct ZeroAnonByType));
      zabt->type = type;
      GNUNET_CONTAINER_DLL_insert (plugin->zero_head,
				   plugin->zero_tail,
				   zabt);
    }
    if (zabt->array_size == zabt->array_pos)
    {
      GNUNET_array_grow (zabt->array,
			 zabt->array_size,
			 zabt->array_size * 2 + 4);
    }
    value->zero_anon_offset = zabt->array_pos;
    zabt->array[zabt->array_pos++] = value;
  }
  value->size = size;
  value->priority = priority;
  value->anonymity = anonymity;
  value->replication = replication;
  value->type = type;
  memcpy (&value[1], data, size);
  GNUNET_CONTAINER_multihashmap_put (plugin->keyvalue,
				     &value->key,
				     value,
				     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  plugin->size += size;
  return GNUNET_OK;
}
/**
 * Add or remove an address from this peer's HELLO message.
 *
 * @param addremove GNUNET_YES to add, GNUNET_NO to remove
 * @param address address to add or remove
 */
void
GST_hello_modify_addresses (int addremove,
                            const struct GNUNET_HELLO_Address *address)
{
  struct OwnAddressList *al;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              (addremove ==
               GNUNET_YES) ? "Adding `%s' to the set of our addresses\n" :
              "Removing `%s' from the set of our addresses\n",
              GST_plugins_a2s (address));
  GNUNET_assert (address != NULL);
  if (GNUNET_NO == addremove)
  {
    for (al = oal_head; al != NULL; al = al->next)
      if (0 == GNUNET_HELLO_address_cmp (address, al->address))
      {
        GNUNET_CONTAINER_DLL_remove (oal_head, oal_tail, al);
        GNUNET_HELLO_address_free (al->address);
        GNUNET_free (al);
        refresh_hello ();
        return;
      }
    /* address to be removed not found!? */
    GNUNET_break (0);
    return;
  }
  al = GNUNET_malloc (sizeof (struct OwnAddressList));
  GNUNET_CONTAINER_DLL_insert (oal_head, oal_tail, al);
  al->address = GNUNET_HELLO_address_copy (address);
  refresh_hello ();
}
/**
 * Handler for monitor start messages
 *
 * @param cls closure for the service
 * @param client the client we received this message from
 * @param message the actual message received
 *
 */
static void
handle_dht_local_monitor (void *cls, struct GNUNET_SERVER_Client *client,
                          const struct GNUNET_MessageHeader *message)
{
  struct ClientMonitorRecord *r;
  const struct GNUNET_DHT_MonitorStartStopMessage *msg;

  msg = (struct GNUNET_DHT_MonitorStartStopMessage *) message;
  r = GNUNET_new (struct ClientMonitorRecord);

  r->client = find_active_client(client);
  r->type = ntohl(msg->type);
  r->get = ntohs(msg->get);
  r->get_resp = ntohs(msg->get_resp);
  r->put = ntohs(msg->put);
  if (0 == ntohs(msg->filter_key))
      r->key = NULL;
  else
  {
    r->key = GNUNET_new (struct GNUNET_HashCode);
    memcpy (r->key, &msg->key, sizeof (struct GNUNET_HashCode));
  }
  GNUNET_CONTAINER_DLL_insert (monitor_head, monitor_tail, r);
  GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
/**
 * 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;
}
/**
 * Transmit the given message to the client.
 *
 * @param client target of the message
 * @param msg message to transmit, will be freed!
 */
static void
transmit (struct GNUNET_SERVER_Client *client, struct GNUNET_MessageHeader *msg)
{
  struct TransmitCallbackContext *tcc;

  if (GNUNET_YES == cleaning_done)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                _("Shutdown in progress, aborting transmission.\n"));
    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
    GNUNET_free (msg);
    return;
  }
  tcc = GNUNET_new (struct TransmitCallbackContext);
  tcc->msg = msg;
  tcc->client = client;
  if (NULL ==
      (tcc->th =
       GNUNET_SERVER_notify_transmit_ready (client, ntohs (msg->size),
                                            GNUNET_TIME_UNIT_FOREVER_REL,
                                            &transmit_callback, tcc)))
  {
    GNUNET_break (0);
    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
    GNUNET_free (msg);
    GNUNET_free (tcc);
    return;
  }
  GNUNET_SERVER_client_keep (client);
  GNUNET_CONTAINER_DLL_insert (tcc_head, tcc_tail, tcc);
}
Example #12
0
/**
 * Process the given file from the "EGODIR".  Parses the file
 * and creates the respective 'struct Ego' in memory.
 *
 * @param cls NULL
 * @param filename name of the file to parse
 * @return #GNUNET_OK to continue to iterate,
 *  #GNUNET_NO to stop iteration with no error,
 *  #GNUNET_SYSERR to abort iteration with error!
 */
static int
process_ego_file (void *cls,
		  const char *filename)
{
  struct Ego *ego;
  const char *fn;

  fn = strrchr (filename, (int) DIR_SEPARATOR);
  if (NULL == fn)
  {
    GNUNET_break (0);
    return GNUNET_OK;
  }
  ego = GNUNET_new (struct Ego);
  ego->pk = GNUNET_CRYPTO_ecdsa_key_create_from_file (filename);
  if (NULL == ego->pk)
  {
    GNUNET_free (ego);
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                _("Failed to parse ego information in `%s'\n"),
                filename);
    return GNUNET_OK;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
	      "Loaded ego `%s'\n",
	      fn + 1);
  ego->identifier = GNUNET_strdup (fn + 1);
  GNUNET_CONTAINER_DLL_insert (ego_head,
			       ego_tail,
			       ego);
  return GNUNET_OK;
}
/**
 * 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;
}
/**
 * Queue a request from a client for transmission to a particular peer.
 *
 * @param car request to queue; this handle is then shared between
 *         the caller (CLIENTS subsystem) and SESSIONS and must not
 *         be released by either until either #GSC_SESSIONS_dequeue(),
 *         #GSC_SESSIONS_transmit() or #GSC_CLIENTS_failed()
 *         have been invoked on it
 */
void
GSC_SESSIONS_queue_request (struct GSC_ClientActiveRequest *car)
{
  struct Session *session;

  session = find_session (&car->target);
  if (NULL == session)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Dropped client request for transmission (am disconnected)\n");
    GNUNET_break (0);           /* should have been rejected earlier */
    GSC_CLIENTS_reject_request (car,
                                GNUNET_NO);
    return;
  }
  if (car->msize > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
  {
    GNUNET_break (0);
    GSC_CLIENTS_reject_request (car,
                                GNUNET_YES);
    return;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Received client transmission request. queueing\n");
  GNUNET_CONTAINER_DLL_insert (session->active_client_request_head,
                               session->active_client_request_tail,
                               car);
  try_transmission (session);
}
Example #15
0
/**
 * Add another child node to the tree.
 *
 * @param parent parent of the child, NULL for top level
 * @param filename name of the file or directory
 * @param is_directory GNUNET_YES for directories
 * @return new entry that was just created
 */
static struct GNUNET_FS_ShareTreeItem *
expand_tree (struct GNUNET_FS_ShareTreeItem *parent,
	     const char *filename,
	     int is_directory)
{
  struct GNUNET_FS_ShareTreeItem *chld;
  size_t slen;

  chld = GNUNET_malloc (sizeof (struct GNUNET_FS_ShareTreeItem));
  chld->parent = parent;
  chld->filename = GNUNET_strdup (filename);
  GNUNET_asprintf (&chld->short_filename,
		   "%s%s",
		   GNUNET_STRINGS_get_short_name (filename),
		   is_directory == GNUNET_YES ? "/" : "");
  /* make sure we do not end with '//' */
  slen = strlen (chld->short_filename);
  if ( (slen >= 2) &&
       (chld->short_filename[slen-1] == '/') &&
       (chld->short_filename[slen-2] == '/') )
    chld->short_filename[slen-1] = '\0';
  chld->is_directory = is_directory;
  if (NULL != parent)
      GNUNET_CONTAINER_DLL_insert (parent->children_head,
				   parent->children_tail,
				   chld);  
  return chld;
}
static void
resolve_validation_address (const struct GNUNET_PeerIdentity *id,
    const struct GNUNET_HELLO_Address *address, int numeric,
    struct GNUNET_TIME_Absolute last_validation,
    struct GNUNET_TIME_Absolute valid_until,
    struct GNUNET_TIME_Absolute next_validation,
    enum GNUNET_TRANSPORT_ValidationState state)
{
  struct ValidationResolutionContext *vc;

  vc = GNUNET_new (struct ValidationResolutionContext);
  GNUNET_assert(NULL != vc);
  GNUNET_CONTAINER_DLL_insert(vc_head, vc_tail, vc);
  address_resolutions++;

  vc->id = (*id);
  vc->transport = GNUNET_strdup(address->transport_name);
  vc->addrcp = GNUNET_HELLO_address_copy (address);
  vc->printed = GNUNET_NO;
  vc->state = state;
  vc->last_validation = last_validation;
  vc->valid_until = valid_until;
  vc->next_validation = next_validation;

  /* Resolve address to string */
  vc->asc = GNUNET_TRANSPORT_address_to_string (cfg, address, numeric,
      RESOLUTION_TIMEOUT, &process_validation_string, vc);
}
/**
 * Force plugin to terminate session due to communication
 * issue.
 *
 * @param plugin_name name of the plugin
 * @param session session to termiante
 */
static void
kill_session (const char *plugin_name,
              struct GNUNET_ATS_Session *session)
{
  struct GNUNET_TRANSPORT_PluginFunctions *plugin;
  struct GNUNET_ATS_SessionKiller *sk;

  for (sk = sk_head; NULL != sk; sk = sk->next)
    if (sk->session == session)
      return;
  plugin = GST_plugins_find (plugin_name);
  if (NULL == plugin)
  {
    GNUNET_break(0);
    return;
  }
  /* need to issue disconnect asynchronously */
  sk = GNUNET_new (struct GNUNET_ATS_SessionKiller);
  sk->session = session;
  sk->plugin = plugin;
  sk->task = GNUNET_SCHEDULER_add_now (&kill_session_task, sk);
  GNUNET_CONTAINER_DLL_insert (sk_head,
                               sk_tail,
                               sk);
}
Example #18
0
/**
 * Stop monitoring.
 *
 * @param handle The handle to the monitor request returned by monitor_start.
 *
 * On return get_handle will no longer be valid, caller must not use again!!!
 */
void
GNUNET_DHT_monitor_stop (struct GNUNET_DHT_MonitorHandle *handle)
{
  struct GNUNET_DHT_MonitorStartStopMessage *m;
  struct PendingMessage *pending;

  GNUNET_CONTAINER_DLL_remove (handle->dht_handle->monitor_head,
                               handle->dht_handle->monitor_tail,
                               handle);

  pending = GNUNET_malloc (sizeof (struct GNUNET_DHT_MonitorStartStopMessage) +
                           sizeof (struct PendingMessage));
  m = (struct GNUNET_DHT_MonitorStartStopMessage *) &pending[1];
  pending->msg = &m->header;
  pending->handle = handle->dht_handle;
  pending->free_on_send = GNUNET_YES;
  m->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_MONITOR_STOP);
  m->header.size = htons (sizeof (struct GNUNET_DHT_MonitorStartStopMessage));
  m->type = htonl(handle->type);
  m->get = htons(NULL != handle->get_cb);
  m->get_resp = htons(NULL != handle->get_resp_cb);
  m->put = htons(NULL != handle->put_cb);
  if (NULL != handle->key) {
    m->filter_key = htons(1);
    memcpy (&m->key, handle->key, sizeof(GNUNET_HashCode));
  }
  GNUNET_CONTAINER_DLL_insert (handle->dht_handle->pending_head,
                               handle->dht_handle->pending_tail,
                               pending);
  pending->in_pending_queue = GNUNET_YES;
  process_pending_messages (handle->dht_handle);
  
  GNUNET_free_non_null (handle->key);
  GNUNET_free (handle);
}
/**
 * Look for a block by directly contacting a particular peer.
 *
 * @param target peer that should have the block
 * @param query hash to query for the block
 * @param type desired type for the block
 * @param proc function to call with result
 * @param proc_cls closure for 'proc'
 * @return handle to cancel the operation
 */
struct GSF_StreamRequest *
GSF_stream_query (const struct GNUNET_PeerIdentity *target,
		  const struct GNUNET_HashCode *query,
		  enum GNUNET_BLOCK_Type type,
		  GSF_StreamReplyProcessor proc, void *proc_cls)
{
  struct StreamHandle *sh;
  struct GSF_StreamRequest *sr;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
	      "Preparing to send query for %s via stream to %s\n",
	      GNUNET_h2s (query),
	      GNUNET_i2s (target));
  sh = get_stream (target);
  sr = GNUNET_malloc (sizeof (struct GSF_StreamRequest));
  sr->sh = sh;
  sr->proc = proc;
  sr->proc_cls = proc_cls;
  sr->type = type;
  sr->query = *query;
  GNUNET_CONTAINER_DLL_insert (sh->pending_head,
			       sh->pending_tail,
			       sr);
  if (GNUNET_YES == sh->is_ready)
    transmit_pending (sh);
  return sr;
}
Example #20
0
/**
 * Start monitoring the local DHT service.
 *
 * @param handle Handle to the DHT service.
 * @param type Type of blocks that are of interest.
 * @param key Key of data of interest, NULL for all.
 * @param get_cb Callback to process monitored get messages.
 * @param get_resp_cb Callback to process monitored get response messages.
 * @param put_cb Callback to process monitored put messages.
 * @param cb_cls Closure for callbacks.
 * @return Handle to stop monitoring.
 */
struct GNUNET_DHT_MonitorHandle *
GNUNET_DHT_monitor_start (struct GNUNET_DHT_Handle *handle,
                          enum GNUNET_BLOCK_Type type,
                          const struct GNUNET_HashCode *key,
                          GNUNET_DHT_MonitorGetCB get_cb,
                          GNUNET_DHT_MonitorGetRespCB get_resp_cb,
                          GNUNET_DHT_MonitorPutCB put_cb,
                          void *cb_cls)
{
  struct GNUNET_DHT_MonitorHandle *h;
  struct GNUNET_DHT_MonitorStartStopMessage *m;
  struct PendingMessage *pending;

  h = GNUNET_new (struct GNUNET_DHT_MonitorHandle);
  GNUNET_CONTAINER_DLL_insert(handle->monitor_head, handle->monitor_tail, h);

  h->get_cb = get_cb;
  h->get_resp_cb = get_resp_cb;
  h->put_cb = put_cb;
  h->cb_cls = cb_cls;
  h->type = type;
  h->dht_handle = handle;
  if (NULL != key)
  {
    h->key = GNUNET_new (struct GNUNET_HashCode);
    *h->key = *key;
  }
Example #21
0
/**
 * Activity on our listen socket. Accept the
 * incoming connection.
 *
 * @param cls the `struct GNUNET_NAT_Test`
 * @param tc scheduler context
 */
static void
do_accept (void *cls,
           const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct GNUNET_NAT_Test *tst = cls;
  struct GNUNET_NETWORK_Handle *s;
  struct NatActivity *wl;

  tst->ltask = NULL;
  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
    return;
  tst->ltask =
      GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, tst->lsock,
                                     &do_accept, tst);
  s = GNUNET_NETWORK_socket_accept (tst->lsock, NULL, NULL);
  if (NULL == s)
  {
    GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, "accept");
    return;                     /* odd error */
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Got an inbound connection, waiting for data\n");
  wl = GNUNET_new (struct NatActivity);
  wl->sock = s;
  wl->h = tst;
  wl->rtask =
    GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
                                   wl->sock,
                                   &do_read, wl);
  GNUNET_CONTAINER_DLL_insert (tst->na_head, tst->na_tail, wl);
}
Example #22
0
/**
 * Disconnect from service and then reconnect.
 *
 * @param handle our handle
 */
static void
force_reconnect (struct GNUNET_GNS_Handle *handle)
{
  struct GNUNET_GNS_ShortenRequest *st;
  struct GNUNET_GNS_LookupRequest *lh;
  struct GNUNET_GNS_GetAuthRequest *ga;
  struct PendingMessage *p;

  GNUNET_CLIENT_disconnect (handle->client);
  handle->client = NULL;
  handle->in_receive = GNUNET_NO;
  for (st = handle->shorten_head; NULL != st; st = st->next)
  {
    p = (struct PendingMessage *) &st[1];
    if (GNUNET_NO == p->transmitted)
      continue;
    p->transmitted = GNUNET_NO;
    GNUNET_CONTAINER_DLL_insert (handle->pending_head,
				 handle->pending_tail,
				 p);  
  }
  for (lh = handle->lookup_head; NULL != lh; lh = lh->next)
  {
    p = (struct PendingMessage *) &lh[1];
    if (GNUNET_NO == p->transmitted)
      continue;
    p->transmitted = GNUNET_NO;
    GNUNET_CONTAINER_DLL_insert (handle->pending_head,
				 handle->pending_tail,
				 p);  
  }
  for (ga = handle->get_auth_head; NULL != ga; ga = ga->next)
  {
    p = (struct PendingMessage *) &ga[1];
    if (GNUNET_NO == p->transmitted)
      continue;
    p->transmitted = GNUNET_NO;
    GNUNET_CONTAINER_DLL_insert (handle->pending_head,
				 handle->pending_tail,
				 p);  
  }
  handle->reconnect_backoff = GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff);
  handle->reconnect_task = GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff,
                                                    &reconnect_task,
                                                    handle);
}
/**
 * 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);
}
Example #24
0
/**
 * Perform a PUT operation storing data in the DHT.  FIXME: we should
 * change the protocol to get a confirmation for the PUT from the DHT
 * and call 'cont' only after getting the confirmation; otherwise, the
 * client has no good way of telling if the 'PUT' message actually got
 * to the DHT service!
 *
 * @param handle handle to DHT service
 * @param key the key to store under
 * @param desired_replication_level estimate of how many
 *                nearest peers this request should reach
 * @param options routing options for this message
 * @param type type of the value
 * @param size number of bytes in data; must be less than 64k
 * @param data the data to store
 * @param exp desired expiration time for the value
 * @param timeout how long to wait for transmission of this request
 * @param cont continuation to call when done (transmitting request to service)
 *        You must not call #GNUNET_DHT_disconnect in this continuation
 * @param cont_cls closure for @a cont
 */
struct GNUNET_DHT_PutHandle *
GNUNET_DHT_put (struct GNUNET_DHT_Handle *handle,
		const struct GNUNET_HashCode * key,
                uint32_t desired_replication_level,
                enum GNUNET_DHT_RouteOption options,
                enum GNUNET_BLOCK_Type type, size_t size,
		const void *data,
                struct GNUNET_TIME_Absolute exp,
                struct GNUNET_TIME_Relative timeout,
		GNUNET_DHT_PutContinuation cont,
                void *cont_cls)
{
  struct GNUNET_DHT_ClientPutMessage *put_msg;
  size_t msize;
  struct PendingMessage *pending;
  struct GNUNET_DHT_PutHandle *ph;


  msize = sizeof (struct GNUNET_DHT_ClientPutMessage) + size;
  if ((msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) ||
      (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE))
  {
    GNUNET_break (0);
    return NULL;
  }
  ph = GNUNET_new (struct GNUNET_DHT_PutHandle);
  ph->dht_handle = handle;
  ph->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &timeout_put_request, ph);
  ph->cont = cont;
  ph->cont_cls = cont_cls;
  ph->unique_id = ++handle->uid_gen;
  pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize);
  ph->pending = pending;
  put_msg = (struct GNUNET_DHT_ClientPutMessage *) &pending[1];
  pending->msg = &put_msg->header;
  pending->handle = handle;
  pending->cont = &mark_put_message_gone;
  pending->cont_cls = ph;
  pending->free_on_send = GNUNET_YES;
  put_msg->header.size = htons (msize);
  put_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT);
  put_msg->type = htonl (type);
  put_msg->options = htonl ((uint32_t) options);
  put_msg->desired_replication_level = htonl (desired_replication_level);
  put_msg->unique_id = ph->unique_id;
  put_msg->expiration = GNUNET_TIME_absolute_hton (exp);
  put_msg->key = *key;
  memcpy (&put_msg[1], data, size);
  GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail,
                               pending);
  pending->in_pending_queue = GNUNET_YES;
  GNUNET_CONTAINER_DLL_insert_tail (handle->put_head,
				    handle->put_tail,
				    ph);
  process_pending_messages (handle);
  return ph;
}
Example #25
0
/**
 * Perform an asynchronous lookup operation on the GNS.
 *
 * @param handle handle to the GNS service
 * @param name the name to look up
 * @param zone the zone to start the resolution in
 * @param type the record type to look up
 * @param options local options for the lookup
 * @param shorten_zone_key the private key of the shorten zone (can be NULL)
 * @param proc processor to call on result
 * @param proc_cls closure for @a proc
 * @return handle to the get request
 */
struct GNUNET_GNS_LookupRequest*
GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle,
                   const char *name,
                   const struct GNUNET_CRYPTO_EcdsaPublicKey *zone,
                   uint32_t type,
                   enum GNUNET_GNS_LocalOptions options,
                   const struct GNUNET_CRYPTO_EcdsaPrivateKey *shorten_zone_key,
                   GNUNET_GNS_LookupResultProcessor proc,
                   void *proc_cls)
{
    /* IPC to shorten gns names, return shorten_handle */
    struct LookupMessage *lookup_msg;
    struct GNUNET_GNS_LookupRequest *lr;
    size_t nlen;

    if (NULL == name)
    {
        GNUNET_break (0);
        return NULL;
    }
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Trying to lookup `%s' in GNS\n",
         name);
    nlen = strlen (name) + 1;
    if (nlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*lr))
    {
        GNUNET_break (0);
        return NULL;
    }
    lr = GNUNET_new (struct GNUNET_GNS_LookupRequest);
    lr->gns_handle = handle;
    lr->lookup_proc = proc;
    lr->proc_cls = proc_cls;
    lr->r_id = handle->r_id_gen++;
    lr->env = GNUNET_MQ_msg_extra (lookup_msg,
                                   nlen,
                                   GNUNET_MESSAGE_TYPE_GNS_LOOKUP);
    lookup_msg->id = htonl (lr->r_id);
    lookup_msg->options = htons ((uint16_t) options);
    lookup_msg->zone = *zone;
    lookup_msg->type = htonl (type);
    if (NULL != shorten_zone_key)
    {
        lookup_msg->have_key = htons (GNUNET_YES);
        lookup_msg->shorten_key = *shorten_zone_key;
    }
    GNUNET_memcpy (&lookup_msg[1],
                   name,
                   nlen);
    GNUNET_CONTAINER_DLL_insert (handle->lookup_head,
                                 handle->lookup_tail,
                                 lr);
    if (NULL != handle->mq)
        GNUNET_MQ_send_copy (handle->mq,
                             lr->env);
    return lr;
}
Example #26
0
/**
 * Our current client connection went down.  Clean it up
 * and try to reconnect!
 *
 * @param h our handle to the core service
 */
static void
reconnect (struct GNUNET_CORE_Handle *h)
{
  struct ControlMessage *cm;
  struct InitMessage *init;
  uint32_t opt;
  uint16_t msize;
  uint16_t *ts;
  unsigned int hpos;

  GNUNET_assert (NULL == h->client);
  GNUNET_assert (GNUNET_YES == h->currently_down);
  GNUNET_assert (NULL != h->cfg);
  h->client = GNUNET_CLIENT_connect ("core", h->cfg);
  if (NULL == h->client)
  {
    reconnect_later (h);
    return;
  }
  msize = h->hcnt * sizeof (uint16_t) + sizeof (struct InitMessage);
  cm = GNUNET_malloc (sizeof (struct ControlMessage) + msize);
  cm->cont = &init_done_task;
  cm->cont_cls = h;
  init = (struct InitMessage *) &cm[1];
  init->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT);
  init->header.size = htons (msize);
  opt = 0;
  if (h->inbound_notify != NULL)
  {
    if (h->inbound_hdr_only)
      opt |= GNUNET_CORE_OPTION_SEND_HDR_INBOUND;
    else
      opt |= GNUNET_CORE_OPTION_SEND_FULL_INBOUND;
  }
  if (h->outbound_notify != NULL)
  {
    if (h->outbound_hdr_only)
      opt |= GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND;
    else
      opt |= GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND;
  }
  LOG (GNUNET_ERROR_TYPE_INFO,
       "(Re)connecting to CORE service, monitoring messages of type %u\n",
       opt);

  init->options = htonl (opt);
  ts = (uint16_t *) & init[1];
  for (hpos = 0; hpos < h->hcnt; hpos++)
    ts[hpos] = htons (h->handlers[hpos].type);
  GNUNET_CONTAINER_DLL_insert (h->control_pending_head, h->control_pending_tail,
                               cm);
  trigger_next_request (h, GNUNET_YES);
}
Example #27
0
/**
 * Prepare a statement.  Prepared statements are automatically discarded
 * when the MySQL context is destroyed.
 *
 * @param mc mysql context
 * @param query query text
 * @return prepared statement, NULL on error
 */
struct GNUNET_MYSQL_StatementHandle *
GNUNET_MYSQL_statement_prepare (struct GNUNET_MYSQL_Context *mc,
                                const char *query)
{
  struct GNUNET_MYSQL_StatementHandle *sh;

  sh = GNUNET_new (struct GNUNET_MYSQL_StatementHandle);
  sh->mc = mc;
  sh->query = GNUNET_strdup (query);
  GNUNET_CONTAINER_DLL_insert (mc->shead, mc->stail, sh);
  return sh;
}
Example #28
0
/**
 * Perform an asynchronous GET operation on the DHT identified. See
 * also #GNUNET_BLOCK_evaluate.
 *
 * @param handle handle to the DHT service
 * @param type expected type of the response object
 * @param key the key to look up
 * @param desired_replication_level estimate of how many
                  nearest peers this request should reach
 * @param options routing options for this message
 * @param xquery extended query data (can be NULL, depending on type)
 * @param xquery_size number of bytes in @a xquery
 * @param iter function to call on each result
 * @param iter_cls closure for iter
 * @return handle to stop the async get
 */
struct GNUNET_DHT_GetHandle *
GNUNET_DHT_get_start (struct GNUNET_DHT_Handle *handle,
                      enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode * key,
                      uint32_t desired_replication_level,
                      enum GNUNET_DHT_RouteOption options, const void *xquery,
                      size_t xquery_size, GNUNET_DHT_GetIterator iter,
                      void *iter_cls)
{
  struct GNUNET_DHT_ClientGetMessage *get_msg;
  struct GNUNET_DHT_GetHandle *get_handle;
  size_t msize;
  struct PendingMessage *pending;

  msize = sizeof (struct GNUNET_DHT_ClientGetMessage) + xquery_size;
  if ((msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) ||
      (xquery_size >= GNUNET_SERVER_MAX_MESSAGE_SIZE))
  {
    GNUNET_break (0);
    return NULL;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending query for %s to DHT %p\n",
       GNUNET_h2s (key), handle);
  pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize);
  get_msg = (struct GNUNET_DHT_ClientGetMessage *) &pending[1];
  pending->msg = &get_msg->header;
  pending->handle = handle;
  pending->free_on_send = GNUNET_NO;
  get_msg->header.size = htons (msize);
  get_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET);
  get_msg->options = htonl ((uint32_t) options);
  get_msg->desired_replication_level = htonl (desired_replication_level);
  get_msg->type = htonl (type);
  get_msg->key = *key;
  get_msg->unique_id = ++handle->uid_gen;
  memcpy (&get_msg[1], xquery, xquery_size);
  GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail,
                               pending);
  pending->in_pending_queue = GNUNET_YES;
  get_handle = GNUNET_new (struct GNUNET_DHT_GetHandle);
  get_handle->key = *key;
  get_handle->dht_handle = handle;
  get_handle->iter = iter;
  get_handle->iter_cls = iter_cls;
  get_handle->message = pending;
  get_handle->unique_id = get_msg->unique_id;
  GNUNET_CONTAINER_multihashmap_put (handle->active_requests,
                                     &get_handle->key,
                                     get_handle,
                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  process_pending_messages (handle);
  return get_handle;
}
Example #29
0
/**
 * Handle ANNOUNCE message.
 *
 * @param cls closure
 * @param client identification of the client
 * @param message the actual message
 */
static void
handle_announce (void *cls,
		 struct GNUNET_SERVER_Client *client,
		 const struct GNUNET_MessageHeader *message)
{
  const struct AnnounceMessage *am;
  const char *regex;
  struct ClientEntry *ce;
  uint16_t size;

  size = ntohs (message->size);
  am = (const struct AnnounceMessage *) message;
  regex = (const char *) &am[1];
  if ( (size <= sizeof (struct AnnounceMessage)) ||
       ('\0' != regex[size - sizeof (struct AnnounceMessage) - 1]) )
  {
    GNUNET_break (0);
    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
    return;
  }

  ce = GNUNET_new (struct ClientEntry);
  ce->client = client;
  ce->frequency = GNUNET_TIME_relative_ntoh (am->refresh_delay);
  ce->refresh_task = GNUNET_SCHEDULER_add_delayed (ce->frequency,
						   &reannounce,
						   ce);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
	      "Starting to announce regex `%s' every %s\n",
	      regex,
	      GNUNET_STRINGS_relative_time_to_string (ce->frequency,
						      GNUNET_NO));
  ce->ah = REGEX_INTERNAL_announce (dht,
				    my_private_key,
				    regex,
				    ntohs (am->compression),
				    stats);
  if (NULL == ce->ah)
  {
    GNUNET_break (0);
    GNUNET_SCHEDULER_cancel (ce->refresh_task);
    GNUNET_free (ce);
    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
    return;
  }
  GNUNET_CONTAINER_DLL_insert (client_head,
			       client_tail,
			       ce);
  GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
Example #30
0
/**
 * Stop async DHT-get.
 *
 * @param get_handle handle to the GET operation to stop
 */
void
GNUNET_DHT_get_stop (struct GNUNET_DHT_GetHandle *get_handle)
{
  struct GNUNET_DHT_Handle *handle;
  const struct GNUNET_DHT_ClientGetMessage *get_msg;
  struct GNUNET_DHT_ClientGetStopMessage *stop_msg;
  struct PendingMessage *pending;

  handle = get_handle->message->handle;
  get_msg =
      (const struct GNUNET_DHT_ClientGetMessage *) get_handle->message->msg;
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Sending STOP for %s to DHT via %p\n",
       GNUNET_h2s (&get_msg->key), handle);
  /* generate STOP */
  pending =
      GNUNET_malloc (sizeof (struct PendingMessage) +
                     sizeof (struct GNUNET_DHT_ClientGetStopMessage));
  stop_msg = (struct GNUNET_DHT_ClientGetStopMessage *) &pending[1];
  pending->msg = &stop_msg->header;
  pending->handle = handle;
  pending->free_on_send = GNUNET_YES;
  stop_msg->header.size =
      htons (sizeof (struct GNUNET_DHT_ClientGetStopMessage));
  stop_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_STOP);
  stop_msg->reserved = htonl (0);
  stop_msg->unique_id = get_msg->unique_id;
  stop_msg->key = get_msg->key;
  GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail,
                               pending);
  pending->in_pending_queue = GNUNET_YES;

  /* remove 'GET' from active status */
  GNUNET_assert (GNUNET_YES ==
                 GNUNET_CONTAINER_multihashmap_remove (handle->active_requests,
                                                       &get_handle->key,
                                                       get_handle));
  if (GNUNET_YES == get_handle->message->in_pending_queue)
  {
    GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail,
                                 get_handle->message);
    get_handle->message->in_pending_queue = GNUNET_NO;
  }
  GNUNET_free (get_handle->message);
  GNUNET_array_grow (get_handle->seen_results,
		     get_handle->seen_results_end,
		     0);
  GNUNET_free (get_handle);
  process_pending_messages (handle);
}