/**
 * Output information of validation entries to the given client.
 *
 * @param cls the 'struct IterationContext'
 * @param peer identity of the neighbour
 * @param address the address
 * @param last_validation point in time when last validation was performed
 * @param valid_until point in time how long address is valid
 * @param next_validation point in time when next validation will be performed
 * @param state state of validation notification
 */
static void
send_validation_information (void *cls,
    const struct GNUNET_PeerIdentity *peer,
    const struct GNUNET_HELLO_Address *address,
    struct GNUNET_TIME_Absolute last_validation,
    struct GNUNET_TIME_Absolute valid_until,
    struct GNUNET_TIME_Absolute next_validation,
    enum GNUNET_TRANSPORT_ValidationState state)
{
  struct IterationContext *pc = cls;
  struct ValidationIterateResponseMessage *msg;

  if ( (GNUNET_YES == pc->all) ||
       (0 == memcmp (peer, &pc->id, sizeof (pc->id))) )
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
        "Sending information about for validation entry for peer `%s' using address `%s'\n",
        GNUNET_i2s(peer), (address != NULL) ? GST_plugins_a2s (address) : "<none>");
    msg = compose_validation_iterate_response_message (peer, address);
    msg->last_validation = GNUNET_TIME_absolute_hton(last_validation);
    msg->valid_until = GNUNET_TIME_absolute_hton(valid_until);
    msg->next_validation = GNUNET_TIME_absolute_hton(next_validation);
    msg->state = htonl ((uint32_t) state);
    GNUNET_SERVER_transmit_context_append_message (pc->tc, &msg->header);
    GNUNET_free (msg);
  }
}
static size_t
node_experiment_start_cb (void *cls, size_t bufsize, void *buf)
{
	struct NodeComCtx *e_ctx = cls;
	struct GED_start_message *msg;
	size_t name_len;
	size_t size;

	if (NULL == buf)
		return 0;

	name_len = strlen(e_ctx->e->name) + 1;
	size = sizeof (struct GED_start_message) + name_len;

	msg = GNUNET_malloc (size);
	msg->header.size = htons (size);
	msg->header.type = htons (GNUNET_MESSAGE_TYPE_EXPERIMENTATION_START);
	msg->issuer = e_ctx->e->issuer;
	msg->version_nbo = GNUNET_TIME_absolute_hton(e_ctx->e->version);
	msg->len_name = htonl (name_len);
	memcpy (&msg[1], e_ctx->e->name, name_len);

	memcpy (buf, msg, size);
	GNUNET_free (msg);
	return size;
}
/**
 * Broadcast the new active address to all clients monitoring the peer.
 *
 * @param peer peer this update is about (never NULL)
 * @param address address, NULL on disconnect
 * @param state the current state of the peer
 * @param state_timeout the time out for the state
 */
void
GST_clients_broadcast_peer_notification (const struct GNUNET_PeerIdentity *peer,
    const struct GNUNET_HELLO_Address *address,
    enum GNUNET_TRANSPORT_PeerState state,
    struct GNUNET_TIME_Absolute state_timeout)
{
  struct PeerIterateResponseMessage *msg;
  struct MonitoringClient *mc;
  static struct GNUNET_PeerIdentity all_zeros;
  msg = compose_address_iterate_response_message (peer, address);
  msg->state = htonl (state);
  msg->state_timeout = GNUNET_TIME_absolute_hton (state_timeout);
  mc = peer_monitoring_clients_head;
  while (mc != NULL)
  {
    if ((0 == memcmp (&mc->peer, &all_zeros,
                      sizeof (struct GNUNET_PeerIdentity))) ||
        (0 == memcmp (&mc->peer, peer,
                      sizeof (struct GNUNET_PeerIdentity))))
    {
      GNUNET_SERVER_notification_context_unicast (peer_nc, mc->client,
                                                  &msg->header, GNUNET_NO);
    }

    mc = mc->next;
  }
  GNUNET_free (msg);
}
Пример #4
0
/**
 * Setup a flood message in our history array at the given
 * slot offset for the given timestamp.
 *
 * @param slot index to use
 * @param ts timestamp to use
 */
static void
setup_flood_message (unsigned int slot,
		     struct GNUNET_TIME_Absolute ts)
{
  struct GNUNET_NSE_FloodMessage *fm;
  uint32_t matching_bits;

  matching_bits = get_matching_bits (ts,
				     &my_identity);
  fm = &size_estimate_messages[slot];
  fm->header.size = htons (sizeof (struct GNUNET_NSE_FloodMessage));
  fm->header.type = htons (GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD);
  fm->hop_count = htonl (0);
  fm->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_NSE_SEND);
  fm->purpose.size =
      htonl (sizeof (struct GNUNET_NSE_FloodMessage) -
             sizeof (struct GNUNET_MessageHeader) - sizeof (uint32_t) -
             sizeof (struct GNUNET_CRYPTO_EddsaSignature));
  fm->matching_bits = htonl (matching_bits);
  fm->timestamp = GNUNET_TIME_absolute_hton (ts);
  fm->origin = my_identity;
  fm->proof_of_work = my_proof;
  if (nse_work_required > 0)
    GNUNET_assert (GNUNET_OK ==
                   GNUNET_CRYPTO_eddsa_sign (my_private_key,
					     &fm->purpose,
					     &fm->signature));
  else
    memset (&fm->signature,
	    0,
	    sizeof (fm->signature));
}
/**
 * Output information of neighbours to the given client.
 *
 * @param cls the 'struct PeerIterationContext'
 * @param peer identity of the neighbour
 * @param address the address
 * @param state current state this peer is in
 * @param state_timeout timeout for the current state of the peer
 * @param bandwidth_in inbound quota in NBO
 * @param bandwidth_out outbound quota in NBO
 */
static void
send_peer_information (void *cls,
    const struct GNUNET_PeerIdentity *peer,
    const struct GNUNET_HELLO_Address *address,
    enum GNUNET_TRANSPORT_PeerState state,
    struct GNUNET_TIME_Absolute state_timeout,
    struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
    struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
{
  struct IterationContext *pc = cls;
  struct PeerIterateResponseMessage *msg;

  if ( (GNUNET_YES == pc->all) ||
       (0 == memcmp (peer, &pc->id, sizeof (pc->id))) )
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
        "Sending information about `%s' using address `%s' in state `%s'\n",
        GNUNET_i2s(peer),
        (address != NULL) ? GST_plugins_a2s (address) : "<none>",
        GNUNET_TRANSPORT_ps2s (state));
    msg = compose_address_iterate_response_message (peer, address);
    msg->state = htonl (state);
    msg->state_timeout = GNUNET_TIME_absolute_hton(state_timeout);
    GNUNET_SERVER_transmit_context_append_message (pc->tc, &msg->header);
    GNUNET_free (msg);
  }
}
Пример #6
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;
}
/**
 * Process a datum that was stored in the datastore.
 *
 * @param cls closure with the struct StreamClient which sent the query
 * @param key key for the content
 * @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 expiration expiration time for the content
 * @param uid unique identifier for the datum;
 *        maybe 0 if no unique identifier is available
 */
static void 
handle_datastore_reply (void *cls,
			const struct GNUNET_HashCode * key,
			size_t size, const void *data,
			enum GNUNET_BLOCK_Type type,
			uint32_t priority,
			uint32_t anonymity,
			struct GNUNET_TIME_Absolute
			expiration, uint64_t uid)
{
  struct StreamClient *sc = cls;
  size_t msize = size + sizeof (struct StreamReplyMessage);
  char buf[msize] GNUNET_ALIGN;
  struct StreamReplyMessage *srm = (struct StreamReplyMessage *) buf;

  sc->qe = NULL;
  if (GNUNET_BLOCK_TYPE_FS_ONDEMAND == type)
  {
    if (GNUNET_OK !=
	GNUNET_FS_handle_on_demand_block (key,
					  size, data, type,
					  priority, anonymity,
					  expiration, uid,
					  &handle_datastore_reply,
					  sc))
    {
      continue_reading (sc);
    }
    return;
  }
  if (msize > GNUNET_SERVER_MAX_MESSAGE_SIZE)
  {
    GNUNET_break (0);
    continue_reading (sc);
    return;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
	      "Starting transmission of %u byte reply via stream\n",
	      (unsigned int) size);
  srm->header.size = htons ((uint16_t) msize);
  srm->header.type = htons (GNUNET_MESSAGE_TYPE_FS_STREAM_REPLY);
  srm->type = htonl (type);
  srm->expiration = GNUNET_TIME_absolute_hton (expiration);
  memcpy (&srm[1], data, size);
  sc->reply_size = msize;
  sc->wh = GNUNET_STREAM_write (sc->socket,
				buf, msize,
				GNUNET_TIME_UNIT_FOREVER_REL,
				&write_continuation,
				sc);
  if (NULL == sc->wh)
  {
    terminate_stream (sc);
    return;
  }
}
Пример #8
0
/**
 * Transmit a send-message request to the chat service.
 *
 * @param cls closure, pointer to the 'struct GNUNET_CHAT_SendMessageContext'
 * @param size number of bytes available in buf
 * @param buf where the callee should write the message
 * @return number of bytes written to buf
 */
