Ejemplo n.º 1
0
/**
 * Transmit START message to service.
 *
 * @param cls unused
 * @param size number of bytes available in buf
 * @param buf where to copy the message
 * @return number of bytes copied to buf
 */
static size_t
send_start (void *cls, size_t size, void *buf)
{
    struct GNUNET_NSE_Handle *h = cls;
    struct GNUNET_MessageHeader *msg;

    h->th = NULL;
    if (buf == NULL)
    {
        /* Connect error... */
        LOG (GNUNET_ERROR_TYPE_DEBUG,
             "Shutdown while trying to transmit `%s' request.\n", "START");
        reschedule_connect (h);
        return 0;
    }
    LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting `%s' request.\n", "START");
    GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));

    msg = (struct GNUNET_MessageHeader *) buf;
    msg->size = htons (sizeof (struct GNUNET_MessageHeader));
    msg->type = htons (GNUNET_MESSAGE_TYPE_NSE_START);
    GNUNET_CLIENT_receive (h->client, &message_handler, h,
                           GNUNET_TIME_UNIT_FOREVER_REL);
    return sizeof (struct GNUNET_MessageHeader);
}
Ejemplo n.º 2
0
/**
 * Transmit next message to service.
 *
 * @param cls The 'struct GNUNET_PSYCSTORE_Handle'.
 * @param size Number of bytes available in buf.
 * @param buf Where to copy the message.
 * @return Number of bytes copied to buf.
 */
static size_t
send_next_message (void *cls, size_t size, void *buf)
{
  struct GNUNET_PSYCSTORE_Handle *h = cls;
  struct GNUNET_PSYCSTORE_OperationHandle *op = h->transmit_head;
  size_t ret;

  h->th = NULL;
  if (NULL == op)
    return 0;
  ret = ntohs (op->msg->size);
  if (ret > size)
  {
    reschedule_connect (h);
    return 0;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Sending message of type %d to PSYCstore service. ID: %" PRIu64 "\n",
       ntohs (op->msg->type), op->op_id);
  memcpy (buf, op->msg, ret);

  GNUNET_CONTAINER_DLL_remove (h->transmit_head, h->transmit_tail, op);

  if (NULL == op->res_cb && NULL == op->data_cb)
  {
    GNUNET_free (op);
  }
  else
  {
    GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
  }

  if (NULL != h->transmit_head)
    transmit_next (h);

  if (GNUNET_NO == h->in_receive)
  {
    h->in_receive = GNUNET_YES;
    GNUNET_CLIENT_receive (h->client, &message_handler, h,
			   GNUNET_TIME_UNIT_FOREVER_REL);
  }
  return ret;
}
Ejemplo n.º 3
0
/**
 * Transmit next message to service.
 *
 * @param cls the `struct GNUNET_IDENTITY_Handle`.
 * @param size number of bytes available in @a buf
 * @param buf where to copy the message
 * @return number of bytes copied to buf
 */
static size_t
send_next_message (void *cls,
		   size_t size,
		   void *buf)
{
  struct GNUNET_IDENTITY_Handle *h = cls;
  struct GNUNET_IDENTITY_Operation *op = h->op_head;
  size_t ret;

  h->th = NULL;
  if (NULL == op)
    return 0;
  ret = ntohs (op->msg->size);
  if (ret > size)
  {
    reschedule_connect (h);
    return 0;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Sending message of type %d to identity service\n",
       ntohs (op->msg->type));
  memcpy (buf, op->msg, ret);
  if ( (NULL == op->cont) &&
       (NULL == op->cb) )
  {
    GNUNET_CONTAINER_DLL_remove (h->op_head,
				 h->op_tail,
				 op);
    GNUNET_free (op);
    transmit_next (h);
  }
  if (GNUNET_NO == h->in_receive)
  {
    h->in_receive = GNUNET_YES;
    GNUNET_CLIENT_receive (h->client,
			   &message_handler, h,
			   GNUNET_TIME_UNIT_FOREVER_REL);
  }
  return ret;
}
Ejemplo n.º 4
0
/**
 * Type of a function to call when we receive a message
 * from the service.
 *
 * @param cls closure
 * @param msg message received, NULL on timeout or fatal error
 */
static void
message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_PSYCSTORE_Handle *h = cls;
  struct GNUNET_PSYCSTORE_OperationHandle *op;
  const struct OperationResult *opres;
  const struct CountersResult *cres;
  const struct FragmentResult *fres;
  const struct StateResult *sres;
  const char *str;

  if (NULL == msg)
  {
    reschedule_connect (h);
    return;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Received message of type %d from PSYCstore service.\n",
       ntohs (msg->type));
  uint16_t size = ntohs (msg->size);
  uint16_t type = ntohs (msg->type);
  switch (type)
  {
  case GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE:
    if (size < sizeof (struct OperationResult))
    {
      LOG (GNUNET_ERROR_TYPE_ERROR,
           "Received message of type %d with length %lu bytes. "
           "Expected >= %lu\n",
           type, size, sizeof (struct OperationResult));
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }

    opres = (const struct OperationResult *) msg;
    str = (const char *) &opres[1];
    if ( (size > sizeof (struct OperationResult)) &&
	 ('\0' != str[size - sizeof (struct OperationResult) - 1]) )
    {
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }
    if (size == sizeof (struct OperationResult))
      str = "";

    op = find_op_by_id (h, GNUNET_ntohll (opres->op_id));
    if (NULL == op)
    {
      LOG (GNUNET_ERROR_TYPE_DEBUG,
           "No callback registered for operation with ID %" PRIu64 ".\n",
           type, GNUNET_ntohll (opres->op_id));
    }
    else
    {
      LOG (GNUNET_ERROR_TYPE_DEBUG,
           "Received result message (type %d) with operation ID: %" PRIu64 "\n",
           type, op->op_id);

      int64_t result_code = GNUNET_ntohll (opres->result_code) + INT64_MIN;
      GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
      if (NULL != op->res_cb)
      {
        const struct StateSyncRequest *ssreq;
        switch (ntohs (op->msg->type))
        {
        case GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_SYNC:
          ssreq = (const struct StateSyncRequest *) op->msg;
          if (!(ssreq->flags & STATE_OP_LAST
                || GNUNET_OK != result_code))
            op->res_cb = NULL;
          break;
        }
      }
      if (NULL != op->res_cb)
        op->res_cb (op->cls, result_code, str, size - sizeof (*opres));
      GNUNET_free (op);
    }
    break;

  case GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_COUNTERS:
    if (size != sizeof (struct CountersResult))
    {
      LOG (GNUNET_ERROR_TYPE_ERROR,
           "Received message of type %d with length %lu bytes. "
           "Expected %lu\n",
           type, size, sizeof (struct CountersResult));
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }

    cres = (const struct CountersResult *) msg;

    op = find_op_by_id (h, GNUNET_ntohll (cres->op_id));
    if (NULL == op)
    {
      LOG (GNUNET_ERROR_TYPE_DEBUG,
           "No callback registered for operation with ID %" PRIu64 ".\n",
           type, GNUNET_ntohll (cres->op_id));
    }
    else
    {
      GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
      if (NULL != op->data_cb)
        ((GNUNET_PSYCSTORE_CountersCallback)
         op->data_cb) (op->cls,
                       ntohl (cres->result_code),
                       GNUNET_ntohll (cres->max_fragment_id),
                       GNUNET_ntohll (cres->max_message_id),
                       GNUNET_ntohll (cres->max_group_generation),
                       GNUNET_ntohll (cres->max_state_message_id));
      GNUNET_free (op);
    }
    break;

  case GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_FRAGMENT:
    if (size < sizeof (struct FragmentResult))
    {
      LOG (GNUNET_ERROR_TYPE_ERROR,
           "Received message of type %d with length %lu bytes. "
           "Expected >= %lu\n",
           type, size, sizeof (struct FragmentResult));
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }

    fres = (const struct FragmentResult *) msg;
    struct GNUNET_MULTICAST_MessageHeader *mmsg =
      (struct GNUNET_MULTICAST_MessageHeader *) &fres[1];
    if (size != sizeof (struct FragmentResult) + ntohs (mmsg->header.size))
    {
      LOG (GNUNET_ERROR_TYPE_ERROR,
           "Received message of type %d with length %lu bytes. "
           "Expected = %lu\n",
           type, size,
           sizeof (struct FragmentResult) + ntohs (mmsg->header.size));
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }

    op = find_op_by_id (h, GNUNET_ntohll (fres->op_id));
    if (NULL == op)
    {
      LOG (GNUNET_ERROR_TYPE_DEBUG,
           "No callback registered for operation with ID %" PRIu64 ".\n",
           type, GNUNET_ntohll (fres->op_id));
    }
    else
    {
      if (NULL != op->data_cb)
        ((GNUNET_PSYCSTORE_FragmentCallback)
         op->data_cb) (op->cls, mmsg, ntohl (fres->psycstore_flags));
    }
    break;

  case GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_STATE:
    if (size < sizeof (struct StateResult))
    {
      LOG (GNUNET_ERROR_TYPE_ERROR,
           "Received message of type %d with length %lu bytes. "
           "Expected >= %lu\n",
           type, size, sizeof (struct StateResult));
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }

    sres = (const struct StateResult *) msg;
    const char *name = (const char *) &sres[1];
    uint16_t name_size = ntohs (sres->name_size);

    if (name_size <= 2 || '\0' != name[name_size - 1])
    {
      LOG (GNUNET_ERROR_TYPE_ERROR,
           "Received state result message (type %d) with invalid name.\n",
           type);
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }

    op = find_op_by_id (h, GNUNET_ntohll (sres->op_id));
    if (NULL == op)
    {
      LOG (GNUNET_ERROR_TYPE_DEBUG,
           "No callback registered for operation with ID %" PRIu64 ".\n",
           type, GNUNET_ntohll (sres->op_id));
    }
    else
    {
      if (NULL != op->data_cb)
        ((GNUNET_PSYCSTORE_StateCallback)
         op->data_cb) (op->cls, name, (char *) &sres[1] + name_size,
                       ntohs (sres->header.size) - sizeof (*sres) - name_size);
    }
    break;

  default:
    GNUNET_break (0);
    reschedule_connect (h);
    return;
  }

  GNUNET_CLIENT_receive (h->client, &message_handler, h,
                         GNUNET_TIME_UNIT_FOREVER_REL);
}
Ejemplo n.º 5
0
/**
 * Type of a function to call when we receive a message
 * from the service.
 *
 * @param cls closure
 * @param msg message received, NULL on timeout or fatal error
 */
static void
message_handler (void *cls,
		 const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_IDENTITY_Handle *h = cls;
  struct GNUNET_IDENTITY_Operation *op;
  struct GNUNET_IDENTITY_Ego *ego;
  const struct GNUNET_IDENTITY_ResultCodeMessage *rcm;
  const struct GNUNET_IDENTITY_UpdateMessage *um;
  const struct GNUNET_IDENTITY_SetDefaultMessage *sdm;
  struct GNUNET_CRYPTO_EcdsaPublicKey pub;
  struct GNUNET_HashCode id;
  const char *str;
  uint16_t size;
  uint16_t name_len;

  if (NULL == msg)
  {
    reschedule_connect (h);
    return;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Received message of type %d from identity service\n",
       ntohs (msg->type));
  size = ntohs (msg->size);
  switch (ntohs (msg->type))
  {
  case GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE:
    if (size < sizeof (struct GNUNET_IDENTITY_ResultCodeMessage))
    {
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }
    rcm = (const struct GNUNET_IDENTITY_ResultCodeMessage *) msg;
    str = (const char *) &rcm[1];
    if ( (size > sizeof (struct GNUNET_IDENTITY_ResultCodeMessage)) &&
	 ('\0' != str[size - sizeof (struct GNUNET_IDENTITY_ResultCodeMessage) - 1]) )
    {
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }
    if (size == sizeof (struct GNUNET_IDENTITY_ResultCodeMessage))
      str = NULL;

    op = h->op_head;
    GNUNET_CONTAINER_DLL_remove (h->op_head,
				 h->op_tail,
				 op);
    GNUNET_CLIENT_receive (h->client, &message_handler, h,
			   GNUNET_TIME_UNIT_FOREVER_REL);
    if (NULL != op->cont)
      op->cont (op->cls,
		str);
    else if (NULL != op->cb)
      op->cb (op->cls, NULL, NULL, NULL);
    GNUNET_free (op);
    break;
  case GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE:
    if (size < sizeof (struct GNUNET_IDENTITY_UpdateMessage))
    {
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }
    um = (const struct GNUNET_IDENTITY_UpdateMessage *) msg;
    name_len = ntohs (um->name_len);

    str = (const char *) &um[1];
    if ( (size != name_len + sizeof (struct GNUNET_IDENTITY_UpdateMessage)) ||
	 ( (0 != name_len) &&
	   ('\0' != str[name_len - 1])) )
    {
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }
    if (GNUNET_YES == ntohs (um->end_of_list))
    {
      /* end of initial list of data */
      GNUNET_CLIENT_receive (h->client, &message_handler, h,
			     GNUNET_TIME_UNIT_FOREVER_REL);
      if (NULL != h->cb)
	h->cb (h->cb_cls, NULL, NULL, NULL);
      break;
    }
    GNUNET_CRYPTO_ecdsa_key_get_public (&um->private_key,
				      &pub);
    GNUNET_CRYPTO_hash (&pub, sizeof (pub), &id);
    if (0 == name_len)
      str = NULL;
    else
      str = (const char *) &um[1];
    ego = GNUNET_CONTAINER_multihashmap_get (h->egos,
					     &id);
    if (NULL == ego)
    {
      /* ego was created */
      if (NULL == str)
      {
	/* deletion of unknown ego? not allowed */
	GNUNET_break (0);
	reschedule_connect (h);
	return;
      }
      ego = GNUNET_new (struct GNUNET_IDENTITY_Ego);
      ego->pk = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
      *ego->pk = um->private_key;
      ego->name = GNUNET_strdup (str);
      ego->id = id;
      GNUNET_assert (GNUNET_YES ==
		     GNUNET_CONTAINER_multihashmap_put (h->egos,
							&ego->id,
							ego,
							GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
    }
    if (NULL == str)
    {
      /* ego was deleted */
      GNUNET_assert (GNUNET_YES ==
		     GNUNET_CONTAINER_multihashmap_remove (h->egos,
							   &ego->id,
							   ego));
    }
    else
    {
      /* ego changed name */
      GNUNET_free (ego->name);
      ego->name = GNUNET_strdup (str);
    }
    GNUNET_CLIENT_receive (h->client, &message_handler, h,
			   GNUNET_TIME_UNIT_FOREVER_REL);
    /* inform application about change */
    if (NULL != h->cb)
      h->cb (h->cb_cls,
	     ego,
	     &ego->ctx,
	     str);
    if (NULL == str)
    {
      GNUNET_free (ego->pk);
      GNUNET_free (ego->name);
      GNUNET_free (ego);
    }
    break;
  case GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT:
    if (size < sizeof (struct GNUNET_IDENTITY_SetDefaultMessage))
    {
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }
    sdm = (const struct GNUNET_IDENTITY_SetDefaultMessage *) msg;
    GNUNET_break (0 == ntohs (sdm->reserved));
    name_len = ntohs (sdm->name_len);
    str = (const char *) &sdm[1];
    if ( (size != name_len + sizeof (struct GNUNET_IDENTITY_SetDefaultMessage)) ||
	 ( (0 != name_len) &&
	   ('\0' != str[name_len - 1]) ) )
    {
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }
    /* Note: we know which service this should be for, so we're not
       really using 'str' henceforth */
    GNUNET_CRYPTO_ecdsa_key_get_public (&sdm->private_key,
				      &pub);
    GNUNET_CRYPTO_hash (&pub, sizeof (pub), &id);
    ego = GNUNET_CONTAINER_multihashmap_get (h->egos,
					     &id);
    if (NULL == ego)
    {
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }
    op = h->op_head;
    if (NULL == op)
    {
      GNUNET_break (0);
      reschedule_connect (h);
      return;
    }
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Received SET_DEFAULT message from identity service\n");
    GNUNET_CONTAINER_DLL_remove (h->op_head,
				 h->op_tail,
				 op);
    GNUNET_CLIENT_receive (h->client, &message_handler, h,
			   GNUNET_TIME_UNIT_FOREVER_REL);
    if (NULL != op->cb)
      op->cb (op->cls,
	      ego,
	      &ego->ctx,
	      ego->name);
    GNUNET_free (op);
    break;
  default:
    GNUNET_break (0);
    reschedule_connect (h);
    return;
  }
}