예제 #1
0
/**
 * Get a result for a particular key from the namestore.  The processor
 * will only be called once.  
 *
 * @param h handle to the namestore
 * @param zone zone to look up a record from
 * @param name name to look up
 * @param record_type desired record type, 0 for all
 * @param proc function to call on the matching records, or with
 *        NULL (rd_count == 0) if there are no matching records
 * @param proc_cls closure for proc
 * @return a handle that can be used to
 *         cancel
 */
struct GNUNET_NAMESTORE_QueueEntry *
GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h, 
			      const struct GNUNET_CRYPTO_ShortHashCode *zone,
			      const char *name,
			      uint32_t record_type,
			      GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
{
  struct GNUNET_NAMESTORE_QueueEntry *qe;
  struct PendingMessage *pe;
  size_t msg_size = 0;
  size_t name_len = 0;
  uint32_t rid = 0;

  GNUNET_assert (NULL != h);
  GNUNET_assert (NULL != zone);
  GNUNET_assert (NULL != name);

  name_len = strlen (name) + 1;
  if ((name_len == 0) || (name_len > 256))
  {
    GNUNET_break (0);
    return NULL;
  }

  rid = get_op_id(h);
  qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
  qe->nsh = h;
  qe->proc = proc;
  qe->proc_cls = proc_cls;
  qe->op_id = rid;
  GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);

  /* set msg_size*/
  msg_size = sizeof (struct LookupNameMessage) + name_len;
  pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);

  /* create msg here */
  struct LookupNameMessage * msg;
  pe->size = msg_size;
  pe->is_init = GNUNET_NO;
  msg = (struct LookupNameMessage *) &pe[1];
  msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME);
  msg->gns_header.header.size = htons (msg_size);
  msg->gns_header.r_id = htonl (rid);
  msg->record_type = htonl (record_type);
  msg->name_len = htonl (name_len);
  msg->zone = *zone;
  memcpy (&msg[1], name, name_len);

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "NAMESTORE_LOOKUP_NAME", name);

  /* transmit message */
  GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
  do_transmit(h);

  return qe;
}
예제 #2
0
/**
 * Call a method for each known matching host and change its trust
 * value.  The callback method will be invoked once for each matching
 * host and then finally once with a NULL pointer.  After that final
 * invocation, the iterator context must no longer be used.
 *
 * Instead of calling this function with 'peer == NULL' it is often
 * better to use 'GNUNET_PEERINFO_notify'.
 *
 * @param h handle to the peerinfo service
 * @param peer restrict iteration to this peer only (can be NULL)
 * @param timeout how long to wait until timing out
 * @param callback the method to call for each peer
 * @param callback_cls closure for callback
 * @return iterator context
 */
struct GNUNET_PEERINFO_IteratorContext *
GNUNET_PEERINFO_iterate (struct GNUNET_PEERINFO_Handle *h,
                         const struct GNUNET_PeerIdentity *peer,
                         struct GNUNET_TIME_Relative timeout,
                         GNUNET_PEERINFO_Processor callback, void *callback_cls)
{
  struct GNUNET_MessageHeader *lapm;
  struct ListPeerMessage *lpm;
  struct GNUNET_PEERINFO_IteratorContext *ic;
  struct GNUNET_PEERINFO_AddContext *ac;

  ic = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_IteratorContext));
  if (NULL == peer)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Requesting list of peers from PEERINFO service\n");
    ac =
        GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_AddContext) +
                       sizeof (struct GNUNET_MessageHeader));
    ac->size = sizeof (struct GNUNET_MessageHeader);
    lapm = (struct GNUNET_MessageHeader *) &ac[1];
    lapm->size = htons (sizeof (struct GNUNET_MessageHeader));
    lapm->type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL);
  }
  else
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Requesting information on peer `%4s' from PEERINFO service\n",
         GNUNET_i2s (peer));
    ac =
        GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_AddContext) +
                       sizeof (struct ListPeerMessage));
    ac->size = sizeof (struct ListPeerMessage);
    lpm = (struct ListPeerMessage *) &ac[1];
    lpm->header.size = htons (sizeof (struct ListPeerMessage));
    lpm->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET);
    memcpy (&lpm->peer, peer, sizeof (struct GNUNET_PeerIdentity));
    ic->have_peer = GNUNET_YES;
    ic->peer = *peer;
  }
  ic->h = h;
  ic->ac = ac;
  ic->callback = callback;
  ic->callback_cls = callback_cls;
  ic->timeout = GNUNET_TIME_relative_to_absolute (timeout);
  ic->timeout_task =
      GNUNET_SCHEDULER_add_delayed (timeout, &signal_timeout, ic);
  ac->cont = &iterator_start_receive;
  ac->cont_cls = ic;
  GNUNET_CONTAINER_DLL_insert_tail (h->ac_head, h->ac_tail, ac);
  GNUNET_CONTAINER_DLL_insert_tail (h->ic_head,
				    h->ic_tail,
				    ic);
  trigger_transmit (h);
  return ic;
}
예제 #3
0
/**
 * Look for an existing PKEY delegation record for a given public key.
 * Returns at most one result to the processor.
 *
 * @param h handle to the namestore
 * @param zone hash of public key of the zone to look up in, never NULL
 * @param value_zone hash of the public key of the target zone (value), never NULL
 * @param proc function to call on the matching records, or with
 *        NULL (rd_count == 0) if there are no matching records
 * @param proc_cls closure for proc
 * @return a handle that can be used to
 *         cancel
 */
struct GNUNET_NAMESTORE_QueueEntry *
GNUNET_NAMESTORE_zone_to_name (struct GNUNET_NAMESTORE_Handle *h,
                               const struct GNUNET_CRYPTO_ShortHashCode *zone,
                               const struct GNUNET_CRYPTO_ShortHashCode *value_zone,
                               GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
{
  struct GNUNET_NAMESTORE_QueueEntry *qe;
  struct PendingMessage *pe;
  size_t msg_size = 0;
  uint32_t rid = 0;

  GNUNET_assert (NULL != h);
  GNUNET_assert (NULL != zone);
  GNUNET_assert (NULL != value_zone);

  rid = get_op_id(h);
  qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
  qe->nsh = h;
  qe->proc = proc;
  qe->proc_cls = proc_cls;
  qe->op_id = rid;
  GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);

  /* set msg_size*/
  msg_size = sizeof (struct ZoneToNameMessage);
  pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);

  /* create msg here */
  struct ZoneToNameMessage * msg;
  pe->size = msg_size;
  pe->is_init = GNUNET_NO;
  msg = (struct ZoneToNameMessage *) &pe[1];
  msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME);
  msg->gns_header.header.size = htons (msg_size);
  msg->gns_header.r_id = htonl (rid);
  msg->zone = *zone;
  msg->value_zone = *value_zone;

  char * z_tmp = GNUNET_strdup (GNUNET_short_h2s (zone));
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s' in zone `%s'\n",
      "NAMESTORE_ZONE_TO_NAME",
      z_tmp,
      GNUNET_short_h2s (value_zone));
  GNUNET_free (z_tmp);

  /* transmit message */
  GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
  do_transmit(h);

  return qe;
}
예제 #4
0
파일: helper.c 프로젝트: GNUnet/gnunet
/**
 * Send an message to the helper.
 *
 * @param h helper to send message to
 * @param msg message to send
 * @param can_drop can the message be dropped if there is already one in the queue?
 * @param cont continuation to run once the message is out (#GNUNET_OK on succees, #GNUNET_NO
 *             if the helper process died, #GNUNET_SYSERR during #GNUNET_HELPER_destroy).
 * @param cont_cls closure for @a cont
 * @return NULL if the message was dropped,
 *         otherwise handle to cancel *cont* (actual transmission may
 *         not be abortable)
 */