static size_t
transmit_send_request (void *cls, size_t size, void *buf)
{
  struct GNUNET_CHAT_SendMessageContext *smc = cls;
  struct TransmitRequestMessage *msg_to_send;
  size_t msg_size;

  if (NULL == buf)
  {
#if DEBUG_CHAT
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Could not transmit a chat message\n");
#endif
    return 0;
  }
#if DEBUG_CHAT
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Transmitting a chat message to the service\n");
#endif
  msg_size = strlen (smc->message) + sizeof (struct TransmitRequestMessage);
  GNUNET_assert (size >= msg_size);
  msg_to_send = buf;
  msg_to_send->header.size = htons (msg_size);
  msg_to_send->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_TRANSMIT_REQUEST);
  msg_to_send->msg_options = htonl (smc->options);
  msg_to_send->sequence_number = htonl (smc->sequence_number);
  msg_to_send->timestamp =
      GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
  msg_to_send->reserved = htonl (0);
  if (NULL == smc->receiver)
    memset (&msg_to_send->target, 0, sizeof (GNUNET_HashCode));
  else
    GNUNET_CRYPTO_hash (smc->receiver,
                        sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
                        &msg_to_send->target);
  memcpy (&msg_to_send[1], smc->message, strlen (smc->message));
  /**
   * Client don't encode private messages since public keys of other members are
   * stored on the service side.
   */
  if (smc->options & GNUNET_CHAT_MSG_AUTHENTICATED)
  {
    msg_to_send->purpose.purpose =
        htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
    msg_to_send->purpose.size =
        htonl (msg_size - sizeof (struct GNUNET_MessageHeader) -
               sizeof (struct GNUNET_CRYPTO_RsaSignature));
    GNUNET_assert (GNUNET_OK ==
                   GNUNET_CRYPTO_rsa_sign (smc->chat_room->my_private_key,
                                           &msg_to_send->purpose,
                                           &msg_to_send->signature));
  }
  GNUNET_free (smc->message);
  GNUNET_free (smc);
  return msg_size;
}
Пример #9
0
/**
 * Sign name and records
 *
 * @param key the private key
 * @param expire block expiration
 * @param name the name
 * @param rd record data
 * @param rd_count number of records
 *
 * @return the signature
 */
struct GNUNET_CRYPTO_RsaSignature *
GNUNET_NAMESTORE_create_signature (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
				   struct GNUNET_TIME_Absolute expire,
				   const char *name,
				   const struct GNUNET_NAMESTORE_RecordData *rd,
				   unsigned int rd_count)
{
  struct GNUNET_CRYPTO_RsaSignature *sig;
  struct GNUNET_CRYPTO_RsaSignaturePurpose *sig_purpose;
  struct GNUNET_TIME_AbsoluteNBO expire_nbo;
  size_t rd_ser_len;
  size_t name_len;
  struct GNUNET_TIME_AbsoluteNBO *expire_tmp;
  char * name_tmp;
  char * rd_tmp;
  int res;
  uint32_t sig_len;

  if (NULL == name)
  {
    GNUNET_break (0);
    return NULL;
  }
  sig = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaSignature));
  name_len = strlen (name) + 1;
  expire_nbo = GNUNET_TIME_absolute_hton (expire);
  rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
  {
    char rd_ser[rd_ser_len];

    GNUNET_assert (rd_ser_len ==
		   GNUNET_NAMESTORE_records_serialize (rd_count, rd, rd_ser_len, rd_ser));
    sig_len = sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + rd_ser_len + name_len;
    sig_purpose = GNUNET_malloc (sig_len);
    sig_purpose->size = htonl (sig_len);
    sig_purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
    expire_tmp = (struct GNUNET_TIME_AbsoluteNBO *) &sig_purpose[1];
    memcpy (expire_tmp, &expire_nbo, sizeof (struct GNUNET_TIME_AbsoluteNBO));
    name_tmp = (char *) &expire_tmp[1];
    memcpy (name_tmp, name, name_len);
    rd_tmp = &name_tmp[name_len];
    memcpy (rd_tmp, rd_ser, rd_ser_len);
    res = GNUNET_CRYPTO_rsa_sign (key, sig_purpose, sig);
    GNUNET_free (sig_purpose);
  }
  if (GNUNET_OK != res)
  {
    GNUNET_break (0);
    GNUNET_free (sig);
    return NULL;
  }
  return sig;
}
Пример #10
0
/**
 * Store an item in the datastore.  If the item is already present,
 * the priorities are summed up and the higher expiration time and
 * lower anonymity level is used.
 *
 * @param h handle to the datastore
 * @param rid reservation ID to use (from "reserve"); use 0 if no
 *            prior reservation was made
 * @param key key for the value
 * @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 how often should the content be replicated to other peers?
 * @param expiration expiration time for the content
 * @param queue_priority ranking of this request in the priority queue
 * @param max_queue_size at what queue size should this request be dropped
 *        (if other requests of higher priority are in the queue)
 * @param timeout timeout for the operation
 * @param cont continuation to call when done
 * @param cont_cls closure for cont
 * @return NULL if the entry was not queued, otherwise a handle that can be used to
 *         cancel; note that even if NULL is returned, the callback will be invoked
 *         (or rather, will already have been invoked)
 */
struct GNUNET_DATASTORE_QueueEntry *
GNUNET_DATASTORE_put (struct GNUNET_DATASTORE_Handle *h, uint32_t rid,
                      const struct GNUNET_HashCode * key, size_t size,
                      const void *data, enum GNUNET_BLOCK_Type type,
                      uint32_t priority, uint32_t anonymity,
                      uint32_t replication,
                      struct GNUNET_TIME_Absolute expiration,
                      unsigned int queue_priority, unsigned int max_queue_size,
                      struct GNUNET_TIME_Relative timeout,
                      GNUNET_DATASTORE_ContinuationWithStatus cont,
                      void *cont_cls)
{
  struct GNUNET_DATASTORE_QueueEntry *qe;
  struct DataMessage *dm;
  size_t msize;
  union QueueContext qc;

  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Asked to put %u bytes of data under key `%s' for %llu ms\n", size,
       GNUNET_h2s (key),
       GNUNET_TIME_absolute_get_remaining (expiration).rel_value);
  msize = sizeof (struct DataMessage) + size;
  GNUNET_assert (msize < GNUNET_SERVER_MAX_MESSAGE_SIZE);
  qc.sc.cont = cont;
  qc.sc.cont_cls = cont_cls;
  qe = make_queue_entry (h, msize, queue_priority, max_queue_size, timeout,
                         &process_status_message, &qc);
  if (qe == NULL)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG, "Could not create queue entry for PUT\n");
    return NULL;
  }
  GNUNET_STATISTICS_update (h->stats, gettext_noop ("# PUT requests executed"),
                            1, GNUNET_NO);
  dm = (struct DataMessage *) &qe[1];
  dm->header.type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_PUT);
  dm->header.size = htons (msize);
  dm->rid = htonl (rid);
  dm->size = htonl ((uint32_t) size);
  dm->type = htonl (type);
  dm->priority = htonl (priority);
  dm->anonymity = htonl (anonymity);
  dm->replication = htonl (replication);
  dm->reserved = htonl (0);
  dm->uid = GNUNET_htonll (0);
  dm->expiration = GNUNET_TIME_absolute_hton (expiration);
  dm->key = *key;
  memcpy (&dm[1], data, size);
  process_queue (h);
  return qe;
}
/**
 * Broadcast the new validation changes to all clients monitoring the peer.
 *
 * @param peer peer this update is about (never NULL)
 * @param address address, NULL on disconnect
 * @param last_validation point in time when last validation was performed
 * @param valid_until point in time how long address is valid
 * @param next_validation point in time when next validation will be performed
 * @param state state of validation notification
 */
void
GST_clients_broadcast_validation_notification (
    const struct GNUNET_PeerIdentity *peer,
    const struct GNUNET_HELLO_Address *address,
    struct GNUNET_TIME_Absolute last_validation,
    struct GNUNET_TIME_Absolute valid_until,
    struct GNUNET_TIME_Absolute next_validation,
    enum GNUNET_TRANSPORT_ValidationState state)
{
  struct ValidationIterateResponseMessage *msg;
  struct MonitoringClient *mc;
  static struct GNUNET_PeerIdentity all_zeros;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
      "Sending information about for validation entry for peer `%s' using address `%s'\n",
      GNUNET_i2s(peer), (address != NULL) ? GST_plugins_a2s (address) : "<none>");

  msg = compose_validation_iterate_response_message (peer, address);
  msg->last_validation = GNUNET_TIME_absolute_hton(last_validation);
  msg->valid_until = GNUNET_TIME_absolute_hton(valid_until);
  msg->next_validation = GNUNET_TIME_absolute_hton(next_validation);
  msg->state = htonl ((uint32_t) state);
  mc = val_monitoring_clients_head;
  while (mc != NULL)
  {
    if ((0 == memcmp (&mc->peer, &all_zeros,
                      sizeof (struct GNUNET_PeerIdentity))) ||
        (0 == memcmp (&mc->peer, peer,
                      sizeof (struct GNUNET_PeerIdentity))))
    {
      GNUNET_SERVER_notification_context_unicast (val_nc, mc->client,
                                                  &msg->header, GNUNET_NO);

    }
    mc = mc->next;
  }
  GNUNET_free (msg);
}
Пример #12
0
/**
 * Check if a signature is valid.  This API is used by the GNS Block
 * to validate signatures received from the network.
 *
 * @param public_key public key of the zone
 * @param expire block expiration
 * @param name name that is being mapped (at most 255 characters long)
 * @param rd_count number of entries in 'rd' array
 * @param rd array of records with data to store
 * @param signature signature for all the records in the zone under the given name
 * @return GNUNET_OK if the signature is valid
 */
int
GNUNET_NAMESTORE_verify_signature (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key,
                                   const struct GNUNET_TIME_Absolute expire,
				   const char *name,
				   unsigned int rd_count,
				   const struct GNUNET_NAMESTORE_RecordData *rd,
				   const struct GNUNET_CRYPTO_RsaSignature *signature)
{
  int res = GNUNET_SYSERR;
  size_t rd_ser_len = 0;
  size_t name_len = 0;
  char * name_tmp;
  char * rd_tmp;
  struct GNUNET_CRYPTO_RsaSignaturePurpose *sig_purpose;
  struct GNUNET_TIME_AbsoluteNBO *expire_tmp;
  struct GNUNET_TIME_AbsoluteNBO expire_nbo = GNUNET_TIME_absolute_hton(expire);

  GNUNET_assert (public_key != NULL);
  GNUNET_assert (name != NULL);
  GNUNET_assert (rd != NULL);
  GNUNET_assert (signature != NULL);


  rd_ser_len = GNUNET_NAMESTORE_records_get_size(rd_count, rd);
  char rd_ser[rd_ser_len];
  GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);

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

  sig_purpose = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + rd_ser_len + name_len);
  sig_purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose)+ rd_ser_len + name_len);
  sig_purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
  expire_tmp = (struct GNUNET_TIME_AbsoluteNBO *) &sig_purpose[1];
  name_tmp = (char *) &expire_tmp[1];
  rd_tmp = &name_tmp[name_len];
  memcpy (expire_tmp, &expire_nbo, sizeof (struct GNUNET_TIME_AbsoluteNBO));
  memcpy (name_tmp, name, name_len);
  memcpy (rd_tmp, rd_ser, rd_ser_len);

  res = GNUNET_CRYPTO_rsa_verify(GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, sig_purpose, signature, public_key);

  GNUNET_free (sig_purpose);

  return res;
}
Пример #13
0
/**
 * Transmit a confirmation receipt to the chat service.
 *
 * @param cls closure, pointer to the 'struct GNUNET_CHAT_SendReceiptContext'
 * @param size number of bytes available in buf
 * @param buf where the callee should write the message
 * @return number of bytes written to buf
 */
static size_t
transmit_acknowledge_request (void *cls, size_t size, void *buf)
{
  struct GNUNET_CHAT_SendReceiptContext *src = cls;
  struct ConfirmationReceiptMessage *receipt;
  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub_key;
  uint16_t msg_len;
  size_t msg_size;

  if (NULL == buf)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("Could not transmit confirmation receipt\n"));
    return 0;
  }
#if DEBUG_CHAT
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Transmitting confirmation receipt to the service\n");
#endif
  msg_size = sizeof (struct ConfirmationReceiptMessage);
  GNUNET_assert (size >= msg_size);
  receipt = buf;
  receipt->header.size = htons (msg_size);
  receipt->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_CONFIRMATION_RECEIPT);
  receipt->reserved = htonl (0);
  receipt->sequence_number = src->received_msg->sequence_number;
  receipt->reserved2 = htonl (0);
  receipt->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
  GNUNET_CRYPTO_rsa_key_get_public (src->chat_room->my_private_key, &pub_key);
  GNUNET_CRYPTO_hash (&pub_key,
                      sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
                      &receipt->target);
  receipt->author = src->received_msg->sender;
  receipt->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_RECEIPT);
  receipt->purpose.size =
      htonl (msg_size - sizeof (struct GNUNET_MessageHeader) -
             sizeof (uint32_t) - sizeof (struct GNUNET_CRYPTO_RsaSignature));
  msg_len =
      ntohs (src->received_msg->header.size) -
      sizeof (struct ReceiveNotificationMessage);
  GNUNET_CRYPTO_hash (&src->received_msg[1], msg_len, &receipt->content);
  GNUNET_assert (GNUNET_OK ==
                 GNUNET_CRYPTO_rsa_sign (src->chat_room->my_private_key,
                                         &receipt->purpose,
                                         &receipt->signature));
  GNUNET_free (src->received_msg);
  GNUNET_free (src);
  return msg_size;
}
Пример #14
0
/**
 * Explicitly remove some content from the database.
 * The "cont"inuation will be called with status
 * "GNUNET_OK" if content was removed, "GNUNET_NO"
 * if no matching entry was found and "GNUNET_SYSERR"
 * on all other types of errors.
 *
 * @param h handle to the datastore
 * @param key key for the value
 * @param size number of bytes in data
 * @param data content stored
 * @param queue_priority ranking of this request in the priority queue
 * @param max_queue_size at what queue size should this request be dropped
 *        (if other requests of higher priority are in the queue)
 * @param timeout how long to wait at most for a response
 * @param cont continuation to call when done
 * @param cont_cls closure for cont
 * @return NULL if the entry was not queued, otherwise a handle that can be used to
 *         cancel; note that even if NULL is returned, the callback will be invoked
 *         (or rather, will already have been invoked)
 */
struct GNUNET_DATASTORE_QueueEntry *
GNUNET_DATASTORE_remove (struct GNUNET_DATASTORE_Handle *h,
                         const struct GNUNET_HashCode * key, size_t size,
                         const void *data, unsigned int queue_priority,
                         unsigned int max_queue_size,
                         struct GNUNET_TIME_Relative timeout,
                         GNUNET_DATASTORE_ContinuationWithStatus cont,
                         void *cont_cls)
{
  struct GNUNET_DATASTORE_QueueEntry *qe;
  struct DataMessage *dm;
  size_t msize;
  union QueueContext qc;

  if (cont == NULL)
    cont = &drop_status_cont;
  LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to remove %u bytes under key `%s'\n",
       size, GNUNET_h2s (key));
  qc.sc.cont = cont;
  qc.sc.cont_cls = cont_cls;
  msize = sizeof (struct DataMessage) + size;
  GNUNET_assert (msize < GNUNET_SERVER_MAX_MESSAGE_SIZE);
  qe = make_queue_entry (h, msize, queue_priority, max_queue_size, timeout,
                         &process_status_message, &qc);
  if (qe == NULL)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG, "Could not create queue entry for REMOVE\n");
    return NULL;
  }
  GNUNET_STATISTICS_update (h->stats,
                            gettext_noop ("# REMOVE requests executed"), 1,
                            GNUNET_NO);
  dm = (struct DataMessage *) &qe[1];
  dm->header.type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_REMOVE);
  dm->header.size = htons (msize);
  dm->rid = htonl (0);
  dm->size = htonl (size);
  dm->type = htonl (0);
  dm->priority = htonl (0);
  dm->anonymity = htonl (0);
  dm->uid = GNUNET_htonll (0);
  dm->expiration = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_ZERO_ABS);
  dm->key = *key;
  memcpy (&dm[1], data, size);
  process_queue (h);
  return qe;
}
Пример #15
0
/**
 * Send a control message to the peer asking for transmission
 * of the message in the given peer record.
 *
 * @param pr peer to request transmission to
 */
static void
request_next_transmission (struct PeerRecord *pr)
{
  struct GNUNET_CORE_Handle *h = pr->ch;
  struct ControlMessage *cm;
  struct SendMessageRequest *smr;
  struct GNUNET_CORE_TransmitHandle *th;

  if (pr->timeout_task != GNUNET_SCHEDULER_NO_TASK)
  {
    GNUNET_SCHEDULER_cancel (pr->timeout_task);
    pr->timeout_task = GNUNET_SCHEDULER_NO_TASK;
  }
  th = &pr->th;
  if (NULL == th->peer)
  {
    trigger_next_request (h, GNUNET_NO);
    return;
  }
  if (th->cm != NULL)
    return;                     /* already done */
  GNUNET_assert (pr->prev == NULL);
  GNUNET_assert (pr->next == NULL);
  pr->timeout_task =
      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
                                    (th->timeout), &transmission_timeout, pr);
  cm = GNUNET_malloc (sizeof (struct ControlMessage) +
                      sizeof (struct SendMessageRequest));
  th->cm = cm;
  cm->th = th;
  smr = (struct SendMessageRequest *) &cm[1];
  smr->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST);
  smr->header.size = htons (sizeof (struct SendMessageRequest));
  smr->priority = htonl ((uint32_t) th->priority);
  smr->deadline = GNUNET_TIME_absolute_hton (th->timeout);
  smr->peer = pr->peer;
  smr->reserved = htonl (0);
  smr->size = htons (th->msize);
  smr->smr_id = htons (th->smr_id = pr->smr_id_gen++);
  GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head,
                                    h->control_pending_tail, cm);
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Adding SEND REQUEST for peer `%s' to message queue\n",
       GNUNET_i2s (&pr->peer));
  trigger_next_request (h, GNUNET_NO);
}
Пример #16
0
/**
 * Function to handle call request from the client
 *
 * @param cls the `struct Line` the message is about
 * @param msg the message from the client
 */