struct GNUNET_HELPER_SendHandle *
GNUNET_HELPER_send (struct GNUNET_HELPER_Handle *h,
		    const struct GNUNET_MessageHeader *msg,
		    int can_drop,
		    GNUNET_HELPER_Continuation cont,
		    void *cont_cls)
{
  struct GNUNET_HELPER_SendHandle *sh;
  uint16_t mlen;

  if (NULL == h->fh_to_helper)
    return NULL;
  if ( (GNUNET_YES == can_drop) &&
       (NULL != h->sh_head) )
    return NULL;
  mlen = ntohs (msg->size);
  sh = GNUNET_malloc (sizeof (struct GNUNET_HELPER_SendHandle) + mlen);
  sh->msg = (const struct GNUNET_MessageHeader*) &sh[1];
  GNUNET_memcpy (&sh[1], msg, mlen);
  sh->h = h;
  sh->cont = cont;
  sh->cont_cls = cont_cls;
  GNUNET_CONTAINER_DLL_insert_tail (h->sh_head,
				    h->sh_tail,
				    sh);
  if (NULL == h->write_task)
    h->write_task = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
						     h->fh_to_helper,
						     &helper_write,
						     h);

  return sh;
}
예제 #5
0
파일: peerstore_api.c 프로젝트: tg-x/gnunet
/**
 * Iterate over records matching supplied key information
 *
 * @param h handle to the PEERSTORE service
 * @param sub_system name of sub system
 * @param peer Peer identity (can be NULL)
 * @param key entry key string (can be NULL)
 * @param timeout time after which the iterate request is canceled
 * @param callback function called with each matching record, all NULL's on end
 * @param callback_cls closure for @a callback
 * @return Handle to iteration request
 */