static void
handle_client_call_message (void *cls,
                            const struct ClientCallMessage *msg)
{
  struct Line *line = cls;
  struct Channel *ch;
  struct GNUNET_MQ_Envelope *e;
  struct CadetPhoneRingMessage *ring;
  struct CadetPhoneRingInfoPS rs;

  line->line_port = msg->line_port;
  rs.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING);
  rs.purpose.size = htonl (sizeof (struct CadetPhoneRingInfoPS));
  rs.line_port = line->line_port;
  rs.target_peer = msg->target;
  rs.expiration_time
    = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (RING_TIMEOUT));

  ch = GNUNET_new (struct Channel);
  ch->line = line;
  GNUNET_CONTAINER_DLL_insert (line->channel_head,
                               line->channel_tail,
                               ch);
  ch->status = CS_CALLER_CALLING;
  ch->channel = GNUNET_CADET_channel_create (cadet,
                                             ch,
                                             &msg->target,
                                             &msg->line_port,
                                             GNUNET_CADET_OPTION_RELIABLE);
  ch->mq = GNUNET_CADET_mq_create (ch->channel);
  e = GNUNET_MQ_msg (ring,
                     GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RING);
  GNUNET_CRYPTO_ecdsa_key_get_public (&msg->caller_id,
                                      &ring->caller_id);
  ring->expiration_time = rs.expiration_time;
  GNUNET_assert (GNUNET_OK ==
                 GNUNET_CRYPTO_ecdsa_sign (&msg->caller_id,
                                           &rs.purpose,
                                           &ring->signature));
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Sending RING message via CADET\n");
  GNUNET_MQ_send (ch->mq,
                  e);
  GNUNET_SERVICE_client_continue (line->client);
}
/**
 * Transmit a status code to the client.
 *
 * @param client receiver of the response
 * @param code status code
 * @param msg optional error message (can be NULL)
 */
static void
transmit_status (struct GNUNET_SERVER_Client *client, int code, const char *msg)
{
  struct StatusMessage *sm;
  size_t slen;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Transmitting `%s' message with value %d and message `%s'\n",
              "STATUS", code, msg != NULL ? msg : "(none)");
  slen = (msg == NULL) ? 0 : strlen (msg) + 1;
  sm = GNUNET_malloc (sizeof (struct StatusMessage) + slen);
  sm->header.size = htons (sizeof (struct StatusMessage) + slen);
  sm->header.type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_STATUS);
  sm->status = htonl (code);
  sm->min_expiration = GNUNET_TIME_absolute_hton (min_expiration);
  if (slen > 0)
    memcpy (&sm[1], msg, slen);
  transmit (client, &sm->header);
}
Пример #18
0
/**
 * Store an item in the datastore.
 *
 * @param cls closure (our `struct Plugin`)
 * @param key key to store @a data under
 * @param size number of bytes in @a data
 * @param data data to store
 * @param type type of the value
 * @param discard_time when to discard the value in any case
 * @param path_info_len number of entries in @a path_info
 * @param path_info a path through the network
 * @return 0 if duplicate, -1 on error, number of bytes used otherwise
 */
static ssize_t
postgres_plugin_put (void *cls,
                     const struct GNUNET_HashCode *key,
                     size_t size,
                     const char *data,
                     enum GNUNET_BLOCK_Type type,
                     struct GNUNET_TIME_Absolute discard_time,
		     unsigned int path_info_len,
		     const struct GNUNET_PeerIdentity *path_info)
{
  struct Plugin *plugin = cls;
  PGresult *ret;
  uint32_t btype = htonl (type);
  uint64_t bexpi = GNUNET_TIME_absolute_hton (discard_time).abs_value_us__;

  const char *paramValues[] = {
    (const char *) &btype,
    (const char *) &bexpi,
    (const char *) key,
    (const char *) data,
    (const char *) path_info
  };
  int paramLengths[] = {
    sizeof (btype),
    sizeof (bexpi),
    sizeof (struct GNUNET_HashCode),
    size,
    path_info_len * sizeof (struct GNUNET_PeerIdentity)
  };
  const int paramFormats[] = { 1, 1, 1, 1, 1 };

  ret =
      PQexecPrepared (plugin->dbh, "put", 5, paramValues, paramLengths,
                      paramFormats, 1);
  if (GNUNET_OK !=
      GNUNET_POSTGRES_check_result (plugin->dbh, ret,
				    PGRES_COMMAND_OK, "PQexecPrepared", "put"))
    return -1;
  plugin->num_items++;
  PQclear (ret);
  return size + OVERHEAD;
}
Пример #19
0
/**
 * Update a value in the datastore.
 *
 * @param h handle to the datastore
 * @param uid identifier for the value
 * @param priority how much to increase the priority of the value
 * @param expiration new expiration value should be MAX of existing and this argument
 * @param queue_priority ranking of this request in the priority queue
 * @param max_queue_size at what queue size should this request be dropped
 *        (if other requests of higher priority are in the queue)
 * @param timeout how long to wait at most for a response
 * @param cont continuation to call when done
 * @param cont_cls closure for cont
 * @return NULL if the entry was not queued, otherwise a handle that can be used to
 *         cancel; note that even if NULL is returned, the callback will be invoked
 *         (or rather, will already have been invoked)
 */
struct GNUNET_DATASTORE_QueueEntry *
GNUNET_DATASTORE_update (struct GNUNET_DATASTORE_Handle *h, uint64_t uid,
                         uint32_t priority,
                         struct GNUNET_TIME_Absolute expiration,
                         unsigned int queue_priority,
                         unsigned int max_queue_size,
                         struct GNUNET_TIME_Relative timeout,
                         GNUNET_DATASTORE_ContinuationWithStatus cont,
                         void *cont_cls)
{
  struct GNUNET_DATASTORE_QueueEntry *qe;
  struct UpdateMessage *um;
  union QueueContext qc;

  if (cont == NULL)
    cont = &drop_status_cont;
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Asked to update entry %llu raising priority by %u and expiration to %llu\n",
       uid, (unsigned int) priority, (unsigned long long) expiration.abs_value);
  qc.sc.cont = cont;
  qc.sc.cont_cls = cont_cls;
  qe = make_queue_entry (h, sizeof (struct UpdateMessage), queue_priority,
                         max_queue_size, timeout, &process_status_message, &qc);
  if (qe == NULL)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG, "Could not create queue entry for UPDATE\n");
    return NULL;
  }
  GNUNET_STATISTICS_update (h->stats,
                            gettext_noop ("# UPDATE requests executed"), 1,
                            GNUNET_NO);
  um = (struct UpdateMessage *) &qe[1];
  um->header.type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_UPDATE);
  um->header.size = htons (sizeof (struct UpdateMessage));
  um->priority = htonl (priority);
  um->expiration = GNUNET_TIME_absolute_hton (expiration);
  um->uid = GNUNET_htonll (uid);
  process_queue (h);
  return qe;
}
Пример #20
0
GNUNET_NETWORK_STRUCT_END

/**
 * Copy the given address information into
 * the given buffer using the format of HELLOs.
 *
 * @param address the address
 * @param expiration expiration for the address
 * @param target where to copy the address
 * @param max maximum number of bytes to copy to target
 * @return number of bytes copied, 0 if
 *         the target buffer was not big enough.
 */
size_t
GNUNET_HELLO_add_address (const struct GNUNET_HELLO_Address *address,
                          struct GNUNET_TIME_Absolute expiration, char *target,
                          size_t max)
{
  uint16_t alen;
  size_t slen;
  struct GNUNET_TIME_AbsoluteNBO exp;

  slen = strlen (address->transport_name) + 1;
  if (slen + sizeof (uint16_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO) +
      address->address_length > max)
    return 0;
  exp = GNUNET_TIME_absolute_hton (expiration);
  alen = htons ((uint16_t) address->address_length);
  memcpy (target, address->transport_name, slen);
  memcpy (&target[slen], &alen, sizeof (uint16_t));
  slen += sizeof (uint16_t);
  memcpy (&target[slen], &exp, sizeof (struct GNUNET_TIME_AbsoluteNBO));
  slen += sizeof (struct GNUNET_TIME_AbsoluteNBO);
  memcpy (&target[slen], address->address, address->address_length);
  slen += address->address_length;
  return slen;
}
Пример #21
0
/**
 * Copy the given address information into
 * the given buffer using the format of HELLOs.
 *
 * @param address the address
 * @param expiration expiration for the address
 * @param target where to copy the address
 * @param max maximum number of bytes to copy to target
 * @return number of bytes copied, 0 if
 *         the target buffer was not big enough.
 */
size_t
GNUNET_HELLO_add_address (const struct GNUNET_HELLO_Address *address,
                          struct GNUNET_TIME_Absolute expiration, char *target,
                          size_t max)
{
  uint16_t alen;
  size_t slen;
  struct GNUNET_TIME_AbsoluteNBO exp;

  slen = strlen (address->transport_name) + 1;
  if (slen + sizeof (uint16_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO) +
      address->address_length > max)
    return 0;
  exp = GNUNET_TIME_absolute_hton (expiration);
  alen = htons ((uint16_t) address->address_length);
  memcpy (target, address->transport_name, slen);
  memcpy (&target[slen], &alen, sizeof (uint16_t));
  slen += sizeof (uint16_t);
  memcpy (&target[slen], &exp, sizeof (struct GNUNET_TIME_AbsoluteNBO));
  slen += sizeof (struct GNUNET_TIME_AbsoluteNBO);
  memcpy (&target[slen], address->address, address->address_length);
  slen += address->address_length;
  return slen;
}
/**
 * Handle a reply we've received from another peer.  If the reply
 * matches any of our pending queries, forward it to the respective
 * client(s).
 *
 * @param expiration when will the reply expire
 * @param key the query this reply is for
 * @param get_path_length number of peers in @a get_path
 * @param get_path path the reply took on get
 * @param put_path_length number of peers in @a put_path
 * @param put_path path the reply took on put
 * @param type type of the reply
 * @param data_size number of bytes in @a data
 * @param data application payload data
 */
void
GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration,
                          const struct GNUNET_HashCode *key,
                          unsigned int get_path_length,
                          const struct GNUNET_PeerIdentity *get_path,
                          unsigned int put_path_length,
                          const struct GNUNET_PeerIdentity *put_path,
                          enum GNUNET_BLOCK_Type type, size_t data_size,
                          const void *data)
{
  struct ForwardReplyContext frc;
  struct PendingMessage *pm;
  struct GNUNET_DHT_ClientResultMessage *reply;
  struct GNUNET_PeerIdentity *paths;
  size_t msize;

  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "reply for key %s\n",
       GNUNET_h2s (key));

  if (NULL == GNUNET_CONTAINER_multihashmap_get (forward_map, key))
  {
    GNUNET_STATISTICS_update (GDS_stats,
                              gettext_noop
                              ("# REPLIES ignored for CLIENTS (no match)"), 1,
                              GNUNET_NO);
    return;                     /* no matching request, fast exit! */
  }
  msize =
      sizeof (struct GNUNET_DHT_ClientResultMessage) + data_size +
      (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity);
  if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                _("Could not pass reply to client, message too big!\n"));
    return;
  }
  pm = GNUNET_malloc (msize + sizeof (struct PendingMessage));
  reply = (struct GNUNET_DHT_ClientResultMessage *) &pm[1];
  pm->msg = &reply->header;
  reply->header.size = htons ((uint16_t) msize);
  reply->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_RESULT);
  reply->type = htonl (type);
  reply->get_path_length = htonl (get_path_length);
  reply->put_path_length = htonl (put_path_length);
  reply->unique_id = 0;         /* filled in later */
  reply->expiration = GNUNET_TIME_absolute_hton (expiration);
  reply->key = *key;
  paths = (struct GNUNET_PeerIdentity *) &reply[1];
  memcpy (paths, put_path,
          sizeof (struct GNUNET_PeerIdentity) * put_path_length);
  memcpy (&paths[put_path_length], get_path,
          sizeof (struct GNUNET_PeerIdentity) * get_path_length);
  memcpy (&paths[get_path_length + put_path_length], data, data_size);
  frc.do_copy = GNUNET_NO;
  frc.pm = pm;
  frc.data = data;
  frc.data_size = data_size;
  frc.type = type;
  GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, key, &forward_reply,
                                              &frc);
  if (GNUNET_NO == frc.do_copy)
  {
    /* did not match any of the requests, free! */
    GNUNET_STATISTICS_update (GDS_stats,
                              gettext_noop
                              ("# REPLIES ignored for CLIENTS (no match)"), 1,
                              GNUNET_NO);
    GNUNET_free (pm);
  }
}
/**
 * Check if some client is monitoring PUT messages and notify
 * them in that case.
 *
 * @param options Options, for instance RecordRoute, DemultiplexEverywhere.
 * @param type The type of data in the request.
 * @param hop_count Hop count so far.
 * @param path_length number of entries in path (or 0 if not recorded).
 * @param path peers on the PUT path (or NULL if not recorded).
 * @param desired_replication_level Desired replication level.
 * @param exp Expiration time of the data.
 * @param key Key under which data is to be stored.
 * @param data Pointer to the data carried.
 * @param size Number of bytes in data.
 */
void
GDS_CLIENTS_process_put (uint32_t options,
                         enum GNUNET_BLOCK_Type type,
                         uint32_t hop_count,
                         uint32_t desired_replication_level,
                         unsigned int path_length,
                         const struct GNUNET_PeerIdentity *path,
                         struct GNUNET_TIME_Absolute exp,
                         const struct GNUNET_HashCode * key,
                         const void *data,
                         size_t size)
{
  struct ClientMonitorRecord *m;
  struct ClientList **cl;
  unsigned int cl_size;

  cl = NULL;
  cl_size = 0;
  for (m = monitor_head; NULL != m; m = m->next)
  {
    if ((GNUNET_BLOCK_TYPE_ANY == m->type || m->type == type) &&
        (NULL == m->key ||
         memcmp (key, m->key, sizeof(struct GNUNET_HashCode)) == 0))
    {
      struct PendingMessage *pm;
      struct GNUNET_DHT_MonitorPutMessage *mmsg;
      struct GNUNET_PeerIdentity *msg_path;
      size_t msize;
      unsigned int i;

      /* Don't send duplicates */
      for (i = 0; i < cl_size; i++)
        if (cl[i] == m->client)
          break;
      if (i < cl_size)
        continue;
      GNUNET_array_append (cl, cl_size, m->client);

      msize = size;
      msize += path_length * sizeof (struct GNUNET_PeerIdentity);
      msize += sizeof (struct GNUNET_DHT_MonitorPutMessage);
      msize += sizeof (struct PendingMessage);
      pm = GNUNET_malloc (msize);
      mmsg = (struct GNUNET_DHT_MonitorPutMessage *) &pm[1];
      pm->msg = (struct GNUNET_MessageHeader *) mmsg;
      mmsg->header.size = htons (msize - sizeof (struct PendingMessage));
      mmsg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT);
      mmsg->options = htonl(options);
      mmsg->type = htonl(type);
      mmsg->hop_count = htonl(hop_count);
      mmsg->desired_replication_level = htonl(desired_replication_level);
      mmsg->put_path_length = htonl(path_length);
      msg_path = (struct GNUNET_PeerIdentity *) &mmsg[1];
      if (path_length > 0)
      {
        memcpy (msg_path, path,
                path_length * sizeof (struct GNUNET_PeerIdentity));
      }
      mmsg->expiration_time = GNUNET_TIME_absolute_hton(exp);
      memcpy (&mmsg->key, key, sizeof (struct GNUNET_HashCode));
      if (size > 0)
        memcpy (&msg_path[path_length], data, size);
      add_pending_message (m->client, pm);
    }
  }
  GNUNET_free_non_null (cl);
}
Пример #24
0
/**
 * Regex callback iterator to store own service description in the DHT.
 *
 * @param cls closure.
 * @param key hash for current state.
 * @param proof proof for current state.
 * @param accepting #GNUNET_YES if this is an accepting state, #GNUNET_NO if not.
 * @param num_edges number of edges leaving current state.
 * @param edges edges leaving current state.
 */