struct GNUNET_PEERSTORE_IterateContext *
GNUNET_PEERSTORE_iterate (struct GNUNET_PEERSTORE_Handle *h,
                          const char *sub_system,
                          const struct GNUNET_PeerIdentity *peer,
                          const char *key, struct GNUNET_TIME_Relative timeout,
                          GNUNET_PEERSTORE_Processor callback,
                          void *callback_cls)
{
  struct GNUNET_MQ_Envelope *ev;
  struct GNUNET_PEERSTORE_IterateContext *ic;

  ev = PEERSTORE_create_record_mq_envelope (sub_system, peer, key, NULL, 0,
                                            NULL, 0,
                                            GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE);
  ic = GNUNET_new (struct GNUNET_PEERSTORE_IterateContext);

  ic->callback = callback;
  ic->callback_cls = callback_cls;
  ic->h = h;
  ic->sub_system = GNUNET_strdup (sub_system);
  if (NULL != peer)
    ic->peer = *peer;
  if (NULL != key)
    ic->key = GNUNET_strdup (key);
  ic->timeout = timeout;
  GNUNET_CONTAINER_DLL_insert_tail (h->iterate_head,
                                    h->iterate_tail,
                                    ic);
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Sending an iterate request for sub system `%s'\n", sub_system);
  GNUNET_MQ_send (h->mq, ev);
  ic->timeout_task =
      GNUNET_SCHEDULER_add_delayed (timeout, &iterate_timeout, ic);
  return ic;
}
예제 #6
0
/**
 * Function to call to start a peer_create type operation once all
 * queues the operation is part of declare that the
 * operation can be activated.
 *
 * @param cls the closure from GNUNET_TESTBED_operation_create_()
 */
static void
opstart_peer_create (void *cls)
{
  struct OperationContext *opc = cls;
  struct PeerCreateData *data;
  struct GNUNET_TESTBED_PeerCreateMessage *msg;
  char *config;
  char *xconfig;
  size_t c_size;
  size_t xc_size;
  uint16_t msize;

  GNUNET_assert (OP_PEER_CREATE == opc->type);
  data = opc->data;
  GNUNET_assert (NULL != data);
  GNUNET_assert (NULL != data->peer);
  opc->state = OPC_STATE_STARTED;
  config = GNUNET_CONFIGURATION_serialize (data->cfg, &c_size);
  xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig);
  GNUNET_free (config);
  msize = xc_size + sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
  msg = GNUNET_realloc (xconfig, msize);
  memmove (&msg[1], msg, xc_size);
  msg->header.size = htons (msize);
  msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER);
  msg->operation_id = GNUNET_htonll (opc->id);
  msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->peer->host));
  msg->peer_id = htonl (data->peer->unique_id);
  msg->config_size = htonl (c_size);
  GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
  GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
}
예제 #7
0
/**
 * Queues a message in send queue of the logger handle
 *
 * @param h the logger handle
 * @param msg the message to queue
 */
static void
queue_message (struct GNUNET_TESTBED_LOGGER_Handle *h,
               struct GNUNET_MessageHeader *msg)
{
  struct MessageQueue *mq;
  uint16_t type;
  uint16_t size;

  type = ntohs (msg->type);
  size = ntohs (msg->size);
  mq = GNUNET_new (struct MessageQueue);
  mq->msg = msg;
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Queueing message of type %u, size %u for sending\n", type,
       ntohs (msg->size));
  GNUNET_CONTAINER_DLL_insert_tail (h->mq_head, h->mq_tail, mq);
  if (NULL == h->th)
  {
    h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff);
    h->th =
        GNUNET_CLIENT_notify_transmit_ready (h->client, size,
                                             h->retry_backoff, GNUNET_YES,
                                             &transmit_ready_notify,
                                             h);
  }
}
예제 #8
0
/**
 * Add a PendingMessage to the subscriber's list of messages to be sent
 *
 * @param subscriber the subscriber to send the message to
 * @param pending_message the actual message to send
 */
static void
add_pending_subscriber_message (struct RemoteSubscriberInfo *subscriber,
                                struct PendingMessage *pending_message)
{
  GNUNET_CONTAINER_DLL_insert_tail (subscriber->pending_head,
                                    subscriber->pending_tail, pending_message);
}
/**
 * Send request to peer to start add him to to the set of experimentation nodes
 *
 * @param peer the peer to send to
 */
static void
send_experimentation_request (const struct GNUNET_PeerIdentity *peer)
{
  struct Node *n;
  struct NodeComCtx *e_ctx;
  size_t size;
  size_t c_issuers;

  c_issuers = GNUNET_CONTAINER_multihashmap_size (valid_issuers);
  size = sizeof (struct Experimentation_Request) +
    c_issuers * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey);
  n = GNUNET_new (struct Node);
  n->id = *peer;
  n->timeout_task = GNUNET_SCHEDULER_add_delayed (EXP_RESPONSE_TIMEOUT, &remove_request, n);
  n->capabilities = NONE;

  e_ctx = GNUNET_new (struct NodeComCtx);
  e_ctx->n = n;
  e_ctx->e = NULL;
  e_ctx->size = size;
  e_ctx->notify = &send_experimentation_request_cb;
  e_ctx->notify_cls = n;
  GNUNET_CONTAINER_DLL_insert_tail(n->e_req_head, n->e_req_tail, e_ctx);
  schedule_transmisson (e_ctx);

  GNUNET_assert (GNUNET_OK ==
		 GNUNET_CONTAINER_multipeermap_put (nodes_requested,
						    peer, n,
						    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
  update_stats (nodes_requested);
}
/**
 * Transmit the given message to the given target.
 *
 * @param target peer that should receive the message (must be connected)
 * @param msg message to transmit
 * @param timeout by when should the transmission be done?
 */
void
GSC_NEIGHBOURS_transmit (const struct GNUNET_PeerIdentity *target,
                         const struct GNUNET_MessageHeader *msg,
                         struct GNUNET_TIME_Relative timeout)
{
  struct NeighbourMessageEntry *me;
  struct Neighbour *n;
  size_t msize;

  n = find_neighbour (target);
  if (NULL == n)
  {
    GNUNET_break (0);
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                "Peer %s not found\n",
                GNUNET_i2s (target));
    return;
  }
  msize = ntohs (msg->size);
  me = GNUNET_malloc (sizeof (struct NeighbourMessageEntry) + msize);
  me->deadline = GNUNET_TIME_relative_to_absolute (timeout);
  me->size = msize;
  memcpy (&me[1],
          msg,
          msize);
  GNUNET_CONTAINER_DLL_insert_tail (n->message_head,
                                    n->message_tail,
                                    me);
  n->queue_size++;
  process_queue (n);
}
예제 #11
0
/**
 * Queues a message in send queue for sending to the service
 *
 * @param client the client to whom the queued message has to be sent
 * @param msg the message to queue
 */
void
GST_queue_message (struct GNUNET_SERVER_Client *client,
                   struct GNUNET_MessageHeader *msg)
{
  struct MessageQueue *mq_entry;
  uint16_t type;
  uint16_t size;

  type = ntohs (msg->type);
  size = ntohs (msg->size);
  GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
                 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
  mq_entry = GNUNET_new (struct MessageQueue);
  mq_entry->msg = msg;
  mq_entry->client = client;
  GNUNET_SERVER_client_keep (client);
  LOG_DEBUG ("Queueing message of type %u, size %u for sending\n", type,
             ntohs (msg->size));
  GNUNET_CONTAINER_DLL_insert_tail (mq_head, mq_tail, mq_entry);
  if (NULL == transmit_handle)
    transmit_handle =
        GNUNET_SERVER_notify_transmit_ready (client, size,
                                             GNUNET_TIME_UNIT_FOREVER_REL,
                                             &transmit_ready_notify, NULL);
}
예제 #12
0
파일: psycstore_api.c 프로젝트: tg-x/gnunet
/**
 * Store a message fragment sent to a channel.
 *
 * @param h Handle for the PSYCstore.
 * @param channel_key The channel the message belongs to.
 * @param message Message to store.
 * @param psycstore_flags Flags indicating whether the PSYC message contains
 *        state modifiers.
 * @param rcb Callback to call with the result of the operation.
 * @param rcb_cls Closure for the callback.
 *
 * @return Handle that can be used to cancel the operation.
 */
struct GNUNET_PSYCSTORE_OperationHandle *
GNUNET_PSYCSTORE_fragment_store (struct GNUNET_PSYCSTORE_Handle *h,
                                 const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
                                 const struct GNUNET_MULTICAST_MessageHeader *msg,
                                 enum GNUNET_PSYCSTORE_MessageFlags psycstore_flags,
                                 GNUNET_PSYCSTORE_ResultCallback rcb,
                                 void *rcb_cls)
{
  uint16_t size = ntohs (msg->header.size);
  struct FragmentStoreRequest *req;
  struct GNUNET_PSYCSTORE_OperationHandle *
    op = GNUNET_malloc (sizeof (*op) + sizeof (*req) + size);
  op->h = h;
  op->res_cb = rcb;
  op->cls = rcb_cls;

  req = (struct FragmentStoreRequest *) &op[1];
  op->msg = (struct GNUNET_MessageHeader *) req;
  req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_STORE);
  req->header.size = htons (sizeof (*req) + size);
  req->channel_key = *channel_key;
  req->psycstore_flags = htonl (psycstore_flags);
  memcpy (&req[1], msg, size);

  op->op_id = get_next_op_id (h);
  req->op_id = GNUNET_htonll (op->op_id);

  GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
  transmit_next (h);

  return op;
}
예제 #13
0
파일: psycstore_api.c 프로젝트: tg-x/gnunet
/**
 * Retrieve all state variables for a channel with the given prefix.
 *
 * @param h
 *        Handle for the PSYCstore.
 * @param channel_key
 *        The channel we are interested in.
 * @param name_prefix
 *        Prefix of state variable names to match.
 * @param scb
 *        Callback to return matching state variables.
 * @param rcb
 *        Callback to call with the result of the operation.
 * @param cls
 *        Closure for the callbacks.
 *
 * @return Handle that can be used to cancel the operation.
 */
struct GNUNET_PSYCSTORE_OperationHandle *
GNUNET_PSYCSTORE_state_get_prefix (struct GNUNET_PSYCSTORE_Handle *h,
                                   const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
                                   const char *name_prefix,
                                   GNUNET_PSYCSTORE_StateCallback scb,
                                   GNUNET_PSYCSTORE_ResultCallback rcb,
                                   void *cls)
{
  size_t name_size = strlen (name_prefix) + 1;
  struct OperationRequest *req;
  struct GNUNET_PSYCSTORE_OperationHandle *
    op = GNUNET_malloc (sizeof (*op) + sizeof (*req) + name_size);
  op->h = h;
  op->data_cb = (DataCallback) scb;
  op->res_cb = rcb;
  op->cls = cls;

  req = (struct OperationRequest *) &op[1];
  op->msg = (struct GNUNET_MessageHeader *) req;
  req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_GET_PREFIX);
  req->header.size = htons (sizeof (*req) + name_size);
  req->channel_key = *channel_key;
  memcpy (&req[1], name_prefix, name_size);

  op->op_id = get_next_op_id (h);
  req->op_id = GNUNET_htonll (op->op_id);

  GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
  transmit_next (h);

  return op;
}
/**
 * Task to register all hosts available in the global host list
 *
 * @param cls NULL
 * @param tc the scheduler task context
 */
static void
register_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct DLLOperation *dll_op;
  static unsigned int reg_host;
  unsigned int slave;

  register_hosts_task = GNUNET_SCHEDULER_NO_TASK;  
  if (reg_host == num_hosts - 1)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "All hosts successfully registered\n");
    /* Start slaves */
    state = STATE_SLAVES_STARTING;
    for (slave = 1; slave < num_hosts; slave++)
    {
      dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
      dll_op->op = GNUNET_TESTBED_controller_link (dll_op,
                                                   mc,
                                                   hosts[slave],
                                                   hosts[0],
                                                   cfg,
                                                   GNUNET_YES);
      GNUNET_CONTAINER_DLL_insert_tail (dll_op_head, dll_op_tail, dll_op);
    }
    return;
  }
  reg_handle = GNUNET_TESTBED_register_host (mc, hosts[++reg_host],
                                             host_registration_completion,
                                             NULL);
}
예제 #15
0
파일: psycstore_api.c 프로젝트: tg-x/gnunet
/**
 * Apply modifiers of a message to the current channel state.
 *
 * An error is returned if there are missing messages containing state
 * operations before the current one.
 *
 * @param h
 *        Handle for the PSYCstore.
 * @param channel_key
 *        The channel we are interested in.
 * @param message_id
 *        ID of the message that contains the @a modifiers.
 * @param state_delta
 *        Value of the _state_delta PSYC header variable of the message.
 * @param rcb
 *        Callback to call with the result of the operation.
 * @param rcb_cls
 *        Closure for the @a rcb callback.
 *
 * @return Handle that can be used to cancel the operation.
 */
struct GNUNET_PSYCSTORE_OperationHandle *
GNUNET_PSYCSTORE_state_modify (struct GNUNET_PSYCSTORE_Handle *h,
                               const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
                               uint64_t message_id,
                               uint64_t state_delta,
                               GNUNET_PSYCSTORE_ResultCallback rcb,
                               void *rcb_cls)
{
  struct GNUNET_PSYCSTORE_OperationHandle *op = NULL;
  struct StateModifyRequest *req;

  op = GNUNET_malloc (sizeof (*op) + sizeof (*req));
  op->h = h;
  op->res_cb = rcb;
  op->cls = rcb_cls;

  req = (struct StateModifyRequest *) &op[1];
  op->msg = (struct GNUNET_MessageHeader *) req;
  req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_MODIFY);
  req->header.size = htons (sizeof (*req));
  req->channel_key = *channel_key;
  req->message_id = GNUNET_htonll (message_id);
  req->state_delta = GNUNET_htonll (state_delta);

  op->op_id = get_next_op_id (h);
  req->op_id = GNUNET_htonll (op->op_id);

  GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
  transmit_next (h);

  return op;
  /* FIXME: only the last operation is returned,
   *        operation_cancel() should be able to cancel all of them.
   */
}
예제 #16
0
파일: psycstore_api.c 프로젝트: tg-x/gnunet
/**
 * Update signed values of state variables in the state store.
 *
 * @param h
 *        Handle for the PSYCstore.
 * @param channel_key
 *        The channel we are interested in.
 * @param message_id
 *        Message ID that contained the state @a hash.
 * @param hash
 *        Hash of the serialized full state.
 * @param rcb
 *        Callback to call with the result of the operation.
 * @param rcb_cls
 *        Closure for the callback.
 */
struct GNUNET_PSYCSTORE_OperationHandle *
GNUNET_PSYCSTORE_state_hash_update (struct GNUNET_PSYCSTORE_Handle *h,
                                    const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
                                    uint64_t message_id,
                                    const struct GNUNET_HashCode *hash,
                                    GNUNET_PSYCSTORE_ResultCallback rcb,
                                    void *rcb_cls)
{
  struct StateHashUpdateRequest *req;
  struct GNUNET_PSYCSTORE_OperationHandle *
    op = GNUNET_malloc (sizeof (*op) + sizeof (*req));
  op->h = h;
  op->res_cb = rcb;
  op->cls = rcb_cls;

  req = (struct StateHashUpdateRequest *) &op[1];
  op->msg = (struct GNUNET_MessageHeader *) req;
  req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_RESET);
  req->header.size = htons (sizeof (*req));
  req->channel_key = *channel_key;
  req->hash = *hash;

  op->op_id = get_next_op_id (h);
  req->op_id = GNUNET_htonll (op->op_id);

  GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
  transmit_next (h);

  return op;
}
예제 #17
0
/**
 * Request a list of running services.
 *
 * @param h handle to ARM
 * @param timeout how long to wait before failing for good
 * @param cont callback to invoke after request is sent or is not sent
 * @param cont_cls closure for callback
 */
void
GNUNET_ARM_request_service_list (struct GNUNET_ARM_Handle *h,
                                 struct GNUNET_TIME_Relative timeout,
                                 GNUNET_ARM_ServiceListCallback cont,
                                 void *cont_cls)
{
  struct ARMControlMessage *cm;
  struct GNUNET_ARM_Message *msg;

  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Requesting LIST from ARM service with timeout: %s\n",
       GNUNET_STRINGS_relative_time_to_string (timeout, GNUNET_YES));
  cm = GNUNET_new (struct ARMControlMessage);
  cm->h = h;
  cm->list_cont = cont;
  cm->cont_cls = cont_cls;
  cm->timeout = GNUNET_TIME_relative_to_absolute (timeout);
  msg = GNUNET_malloc (sizeof (struct GNUNET_ARM_Message));
  msg->header.size = htons (sizeof (struct GNUNET_ARM_Message));
  msg->header.type = htons (GNUNET_MESSAGE_TYPE_ARM_LIST);
  msg->reserved = htonl (0);
  cm->msg = msg;
  GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head,
                                    h->control_pending_tail, cm);
  cm->timeout_task_id =
      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
                                    (cm->timeout), &control_message_timeout, cm);
  trigger_next_request (h, GNUNET_NO);
}
예제 #18
0
파일: psycstore_api.c 프로젝트: tg-x/gnunet
/**
 * Retrieve latest values of counters for a channel master.
 *
 * The current value of counters are needed when a channel master is restarted,
 * so that it can continue incrementing the counters from their last value.
 *
 * @param h
 *        Handle for the PSYCstore.
 * @param channel_key
 *        Public key that identifies the channel.
 * @param ccb
 *        Callback to call with the result.
 * @param ccb_cls
 *        Closure for the @a ccb callback.
 *
 * @return Handle that can be used to cancel the operation.
 */
struct GNUNET_PSYCSTORE_OperationHandle *
GNUNET_PSYCSTORE_counters_get (struct GNUNET_PSYCSTORE_Handle *h,
                               struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
                               GNUNET_PSYCSTORE_CountersCallback ccb,
                               void *ccb_cls)
{
  struct OperationRequest *req;
  struct GNUNET_PSYCSTORE_OperationHandle *
    op = GNUNET_malloc (sizeof (*op) + sizeof (*req));
  op->h = h;
  op->data_cb = ccb;
  op->cls = ccb_cls;

  req = (struct OperationRequest *) &op[1];
  op->msg = (struct GNUNET_MessageHeader *) req;
  req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_COUNTERS_GET);
  req->header.size = htons (sizeof (*req));
  req->channel_key = *channel_key;

  op->op_id = get_next_op_id (h);
  req->op_id = GNUNET_htonll (op->op_id);

  GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
  transmit_next (h);

  return op;
}
예제 #19
0
/**
 * Creates a new cache entry and then puts it into the cache's hashtable.
 *
 * @param peer_id the index of the peer to tag the newly created entry
 * @return the newly created entry
 */
static struct CacheEntry *
add_entry (unsigned int peer_id)
{
  struct CacheEntry *entry;

  GNUNET_assert (NULL != cache);
  if (cache_size == GNUNET_CONTAINER_multihashmap32_size (cache))
  {
    /* remove the LRU head */
    entry = cache_head;
    GNUNET_assert (GNUNET_OK ==
                   GNUNET_CONTAINER_multihashmap32_remove (cache, (uint32_t)
                                                           entry->peer_id,
                                                           entry));
    free_entry (entry);
  }
  entry = GNUNET_new (struct CacheEntry);
  entry->peer_id = peer_id;
  GNUNET_assert (GNUNET_OK ==
                 GNUNET_CONTAINER_multihashmap32_put (cache,
                                                      (uint32_t) peer_id,
                                                      entry,
                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
  GNUNET_CONTAINER_DLL_insert_tail (cache_head, cache_tail, entry);
  return entry;
}
예제 #20
0
/**
 * Try to open a connection to the given neigbour.  If the connection is open
 * already, then it is re-used.  If not, the request is queued in the operation
 * queues responsible for bounding the total number of file descriptors.  The
 * actual connection will happen when the operation queue marks the
 * corresponding operation as active.
 *
 * @param n the neighbour to open a connection to
 * @param cb the notification callback to call when the connection is opened
 * @param cb_cls the closure for the above callback
 */
struct NeighbourConnectNotification *
GST_neighbour_get_connection (struct Neighbour *n,
                              GST_NeigbourConnectNotifyCallback cb,
                              void *cb_cls)
{
  struct NeighbourConnectNotification *h;

  GNUNET_assert (NULL != cb);
  LOG_DEBUG ("Attempting to get connection to controller on host %u\n",
             n->host_id);
  h = GNUNET_new (struct NeighbourConnectNotification);
  h->n = n;
  h->cb  = cb;
  h->cb_cls = cb_cls;
  GNUNET_CONTAINER_DLL_insert_tail (n->nl_head, n->nl_tail, h);
  if (NULL == n->conn_op)
  {
    GNUNET_assert (NULL == n->controller);
    n->conn_op = GNUNET_TESTBED_operation_create_ (n, &opstart_neighbour_conn,
                                                   &oprelease_neighbour_conn);
    GNUNET_TESTBED_operation_queue_insert_ (GST_opq_openfds, n->conn_op);
    GNUNET_TESTBED_operation_begin_wait_ (n->conn_op);
    return h;
  }
  trigger_notifications (n);
  return h;
}
예제 #21
0
파일: psycstore_api.c 프로젝트: tg-x/gnunet
/**
 * Test if a member was admitted to the channel at the given message ID.
 *
 * This is useful when relaying and replaying messages to check if a particular
 * slave has access to the message fragment with a given group generation.  It
 * is also used when handling join requests to determine whether the slave is
 * currently admitted to the channel.
 *
 * @param h
 *        Handle for the PSYCstore.
 * @param channel_key
 *        The channel we are interested in.
 * @param slave_key
 *        Public key of slave whose membership to check.
 * @param message_id
 *        Message ID for which to do the membership test.
 * @param group_generation
 *        Group generation of the fragment of the message to test.
 *        It has relevance if the message consists of multiple fragments with
 *        different group generations.
 * @param rcb
 *        Callback to call with the test result.
 * @param rcb_cls
 *        Closure for the callback.
 *
 * @return Operation handle that can be used to cancel the operation.
 */
struct GNUNET_PSYCSTORE_OperationHandle *
GNUNET_PSYCSTORE_membership_test (struct GNUNET_PSYCSTORE_Handle *h,
                                  const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key,
                                  const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
                                  uint64_t message_id,
                                  uint64_t group_generation,
                                  GNUNET_PSYCSTORE_ResultCallback rcb,
                                  void *rcb_cls)
{
  struct MembershipTestRequest *req;
  struct GNUNET_PSYCSTORE_OperationHandle *
    op = GNUNET_malloc (sizeof (*op) + sizeof (*req));
  op->h = h;
  op->res_cb = rcb;
  op->cls = rcb_cls;

  req = (struct MembershipTestRequest *) &op[1];
  op->msg = (struct GNUNET_MessageHeader *) req;
  req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_TEST);
  req->header.size = htons (sizeof (*req));
  req->channel_key = *channel_key;
  req->slave_key = *slave_key;
  req->message_id = GNUNET_htonll (message_id);
  req->group_generation = GNUNET_htonll (group_generation);

  op->op_id = get_next_op_id (h);
  req->op_id = GNUNET_htonll (op->op_id);

  GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op);
  transmit_next (h);

  return op;
}
예제 #22
0
/**
 * Perform an authority lookup for a given name.
 *
 * @param handle handle to the GNS service
 * @param name the name to look up authority for
 * @param proc function to call on result
 * @param proc_cls closure for processor
 * @return handle to the operation
 */
struct GNUNET_GNS_GetAuthRequest*
GNUNET_GNS_get_authority (struct GNUNET_GNS_Handle *handle,
			  const char *name,
			  GNUNET_GNS_GetAuthResultProcessor proc,
			  void *proc_cls)
{
  struct GNUNET_GNS_ClientGetAuthMessage *get_auth_msg;
  struct GNUNET_GNS_GetAuthRequest *gar;
  size_t msize;
  struct PendingMessage *pending;

  if (NULL == name)
  {
    GNUNET_break (0);
    return NULL;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Trying to look up authority for %s in GNS\n", name);
  msize = sizeof (struct GNUNET_GNS_ClientGetAuthMessage) + strlen (name) + 1;
  if (msize > UINT16_MAX)
  {
    GNUNET_break (0);
    return NULL;
  }
  gar = GNUNET_malloc (sizeof (struct GNUNET_GNS_GetAuthRequest) +
		       sizeof (struct PendingMessage) + msize);
  gar->gns_handle = handle;
  gar->auth_proc = proc;
  gar->proc_cls = proc_cls;
  gar->r_id = handle->r_id_gen++;
  GNUNET_CONTAINER_DLL_insert_tail (handle->get_auth_head,
                                    handle->get_auth_tail, gar);

  pending = (struct PendingMessage *) &gar[1];
  pending->size = msize;
  pending->r_id = gar->r_id;
  get_auth_msg = (struct GNUNET_GNS_ClientGetAuthMessage *) &pending[1];
  get_auth_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_GET_AUTH);
  get_auth_msg->header.size = htons (msize);
  get_auth_msg->id = htonl (gar->r_id);
  memcpy (&get_auth_msg[1], name, strlen (name) + 1);
  GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head, 
				    handle->pending_tail,
				    pending);
  process_pending_messages (handle);
  return gar;
}
/**
 * Add a PendingMessage to the clients list of messages to be sent
 *
 * @param client the active client to send the message to
 * @param pending_message the actual message to send
 */
static void
add_pending_message (struct ClientList *client,
                     struct PendingMessage *pending_message)
{
  GNUNET_CONTAINER_DLL_insert_tail (client->pending_head, client->pending_tail,
                                    pending_message);
  process_pending_messages (client);
}
예제 #24
0
/**
 * This function is called *before* the DNS request has been 
 * given to a "local" DNS resolver.  Tunneling for DNS requests
 * was enabled, so we now need to send the request via some MESH
 * tunnel to a DNS EXIT for resolution.
 *
 * @param cls closure
 * @param rh request handle to user for reply
 * @param request_length number of bytes in request
 * @param request udp payload of the DNS request
 */
static void 
dns_pre_request_handler (void *cls,
			 struct GNUNET_DNS_RequestHandle *rh,
			 size_t request_length,
			 const char *request)
{
  struct RequestContext *rc;
  size_t mlen;
  struct GNUNET_MessageHeader hdr;
  struct GNUNET_TUN_DnsHeader dns;

  GNUNET_STATISTICS_update (stats,
			    gettext_noop ("# DNS requests intercepted"),
			    1, GNUNET_NO);
  if (0 == dns_exit_available)
  {
    GNUNET_STATISTICS_update (stats,
			      gettext_noop ("# DNS requests dropped (DNS mesh tunnel down)"),
			      1, GNUNET_NO);
    GNUNET_DNS_request_drop (rh);
    return;
  }
  if (request_length < sizeof (dns))
  {
    GNUNET_STATISTICS_update (stats,
			      gettext_noop ("# DNS requests dropped (malformed)"),
			      1, GNUNET_NO);
    GNUNET_DNS_request_drop (rh);
    return;
  }
  memcpy (&dns, request, sizeof (dns));
  GNUNET_assert (NULL != mesh_tunnel);
  mlen = sizeof (struct GNUNET_MessageHeader) + request_length;
  rc = GNUNET_malloc (sizeof (struct RequestContext) + mlen);
  rc->rh = rh;
  rc->mesh_message = (const struct GNUNET_MessageHeader*) &rc[1];
  rc->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
						   &timeout_request,
						   rc);
  rc->dns_id = dns.id;
  hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET);
  hdr.size = htons (mlen);
  memcpy (&rc[1], &hdr, sizeof (struct GNUNET_MessageHeader));
  memcpy (&(((char*)&rc[1])[sizeof (struct GNUNET_MessageHeader)]),
	  request,
	  request_length);
  GNUNET_CONTAINER_DLL_insert_tail (transmit_queue_head,
				    transmit_queue_tail,
				    rc);
  if (NULL == mesh_th)
    mesh_th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel,
						 GNUNET_NO, 0,
						 TIMEOUT,
						 NULL, mlen,
						 &transmit_dns_request_to_mesh,
						 NULL);
}
예제 #25
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;
}
예제 #26
0
/**
 * Get an IP address as a string.
 *
 * @param sa host address
 * @param salen length of host address in @a sa
 * @param do_resolve use #GNUNET_NO to return numeric hostname
 * @param timeout how long to try resolving
 * @param callback function to call with hostnames
 *        last callback is NULL when finished
 * @param cls closure for @a callback
 * @return handle that can be used to cancel the request
 */
struct GNUNET_RESOLVER_RequestHandle *
GNUNET_RESOLVER_hostname_get (const struct sockaddr *sa,
                              socklen_t salen,
                              int do_resolve,
                              struct GNUNET_TIME_Relative timeout,
                              GNUNET_RESOLVER_HostnameCallback callback,
                              void *cls)
{
    struct GNUNET_RESOLVER_RequestHandle *rh;
    size_t ip_len;
    const void *ip;

    check_config ();
    switch (sa->sa_family)
    {
    case AF_INET:
        GNUNET_assert (salen == sizeof (struct sockaddr_in));
        ip_len = sizeof (struct in_addr);
        ip = &((const struct sockaddr_in*)sa)->sin_addr;
        break;
    case AF_INET6:
        GNUNET_assert (salen == sizeof (struct sockaddr_in6));
        ip_len = sizeof (struct in6_addr);
        ip = &((const struct sockaddr_in6*)sa)->sin6_addr;
        break;
    default:
        GNUNET_break (0);
        return NULL;
    }
    rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + salen);
    rh->name_callback = callback;
    rh->cls = cls;
    rh->af = sa->sa_family;
    rh->timeout = GNUNET_TIME_relative_to_absolute (timeout);
    memcpy (&rh[1], ip, ip_len);
    rh->data_len = ip_len;
    rh->direction = GNUNET_YES;
    rh->received_response = GNUNET_NO;
    if (GNUNET_NO == do_resolve)
    {
        rh->task = GNUNET_SCHEDULER_add_now (&numeric_reverse, rh);
        return rh;
    }
    GNUNET_CONTAINER_DLL_insert_tail (req_head,
                                      req_tail,
                                      rh);
    rh->was_queued = GNUNET_YES;
    if (NULL != s_task)
    {
        GNUNET_SCHEDULER_cancel (s_task);
        s_task = NULL;
    }
    process_requests ();
    return rh;
}
/**
 * Add a new message to the queue to be sent to the given client peer.
 *
 * @param msg Message to be queued
 * @param cp Client peer context
 */
static void
queue_msg (struct GNUNET_MessageHeader *msg, struct ClientPeerContext *cp)
{
  struct PendingMessage *pm;

  pm = GNUNET_new (struct PendingMessage);

  pm->msg = msg;
  GNUNET_CONTAINER_DLL_insert_tail (cp->pm_head, cp->pm_tail, pm);
  trigger_send_next_msg (cp);
}
예제 #28
0
파일: dv_api.c 프로젝트: tg-x/gnunet
/**
 * Send a message via DV service.
 *
 * @param sh service handle
 * @param target intended recpient
 * @param msg message payload
 * @param cb function to invoke when done
 * @param cb_cls closure for @a cb
 * @return handle to cancel the operation
 */
struct GNUNET_DV_TransmitHandle *
GNUNET_DV_send (struct GNUNET_DV_ServiceHandle *sh,
		const struct GNUNET_PeerIdentity *target,
		const struct GNUNET_MessageHeader *msg,
		GNUNET_DV_MessageSentCallback cb,
		void *cb_cls)
{
  struct GNUNET_DV_TransmitHandle *th;
  struct GNUNET_DV_SendMessage *sm;
  struct ConnectedPeer *peer;

  if (ntohs (msg->size) + sizeof (struct GNUNET_DV_SendMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
  {
    GNUNET_break (0);
    return NULL;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Asked to send %u bytes of type %u to %s via %p\n",
       (unsigned int) ntohs (msg->size),
       (unsigned int) ntohs (msg->type),
       GNUNET_i2s (target),
       sh->client);
  peer = GNUNET_CONTAINER_multipeermap_get (sh->peers,
                                            target);
  if (NULL == peer)
  {
    GNUNET_break (0);
    return NULL;
  }
  th = GNUNET_malloc (sizeof (struct GNUNET_DV_TransmitHandle) +
		      sizeof (struct GNUNET_DV_SendMessage) +
		      ntohs (msg->size));
  th->sh = sh;
  th->target = peer;
  th->cb = cb;
  th->cb_cls = cb_cls;
  th->msg = (const struct GNUNET_MessageHeader *) &th[1];
  sm = (struct GNUNET_DV_SendMessage *) &th[1];
  sm->header.type = htons (GNUNET_MESSAGE_TYPE_DV_SEND);
  sm->header.size = htons (sizeof (struct GNUNET_DV_SendMessage) +
			   ntohs (msg->size));
  if (0 == sh->uid_gen)
    sh->uid_gen = 1;
  th->uid = sh->uid_gen;
  sm->uid = htonl (sh->uid_gen++);
  /* use memcpy here as 'target' may not be sufficiently aligned */
  memcpy (&sm->target, target, sizeof (struct GNUNET_PeerIdentity));
  memcpy (&sm[1], msg, ntohs (msg->size));
  GNUNET_CONTAINER_DLL_insert_tail (sh->th_head,
                                    sh->th_tail,
                                    th);
  start_transmit (sh);
  return th;
}
예제 #29
0
/**
 * Convert a string to one or more IP addresses.
 *
 * @param hostname the hostname to resolve
 * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any"
 * @param callback function to call with addresses
 * @param callback_cls closure for callback
 * @param timeout how long to try resolving
 * @return handle that can be used to cancel the request, NULL on error
 */
struct GNUNET_RESOLVER_RequestHandle *
GNUNET_RESOLVER_ip_get (const char *hostname, int af,
                        struct GNUNET_TIME_Relative timeout,
                        GNUNET_RESOLVER_AddressCallback callback,
                        void *callback_cls)
{
  struct GNUNET_RESOLVER_RequestHandle *rh;
  size_t slen;
  unsigned int i;
  struct in_addr v4;
  struct in6_addr v6;

  slen = strlen (hostname) + 1;
  if (slen + sizeof (struct GNUNET_RESOLVER_GetMessage) >=
      GNUNET_SERVER_MAX_MESSAGE_SIZE)
  {
    GNUNET_break (0);
    return NULL;
  }
  rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + slen);
  rh->af = af;
  rh->addr_callback = callback;
  rh->cls = callback_cls;
  memcpy (&rh[1], hostname, slen);
  rh->data_len = slen;
  rh->timeout = GNUNET_TIME_relative_to_absolute (timeout);
  rh->direction = GNUNET_NO;
  /* first, check if this is a numeric address */
  if (((1 == inet_pton (AF_INET, hostname, &v4)) &&
       ((af == AF_INET) || (af == AF_UNSPEC))) ||
      ((1 == inet_pton (AF_INET6, hostname, &v6)) &&
       ((af == AF_INET6) || (af == AF_UNSPEC))))
  {
    rh->task = GNUNET_SCHEDULER_add_now (&numeric_resolution, rh);
    return rh;
  }
  /* then, check if this is a loopback address */
  i = 0;
  while (loopback[i] != NULL)
    if (0 == strcasecmp (loopback[i++], hostname))
    {
      rh->task = GNUNET_SCHEDULER_add_now (&loopback_resolution, rh);
      return rh;
    }
  GNUNET_CONTAINER_DLL_insert_tail (req_head, req_tail, rh);
  rh->was_queued = GNUNET_YES;
  if (s_task != GNUNET_SCHEDULER_NO_TASK)
  {
    GNUNET_SCHEDULER_cancel (s_task);
    s_task = GNUNET_SCHEDULER_NO_TASK;
  }
  process_requests ();
  return rh;
}
/**
 * Obtain statistics and/or change preferences for the given peer.
 *
 * @param h core handle
 * @param peer identifies the peer
 * @param amount reserve N bytes for receiving, negative
 *                amounts can be used to undo a (recent) reservation;
 * @param preference increase incoming traffic share preference by this amount;
 *                in the absence of "amount" reservations, we use this
 *                preference value to assign proportional bandwidth shares
 *                to all connected peers
 * @param info function to call with the resulting configuration information
 * @param info_cls closure for info
 * @return NULL on error
 */
struct GNUNET_ATS_InformationRequestContext *
GNUNET_ATS_peer_change_preference (struct GNUNET_ATS_SchedulingHandle *h,
                                   const struct GNUNET_PeerIdentity *peer,
                                   int32_t amount, uint64_t preference,
                                   GNUNET_ATS_PeerConfigurationInfoCallback
                                   info, void *info_cls)
{
  struct GNUNET_ATS_InformationRequestContext *irc;
  struct PeerRecord *pr;
  struct RequestInfoMessage *rim;
  struct ControlMessage *cm;

  pr = GNUNET_CONTAINER_multihashmap_get (h->peers, &peer->hashPubKey);
  if (NULL == pr)
  {
    /* attempt to change preference on peer that is not connected */
    GNUNET_assert (0);
    return NULL;
  }
  if (pr->pcic != NULL)
  {
    /* second change before first one is done */
    GNUNET_break (0);
    return NULL;
  }
  irc = GNUNET_malloc (sizeof (struct GNUNET_ATS_InformationRequestContext));
  irc->h = h;
  irc->pr = pr;
  cm = GNUNET_malloc (sizeof (struct ControlMessage) +
                      sizeof (struct RequestInfoMessage));
  cm->cont = &change_preference_send_continuation;
  cm->cont_cls = irc;
  irc->cm = cm;
  rim = (struct RequestInfoMessage *) &cm[1];
  rim->header.size = htons (sizeof (struct RequestInfoMessage));
  rim->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_REQUEST_INFO);
  rim->rim_id = htonl (pr->rim_id = h->rim_id_gen++);
  rim->reserved = htonl (0);
  rim->reserve_inbound = htonl (amount);
  rim->preference_change = GNUNET_htonll (preference);
  rim->peer = *peer;
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Queueing CHANGE PREFERENCE request for peer `%s' with RIM %u\n",
              GNUNET_i2s (peer), (unsigned int) pr->rim_id);
  GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head,
                                    h->control_pending_tail, cm);
  pr->pcic = info;
  pr->pcic_cls = info_cls;
  pr->pcic_ptr = irc;           /* for free'ing irc */
  if (NULL != h->client)
    trigger_next_request (h, GNUNET_NO);
  return irc;
}