static void
regex_iterator (void *cls,
                const struct GNUNET_HashCode *key,
                const char *proof,
                int accepting,
                unsigned int num_edges,
                const struct REGEX_BLOCK_Edge *edges)
{
  struct REGEX_INTERNAL_Announcement *h = cls;
  struct RegexBlock *block;
  size_t size;
  unsigned int i;

  LOG (GNUNET_ERROR_TYPE_INFO,
       "DHT PUT for state %s with proof `%s' and %u edges:\n",
       GNUNET_h2s (key),
       proof,
       num_edges);
  for (i = 0; i < num_edges; i++)
  {
    LOG (GNUNET_ERROR_TYPE_INFO,
         "Edge %u `%s' towards %s\n",
         i,
         edges[i].label,
         GNUNET_h2s (&edges[i].destination));
  }
  if (GNUNET_YES == accepting)
  {
    struct RegexAcceptBlock ab;

    LOG (GNUNET_ERROR_TYPE_INFO,
         "State %s is accepting, putting own id\n",
         GNUNET_h2s (key));
    size = sizeof (struct RegexAcceptBlock);
    ab.purpose.size = ntohl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
                             sizeof (struct GNUNET_TIME_AbsoluteNBO) +
                             sizeof (struct GNUNET_HashCode));
    ab.purpose.purpose = ntohl (GNUNET_SIGNATURE_PURPOSE_REGEX_ACCEPT);
    ab.expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_DHT_MAX_EXPIRATION));
    ab.key = *key;
    GNUNET_CRYPTO_eddsa_key_get_public (h->priv,
                                        &ab.peer.public_key);
    GNUNET_assert (GNUNET_OK ==
                   GNUNET_CRYPTO_eddsa_sign (h->priv,
                                           &ab.purpose,
                                           &ab.signature));

    GNUNET_STATISTICS_update (h->stats, "# regex accepting blocks stored",
                              1, GNUNET_NO);
    GNUNET_STATISTICS_update (h->stats, "# regex accepting block bytes stored",
                              sizeof (struct RegexAcceptBlock), GNUNET_NO);
    (void)
    GNUNET_DHT_put (h->dht, key,
                    DHT_REPLICATION,
                    DHT_OPT | GNUNET_DHT_RO_RECORD_ROUTE,
                    GNUNET_BLOCK_TYPE_REGEX_ACCEPT,
                    size,
                    &ab,
                    GNUNET_TIME_relative_to_absolute (DHT_TTL),
                    NULL, NULL);
  }
  block = REGEX_BLOCK_create (proof,
                              num_edges, edges,
                              accepting,
                              &size);
  (void)
  GNUNET_DHT_put (h->dht, key,
                  DHT_REPLICATION,
                  DHT_OPT,
                  GNUNET_BLOCK_TYPE_REGEX,
                  size, block,
                  GNUNET_TIME_relative_to_absolute (DHT_TTL),
                  NULL, NULL);
  GNUNET_STATISTICS_update (h->stats,
                            "# regex blocks stored",
                            1, GNUNET_NO);
  GNUNET_STATISTICS_update (h->stats,
                            "# regex block bytes stored",
                            size, GNUNET_NO);
  GNUNET_free (block);
}
Пример #25
0
/**
 * Transmit the next message to the core service.
 *
 * @param cls closure with the `struct GNUNET_CORE_Handle`
 * @param size number of bytes available in @a buf
 * @param buf where the callee should write the message
 * @return number of bytes written to @a buf
 */
static size_t
transmit_message (void *cls, size_t size, void *buf)
{
  struct GNUNET_CORE_Handle *h = cls;
  struct ControlMessage *cm;
  struct GNUNET_CORE_TransmitHandle *th;
  struct PeerRecord *pr;
  struct SendMessage *sm;
  const struct GNUNET_MessageHeader *hdr;
  uint16_t msize;
  size_t ret;

  GNUNET_assert (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK);
  h->cth = NULL;
  if (NULL == buf)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Transmission failed, initiating reconnect\n");
    reconnect_later (h);
    return 0;
  }
  /* first check for control messages */
  if (NULL != (cm = h->control_pending_head))
  {
    hdr = (const struct GNUNET_MessageHeader *) &cm[1];
    msize = ntohs (hdr->size);
    if (size < msize)
    {
      trigger_next_request (h, GNUNET_NO);
      return 0;
    }
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Transmitting control message with %u bytes of type %u to core.\n",
         (unsigned int) msize, (unsigned int) ntohs (hdr->type));
    memcpy (buf, hdr, msize);
    GNUNET_CONTAINER_DLL_remove (h->control_pending_head,
                                 h->control_pending_tail, cm);
    if (NULL != cm->th)
      cm->th->cm = NULL;
    if (NULL != cm->cont)
      cm->cont (cm->cont_cls, GNUNET_OK);
    GNUNET_free (cm);
    trigger_next_request (h, GNUNET_NO);
    return msize;
  }
  /* now check for 'ready' P2P messages */
  if (NULL == (pr = h->ready_peer_head))
    return 0;
  GNUNET_assert (NULL != pr->th.peer);
  th = &pr->th;
  if (size < th->msize + sizeof (struct SendMessage))
  {
    trigger_next_request (h, GNUNET_NO);
    return 0;
  }
  GNUNET_CONTAINER_DLL_remove (h->ready_peer_head, h->ready_peer_tail, pr);
  th->peer = NULL;
  if (GNUNET_SCHEDULER_NO_TASK != pr->timeout_task)
  {
    GNUNET_SCHEDULER_cancel (pr->timeout_task);
    pr->timeout_task = GNUNET_SCHEDULER_NO_TASK;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Transmitting SEND request to `%s' with %u bytes.\n",
       GNUNET_i2s (&pr->peer), (unsigned int) th->msize);
  sm = (struct SendMessage *) buf;
  sm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND);
  sm->priority = htonl ((uint32_t) th->priority);
  sm->deadline = GNUNET_TIME_absolute_hton (th->timeout);
  sm->peer = pr->peer;
  sm->cork = htonl ((uint32_t) th->cork);
  sm->reserved = htonl (0);
  ret =
    th->get_message (th->get_message_cls,
		     size - sizeof (struct SendMessage), &sm[1]);

  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Transmitting SEND request to `%s' yielded %u bytes.\n",
       GNUNET_i2s (&pr->peer), ret);
  if (0 == ret)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
	 "Size of clients message to peer %s is 0!\n",
	 GNUNET_i2s (&pr->peer));
    /* client decided to send nothing! */
    request_next_transmission (pr);
    return 0;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Produced SEND message to core with %u bytes payload\n",
       (unsigned int) ret);
  GNUNET_assert (ret >= sizeof (struct GNUNET_MessageHeader));
  if (ret + sizeof (struct SendMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
  {
    GNUNET_break (0);
    request_next_transmission (pr);
    return 0;
  }
  ret += sizeof (struct SendMessage);
  sm->header.size = htons (ret);
  GNUNET_assert (ret <= size);
  request_next_transmission (pr);
  return ret;
}
Пример #26
0
int
main (int argc, char *argv[])
{
  struct GNUNET_TIME_Absolute now;
  struct GNUNET_TIME_AbsoluteNBO nown;
  struct GNUNET_TIME_Absolute future;
  struct GNUNET_TIME_Absolute past;
  struct GNUNET_TIME_Absolute last;
  struct GNUNET_TIME_Absolute forever;
  struct GNUNET_TIME_Absolute zero;
  struct GNUNET_TIME_Relative rel;
  struct GNUNET_TIME_Relative relForever;
  struct GNUNET_TIME_Relative relUnit;
  struct GNUNET_TIME_RelativeNBO reln;
  unsigned int i;

  GNUNET_log_setup ("test-time", "WARNING", NULL);
  forever = GNUNET_TIME_UNIT_FOREVER_ABS;
  relForever = GNUNET_TIME_UNIT_FOREVER_REL;
  relUnit = GNUNET_TIME_UNIT_MILLISECONDS;
  zero.abs_value_us = 0;

  last = now = GNUNET_TIME_absolute_get ();
  while (now.abs_value_us == last.abs_value_us)
    now = GNUNET_TIME_absolute_get ();
  GNUNET_assert (now.abs_value_us > last.abs_value_us);

  /* test overflow checking in multiply */
  rel = GNUNET_TIME_UNIT_MILLISECONDS;
  GNUNET_log_skip (1, GNUNET_NO);
  for (i = 0; i < 55; i++)
    rel = GNUNET_TIME_relative_multiply (rel, 2);
  GNUNET_log_skip (0, GNUNET_NO);
  GNUNET_assert (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us);
  /*check zero */
  rel.rel_value_us = (UINT64_MAX) - 1024;
  GNUNET_assert (GNUNET_TIME_UNIT_ZERO.rel_value_us ==
                 GNUNET_TIME_relative_multiply (rel, 0).rel_value_us);

  /* test infinity-check for relative to absolute */
  GNUNET_log_skip (1, GNUNET_NO);
  last = GNUNET_TIME_relative_to_absolute (rel);
  GNUNET_assert (last.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us);
  GNUNET_log_skip (0, GNUNET_YES);

  /* check relative to absolute */
  rel.rel_value_us = 1000000;
  GNUNET_assert (GNUNET_TIME_absolute_get ().abs_value_us <
                 GNUNET_TIME_relative_to_absolute (rel).abs_value_us);
  /*check forever */
  rel.rel_value_us = UINT64_MAX;
  GNUNET_assert (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us ==
                 GNUNET_TIME_relative_to_absolute (rel).abs_value_us);
  /* check overflow for r2a */
  rel.rel_value_us = (UINT64_MAX) - 1024;
  GNUNET_log_skip (1, GNUNET_NO);
  last = GNUNET_TIME_relative_to_absolute (rel);
  GNUNET_log_skip (0, GNUNET_NO);
  GNUNET_assert (last.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us);

  /* check overflow for relative add */
  GNUNET_log_skip (1, GNUNET_NO);
  rel = GNUNET_TIME_relative_add (rel, rel);
  GNUNET_log_skip (0, GNUNET_NO);
  GNUNET_assert (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us);

  GNUNET_log_skip (1, GNUNET_NO);
  rel = GNUNET_TIME_relative_add (relForever, relForever);
  GNUNET_log_skip (0, GNUNET_NO);
  GNUNET_assert (rel.rel_value_us == relForever.rel_value_us);

  GNUNET_log_skip (1, GNUNET_NO);
  rel = GNUNET_TIME_relative_add (relUnit, relUnit);
  GNUNET_assert (rel.rel_value_us == 2 * relUnit.rel_value_us);

  /* check relation check in get_duration */
  future.abs_value_us = now.abs_value_us + 1000000;
  GNUNET_assert (GNUNET_TIME_absolute_get_difference (now, future).rel_value_us ==
                 1000000);
  GNUNET_assert (GNUNET_TIME_absolute_get_difference (future, now).rel_value_us ==
                 0);

  GNUNET_assert (GNUNET_TIME_absolute_get_difference (zero, forever).rel_value_us
                 == forever.abs_value_us);

  past.abs_value_us = now.abs_value_us - 1000000;
  rel = GNUNET_TIME_absolute_get_duration (future);
  GNUNET_assert (rel.rel_value_us == 0);
  rel = GNUNET_TIME_absolute_get_duration (past);
  GNUNET_assert (rel.rel_value_us >= 1000000);

  /* check get remaining */
  rel = GNUNET_TIME_absolute_get_remaining (now);
  GNUNET_assert (rel.rel_value_us == 0);
  rel = GNUNET_TIME_absolute_get_remaining (past);
  GNUNET_assert (rel.rel_value_us == 0);
  rel = GNUNET_TIME_absolute_get_remaining (future);
  GNUNET_assert (rel.rel_value_us > 0);
  GNUNET_assert (rel.rel_value_us <= 1000000);
  forever = GNUNET_TIME_UNIT_FOREVER_ABS;
  GNUNET_assert (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us ==
                 GNUNET_TIME_absolute_get_remaining (forever).rel_value_us);

  /* check endianess */
  reln = GNUNET_TIME_relative_hton (rel);
  GNUNET_assert (rel.rel_value_us == GNUNET_TIME_relative_ntoh (reln).rel_value_us);
  nown = GNUNET_TIME_absolute_hton (now);
  GNUNET_assert (now.abs_value_us == GNUNET_TIME_absolute_ntoh (nown).abs_value_us);

  /* check absolute addition */
  future = GNUNET_TIME_absolute_add (now, GNUNET_TIME_UNIT_SECONDS);
  GNUNET_assert (future.abs_value_us == now.abs_value_us + 1000 * 1000LL);

  future = GNUNET_TIME_absolute_add (forever, GNUNET_TIME_UNIT_ZERO);
  GNUNET_assert (future.abs_value_us == forever.abs_value_us);

  rel.rel_value_us = (UINT64_MAX) - 1024;
  now.abs_value_us = rel.rel_value_us;
  future = GNUNET_TIME_absolute_add (now, rel);
  GNUNET_assert (future.abs_value_us == forever.abs_value_us);

  /* check zero */
  future = GNUNET_TIME_absolute_add (now, GNUNET_TIME_UNIT_ZERO);
  GNUNET_assert (future.abs_value_us == now.abs_value_us);

  GNUNET_assert (forever.abs_value_us ==
                 GNUNET_TIME_absolute_subtract (forever,
                                                GNUNET_TIME_UNIT_MINUTES).abs_value_us);
  /*check absolute subtract */
  now.abs_value_us = 50000;
  rel.rel_value_us = 100000;
  GNUNET_assert (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
                 (GNUNET_TIME_absolute_subtract (now, rel)).abs_value_us);
  rel.rel_value_us = 10000;
  GNUNET_assert (40000 == (GNUNET_TIME_absolute_subtract (now, rel)).abs_value_us);

  /*check relative divide */
  GNUNET_assert (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us ==
                 (GNUNET_TIME_relative_divide (rel, 0)).rel_value_us);

  rel = GNUNET_TIME_UNIT_FOREVER_REL;
  GNUNET_assert (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us ==
                 (GNUNET_TIME_relative_divide (rel, 2)).rel_value_us);

  rel = GNUNET_TIME_relative_divide (relUnit, 2);
  GNUNET_assert (rel.rel_value_us == relUnit.rel_value_us / 2);


  /* check Return absolute time of 0ms */
  zero = GNUNET_TIME_UNIT_ZERO_ABS;

  /* check GNUNET_TIME_calculate_eta */
  last.abs_value_us = GNUNET_TIME_absolute_get ().abs_value_us - 1024;
  forever = GNUNET_TIME_UNIT_FOREVER_ABS;
  forever.abs_value_us = forever.abs_value_us - 1024;
  GNUNET_assert (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
                 GNUNET_TIME_calculate_eta (forever, 50000, 100000).rel_value_us);
  /* check zero */
  GNUNET_log_skip (1, GNUNET_NO);
  GNUNET_assert (GNUNET_TIME_UNIT_ZERO.rel_value_us ==
                 (GNUNET_TIME_calculate_eta (last, 60000, 50000)).rel_value_us);
  GNUNET_log_skip (0, GNUNET_YES);
  /*check forever */
  GNUNET_assert (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us ==
                 (GNUNET_TIME_calculate_eta (last, 0, 50000)).rel_value_us);

  /*check relative subtract */
  now = GNUNET_TIME_absolute_get ();
  rel.rel_value_us = now.abs_value_us;
  relForever.rel_value_us = rel.rel_value_us + 1024;
  GNUNET_assert (1024 ==
                 GNUNET_TIME_relative_subtract (relForever, rel).rel_value_us);
  /*check zero */
  GNUNET_assert (GNUNET_TIME_UNIT_ZERO.rel_value_us ==
                 GNUNET_TIME_relative_subtract (rel, relForever).rel_value_us);
  /*check forever */
  rel.rel_value_us = UINT64_MAX;
  GNUNET_assert (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us ==
                 GNUNET_TIME_relative_subtract (rel, relForever).rel_value_us);

  /*check GNUNET_TIME_relative_min */
  now = GNUNET_TIME_absolute_get ();
  rel.rel_value_us = now.abs_value_us;
  relForever.rel_value_us = rel.rel_value_us - 1024;
  GNUNET_assert (relForever.rel_value_us ==
                 GNUNET_TIME_relative_min (rel, relForever).rel_value_us);

  /*check GNUNET_TIME_relative_max */
  GNUNET_assert (rel.rel_value_us ==
                 GNUNET_TIME_relative_max (rel, relForever).rel_value_us);

  /*check GNUNET_TIME_absolute_min */
  now = GNUNET_TIME_absolute_get ();
  last.abs_value_us = now.abs_value_us - 1024;
  GNUNET_assert (last.abs_value_us ==
                 GNUNET_TIME_absolute_min (now, last).abs_value_us);

  /*check  GNUNET_TIME_absolute_max */
  GNUNET_assert (now.abs_value_us ==
                 GNUNET_TIME_absolute_max (now, last).abs_value_us);

  return 0;
}
Пример #27
0
/**
 * Store an item in the namestore.  If the item is already present,
 * the expiration time is updated to the max of the existing time and
 * the new time.  This API is used by the authority of a zone.
 *
 * @param h handle to the namestore
 * @param pkey private key of the zone
 * @param name name that is being mapped (at most 255 characters long)
 * @param rd record data to store
 * @param cont continuation to call when done
 * @param cont_cls closure for cont
 * @return handle to abort the request
 */
struct GNUNET_NAMESTORE_QueueEntry *
GNUNET_NAMESTORE_record_create (struct GNUNET_NAMESTORE_Handle *h,
				const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
				const char *name,
				const struct GNUNET_NAMESTORE_RecordData *rd,
				GNUNET_NAMESTORE_ContinuationWithStatus cont,
				void *cont_cls)
{
  struct GNUNET_NAMESTORE_QueueEntry *qe;
  struct PendingMessage *pe;
  char * name_tmp;
  char * pkey_tmp;
  char * rd_tmp;
  size_t rd_ser_len = 0;
  size_t msg_size = 0;
  size_t name_len = 0;
  size_t key_len = 0;
  uint32_t rid = 0;

  GNUNET_assert (NULL != h);
  GNUNET_assert (NULL != pkey);
  GNUNET_assert (NULL != name);
  GNUNET_assert (NULL != rd);

  name_len = strlen(name) + 1;
  if (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->cont = cont;
  qe->cont_cls = cont_cls;
  qe->op_id = rid;
  GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);

  /* set msg_size*/
  struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * pkey_enc = GNUNET_CRYPTO_rsa_encode_key (pkey);
  GNUNET_assert (pkey_enc != NULL);
  key_len = ntohs (pkey_enc->len);

  rd_ser_len = GNUNET_NAMESTORE_records_get_size(1, rd);
  char rd_ser[rd_ser_len];
  GNUNET_NAMESTORE_records_serialize(1, rd, rd_ser_len, rd_ser);

  struct RecordCreateMessage * msg;
  msg_size = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;

  /* create msg here */
  pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
  pe->size = msg_size;
  pe->is_init = GNUNET_NO;
  msg = (struct RecordCreateMessage *) &pe[1];

  pkey_tmp = (char *) &msg[1];
  name_tmp = &pkey_tmp[key_len];
  rd_tmp = &name_tmp[name_len];

  msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE);
  msg->gns_header.header.size = htons (msg_size);
  msg->gns_header.r_id = htonl (rid);
  msg->name_len = htons (name_len);
  msg->rd_count = htons (1);
  msg->rd_len = htons (rd_ser_len);
  msg->pkey_len = htons (key_len);
  msg->expire = GNUNET_TIME_absolute_hton(GNUNET_TIME_UNIT_FOREVER_ABS);
  memcpy (pkey_tmp, pkey_enc, key_len);
  memcpy (name_tmp, name, name_len);
  memcpy (rd_tmp, rd_ser, rd_ser_len);
  GNUNET_free (pkey_enc);

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_CREATE", name, msg_size);

  GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
  do_transmit(h);
  return qe;
}
    GNUNET_SERVER_client_drop (client);
    return GNUNET_OK;
  }
  GNUNET_assert (sizeof (struct DataMessage) + size <
                 GNUNET_SERVER_MAX_MESSAGE_SIZE);
  dm = GNUNET_malloc (sizeof (struct DataMessage) + size);
  dm->header.size = htons (sizeof (struct DataMessage) + size);
  dm->header.type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_DATA);
  dm->rid = htonl (0);
  dm->size = htonl (size);
  dm->type = htonl (type);
  dm->priority = htonl (priority);
  dm->anonymity = htonl (anonymity);
  dm->replication = htonl (0);
  dm->reserved = htonl (0);
  dm->expiration = GNUNET_TIME_absolute_hton (expiration);
  dm->uid = GNUNET_htonll (uid);
  dm->key = *key;
  memcpy (&dm[1], data, size);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Transmitting `%s' message for `%s' of type %u with expiration %s (in: %s)\n",
              "DATA", GNUNET_h2s (key), type,
              GNUNET_STRINGS_absolute_time_to_string (expiration),
              GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (expiration),
						      GNUNET_YES));
  GNUNET_STATISTICS_update (stats, gettext_noop ("# results found"), 1,
                            GNUNET_NO);
  transmit (client, &dm->header);
  GNUNET_SERVER_client_drop (client);
  return GNUNET_OK;
}
Пример #29
0
/**
 * Store an item in the namestore.  If the item is already present,
 * the expiration time is updated to the max of the existing time and
 * the new time.  This API is used when we cache signatures from other
 * authorities.
 *
 * @param h handle to the namestore
 * @param zone_key public key of the zone
 * @param name name that is being mapped (at most 255 characters long)
 * @param freshness when does the corresponding block in the DHT expire (until
 *               when should we never do a DHT lookup for the same name again)?
 * @param rd_count number of entries in 'rd' array
 * @param rd array of records with data to store
 * @param signature signature for all the records in the zone under the given name
 * @param cont continuation to call when done
 * @param cont_cls closure for cont
 * @return handle to abort the request
 */
struct GNUNET_NAMESTORE_QueueEntry *
GNUNET_NAMESTORE_record_put (struct GNUNET_NAMESTORE_Handle *h,
			     const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
			     const char *name,
			     struct GNUNET_TIME_Absolute freshness,
			     unsigned int rd_count,
			     const struct GNUNET_NAMESTORE_RecordData *rd,
			     const struct GNUNET_CRYPTO_RsaSignature *signature,
			     GNUNET_NAMESTORE_ContinuationWithStatus cont,
			     void *cont_cls)
{
  struct GNUNET_NAMESTORE_QueueEntry *qe;
  struct PendingMessage *pe;

  /* pointer to elements */
  char * rd_tmp;
  char * name_tmp;

  size_t msg_size = 0;
  size_t name_len = 0;
  size_t rd_ser_len = 0;
  uint32_t rid = 0;

  GNUNET_assert (NULL != h);
  GNUNET_assert (NULL != zone_key);
  GNUNET_assert (NULL != name);
  GNUNET_assert (NULL != rd);
  GNUNET_assert (NULL != signature);

  name_len = strlen(name) + 1;
  if (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->cont = cont;
  qe->cont_cls = cont_cls;
  qe->op_id = rid;
  GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe);

  /* set msg_size*/
  rd_ser_len = GNUNET_NAMESTORE_records_get_size(rd_count, rd);
  char rd_ser[rd_ser_len];
  GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);

  struct RecordPutMessage * msg;
  msg_size = sizeof (struct RecordPutMessage) + name_len  + rd_ser_len;

  /* create msg here */
  pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size);
  pe->size = msg_size;
  pe->is_init = GNUNET_NO;
  msg = (struct RecordPutMessage *) &pe[1];
  name_tmp = (char *) &msg[1];
  rd_tmp = &name_tmp[name_len];

  msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT);
  msg->gns_header.header.size = htons (msg_size);
  msg->gns_header.r_id = htonl (rid);
  msg->signature = *signature;
  msg->name_len = htons (name_len);
  msg->expire = GNUNET_TIME_absolute_hton (freshness);
  msg->rd_len = htons (rd_ser_len);
  msg->rd_count = htons (rd_count);

  msg->public_key = *zone_key;
  memcpy (name_tmp, name, name_len);
  memcpy (rd_tmp, rd_ser, rd_ser_len);

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_PUT", name, msg_size);

  GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe);
  do_transmit(h);

  return qe;
}
Пример #30
0
/**
 * We're ready to transmit a request to the VPN service. Do it.
 *
 * @param cls the 'struct GNUNET_VPN_Handle*'
 * @param size number of bytes available in buf
 * @param buf where to copy the request
 * @return number of bytes copied to 'buf'
 */
static size_t
transmit_request (void *cls,
		  size_t size,
		  void *buf)
{
  struct GNUNET_VPN_Handle *vh = cls;
  struct GNUNET_VPN_RedirectionRequest *rr;
  struct RedirectToIpRequestMessage rip;
  struct RedirectToServiceRequestMessage rs;
  char *cbuf;
  size_t alen;
  size_t ret;

  vh->th = NULL;
  /* find a pending request */
  rr = vh->rr_head;
  while ( (NULL != rr) &&
	  (0 != rr->request_id) )
    rr = rr->next;
  if (NULL == rr) 
    return 0;
  if (0 == size) 
  {
    reconnect (vh);
    return 0;
  }

  /* if first request, start receive loop */
  if (0 == vh->request_id_gen)
    GNUNET_CLIENT_receive (vh->client,
			   &receive_response, vh,
			   GNUNET_TIME_UNIT_FOREVER_REL); 
  if (NULL == rr->addr)
  {
    ret = sizeof (struct RedirectToServiceRequestMessage);
    GNUNET_assert (ret <= size);
    rs.header.size = htons ((uint16_t) ret);
    rs.header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE);
    rs.nac = htonl (rr->nac);
    rs.expiration_time = GNUNET_TIME_absolute_hton (rr->expiration_time);
    rs.protocol = htonl (rr->protocol);
    rs.result_af = htonl (rr->result_af);
    rs.target = rr->peer;
    rs.service_descriptor = rr->serv;
    rs.request_id = rr->request_id = ++vh->request_id_gen;    
    memcpy (buf, &rs, sizeof (struct RedirectToServiceRequestMessage));
  }
  else
  {
    switch (rr->addr_af)
    {
    case AF_INET:
      alen = sizeof (struct in_addr);
      break;
    case AF_INET6:
      alen = sizeof (struct in6_addr);
      break;
    default:
      GNUNET_assert (0);
      return 0;
    }
    ret = alen + sizeof (struct RedirectToIpRequestMessage);
    GNUNET_assert (ret <= size);
    rip.header.size = htons ((uint16_t) ret);
    rip.header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP);
    rip.nac = htonl (rr->nac);
    rip.expiration_time = GNUNET_TIME_absolute_hton (rr->expiration_time);
    rip.result_af = htonl (rr->result_af);
    rip.addr_af = htonl (rr->addr_af);
    rip.request_id = rr->request_id = ++vh->request_id_gen;
    cbuf = buf;
    memcpy (cbuf, &rip, sizeof (struct RedirectToIpRequestMessage));
    memcpy (&cbuf[sizeof (struct RedirectToIpRequestMessage)], rr->addr, alen);
  }
  /* test if there are more pending requests */
  while ( (NULL != rr) &&
	  (0 != rr->request_id) )
    rr = rr->next;
  if (NULL != rr)
    vh->th = GNUNET_CLIENT_notify_transmit_ready (vh->client,
						  sizeof (struct RedirectToServiceRequestMessage),
						  GNUNET_TIME_UNIT_FOREVER_REL,
						  GNUNET_NO,
						  &transmit_request,
						  vh);
  return ret;
}