Ejemplo n.º 1
0
/**
 * Handles messages received from the service.  Calls the proper client
 * callback.
 */
static void
process_result (struct GNUNET_CHAT_Room *room,
                const struct GNUNET_MessageHeader *reply)
{
  struct LeaveNotificationMessage *leave_msg;
  struct JoinNotificationMessage *join_msg;
  struct ReceiveNotificationMessage *received_msg;
  struct ConfirmationReceiptMessage *receipt;
  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
  GNUNET_HashCode id;
  const GNUNET_HashCode *sender;
  struct GNUNET_CONTAINER_MetaData *meta;
  struct GNUNET_CHAT_SendReceiptContext *src;
  struct MemberList *pos;
  struct MemberList *prev;
  struct GNUNET_CRYPTO_AesSessionKey key;
  char decrypted_msg[MAX_MESSAGE_LENGTH];
  uint16_t size;
  uint16_t meta_len;
  uint16_t msg_len;
  char *message_content;

  size = ntohs (reply->size);
  switch (ntohs (reply->type))
  {
  case GNUNET_MESSAGE_TYPE_CHAT_JOIN_NOTIFICATION:
#if DEBUG_CHAT
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a join notification\n");
#endif
    if (size < sizeof (struct JoinNotificationMessage))
    {
      GNUNET_break (0);
      return;
    }
    join_msg = (struct JoinNotificationMessage *) reply;
    meta_len = size - sizeof (struct JoinNotificationMessage);
    meta =
        GNUNET_CONTAINER_meta_data_deserialize ((const char *) &join_msg[1],
                                                meta_len);
    if (NULL == meta)
    {
      GNUNET_break (0);
      return;
    }
    pos = GNUNET_malloc (sizeof (struct MemberList));
    pos->meta = meta;
    GNUNET_CRYPTO_hash (&join_msg->public_key,
                        sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
                        &pos->id);
    GNUNET_PSEUDONYM_add (room->cfg, &pos->id, meta);
    pos->next = room->members;
    room->members = pos;
    if (GNUNET_NO == room->is_joined)
    {
      GNUNET_CRYPTO_rsa_key_get_public (room->my_private_key, &pkey);
      if (0 ==
          memcmp (&join_msg->public_key, &pkey,
                  sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)))
      {
        room->join_callback (room->join_callback_cls);
        room->is_joined = GNUNET_YES;
      }
      else
      {
        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                    _("The current user must be the the first one joined\n"));
        GNUNET_break (0);
        return;
      }
    }
    else
      room->member_list_callback (room->member_list_callback_cls, meta,
                                  &join_msg->public_key,
                                  ntohl (join_msg->msg_options));
    break;
  case GNUNET_MESSAGE_TYPE_CHAT_LEAVE_NOTIFICATION:
#if DEBUG_CHAT
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a leave notification\n");
#endif
    if (size < sizeof (struct LeaveNotificationMessage))
    {
      GNUNET_break (0);
      return;
    }
    leave_msg = (struct LeaveNotificationMessage *) reply;
    room->member_list_callback (room->member_list_callback_cls, NULL,
                                &leave_msg->user, GNUNET_CHAT_MSG_OPTION_NONE);
    GNUNET_CRYPTO_hash (&leave_msg->user,
                        sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
                        &id);
    prev = NULL;
    pos = room->members;
    while ((NULL != pos) &&
           (0 != memcmp (&pos->id, &id, sizeof (GNUNET_HashCode))))
    {
      prev = pos;
      pos = pos->next;
    }
    GNUNET_assert (NULL != pos);
    if (NULL == prev)
      room->members = pos->next;
    else
      prev->next = pos->next;
    GNUNET_CONTAINER_meta_data_destroy (pos->meta);
    GNUNET_free (pos);
    break;
  case GNUNET_MESSAGE_TYPE_CHAT_MESSAGE_NOTIFICATION:
#if DEBUG_CHAT
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a message notification\n");
#endif
    if (size <= sizeof (struct ReceiveNotificationMessage))
    {
      GNUNET_break (0);
      return;
    }
    received_msg = (struct ReceiveNotificationMessage *) reply;
    if (0 != (ntohl (received_msg->msg_options) & GNUNET_CHAT_MSG_ACKNOWLEDGED))
    {
      src = GNUNET_malloc (sizeof (struct GNUNET_CHAT_SendReceiptContext));
      src->chat_room = room;
      src->received_msg = GNUNET_memdup (received_msg, size);
      GNUNET_CLIENT_notify_transmit_ready (room->client,
                                           sizeof (struct
                                                   ConfirmationReceiptMessage),
                                           GNUNET_CONSTANTS_SERVICE_TIMEOUT,
                                           GNUNET_YES,
                                           &transmit_acknowledge_request, src);
    }
    msg_len = size - sizeof (struct ReceiveNotificationMessage);
    if (0 != (ntohl (received_msg->msg_options) & GNUNET_CHAT_MSG_PRIVATE))
    {
      if (-1 ==
          GNUNET_CRYPTO_rsa_decrypt (room->my_private_key,
                                     &received_msg->encrypted_key, &key,
                                     sizeof (struct
                                             GNUNET_CRYPTO_AesSessionKey)))
      {
        GNUNET_break (0);
        return;
      }
      msg_len =
          GNUNET_CRYPTO_aes_decrypt (&received_msg[1], msg_len, &key,
                                     (const struct
                                      GNUNET_CRYPTO_AesInitializationVector *)
                                     INITVALUE, decrypted_msg);
      message_content = decrypted_msg;
    }
    else
    {
      message_content = GNUNET_malloc (msg_len + 1);
      memcpy (message_content, &received_msg[1], msg_len);
    }
    message_content[msg_len] = '\0';
    if (0 != (ntohl (received_msg->msg_options) & GNUNET_CHAT_MSG_ANONYMOUS))
    {
      sender = NULL;
      meta = NULL;
    }
    else
    {
      pos = room->members;
      while ((NULL != pos) &&
             (0 !=
              memcmp (&pos->id, &received_msg->sender,
                      sizeof (GNUNET_HashCode))))
        pos = pos->next;
      GNUNET_assert (NULL != pos);
      sender = &received_msg->sender;
      meta = pos->meta;
    }
    room->message_callback (room->message_callback_cls, room, sender, meta,
                            message_content,
                            GNUNET_TIME_absolute_ntoh (received_msg->timestamp),
                            ntohl (received_msg->msg_options));
    if (message_content != decrypted_msg)
      GNUNET_free (message_content);
    break;
  case GNUNET_MESSAGE_TYPE_CHAT_CONFIRMATION_NOTIFICATION:
#if DEBUG_CHAT
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a confirmation receipt\n");
#endif
    if (size < sizeof (struct ConfirmationReceiptMessage))
    {
      GNUNET_break (0);
      return;
    }
    receipt = (struct ConfirmationReceiptMessage *) reply;
    if (NULL != room->confirmation_callback)
      room->confirmation_callback (room->confirmation_cls, room,
                                   ntohl (receipt->sequence_number),
                                   GNUNET_TIME_absolute_ntoh
                                   (receipt->timestamp), &receipt->target);
    break;
  default:
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unknown message type: '%u'\n"),
                ntohs (reply->type));
    GNUNET_break_op (0);
    break;
  }
}
Ejemplo n.º 2
0
/**
 * Join a chat room.
 *
 * @param cfg configuration
 * @param nick_name nickname of the user joining (used to
 *                  determine which public key to use);
 *                  the nickname should probably also
 *                  be used in the member_info (as "EXTRACTOR_TITLE")
 * @param member_info information about the joining member
 * @param room_name name of the room
 * @param msg_options message options of the joining user
 * @param joinCallback function to call on successful join
 * @param join_cls closure for joinCallback
 * @param messageCallback which function to call if a message has
 *        been received?
 * @param message_cls argument to callback
 * @param memberCallback which function to call for join/leave notifications
 * @param member_cls argument to callback
 * @param confirmationCallback which function to call for confirmations (maybe NULL)
 * @param confirmation_cls argument to callback
 * @param me member ID (pseudonym)
 * @return NULL on error
 */
struct GNUNET_CHAT_Room *
GNUNET_CHAT_join_room (const struct GNUNET_CONFIGURATION_Handle *cfg,
                       const char *nick_name,
                       struct GNUNET_CONTAINER_MetaData *member_info,
                       const char *room_name,
                       enum GNUNET_CHAT_MsgOptions msg_options,
                       GNUNET_CHAT_JoinCallback joinCallback, void *join_cls,
                       GNUNET_CHAT_MessageCallback messageCallback,
                       void *message_cls,
                       GNUNET_CHAT_MemberListCallback memberCallback,
                       void *member_cls,
                       GNUNET_CHAT_MessageConfirmation confirmationCallback,
                       void *confirmation_cls, GNUNET_HashCode * me)
{
  struct GNUNET_CHAT_Room *chat_room;
  struct GNUNET_CRYPTO_RsaPrivateKey *priv_key;
  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub_key;
  struct GNUNET_CLIENT_Connection *client;

#if DEBUG_CHAT
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Joining the room '%s'\n", room_name);
#endif
  priv_key = init_private_key (cfg, nick_name);
  if (NULL == priv_key)
    return NULL;
  GNUNET_CRYPTO_rsa_key_get_public (priv_key, &pub_key);
  GNUNET_CRYPTO_hash (&pub_key,
                      sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
                      me);
  GNUNET_PSEUDONYM_add (cfg, me, member_info);
  client = GNUNET_CLIENT_connect ("chat", cfg);
  if (NULL == client)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("Failed to connect to the chat service\n"));
    return NULL;
  }
  if (NULL == joinCallback)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("Undefined mandatory parameter: joinCallback\n"));
    return NULL;
  }
  if (NULL == messageCallback)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("Undefined mandatory parameter: messageCallback\n"));
    return NULL;
  }
  if (NULL == memberCallback)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("Undefined mandatory parameter: memberCallback\n"));
    return NULL;
  }
  chat_room = GNUNET_malloc (sizeof (struct GNUNET_CHAT_Room));
  chat_room->msg_options = msg_options;
  chat_room->room_name = GNUNET_strdup (room_name);
  chat_room->member_info = GNUNET_CONTAINER_meta_data_duplicate (member_info);
  chat_room->my_private_key = priv_key;
  chat_room->is_joined = GNUNET_NO;
  chat_room->join_callback = joinCallback;
  chat_room->join_callback_cls = join_cls;
  chat_room->message_callback = messageCallback;
  chat_room->message_callback_cls = message_cls;
  chat_room->member_list_callback = memberCallback;
  chat_room->member_list_callback_cls = member_cls;
  chat_room->confirmation_callback = confirmationCallback;
  chat_room->confirmation_cls = confirmation_cls;
  chat_room->cfg = cfg;
  chat_room->client = client;
  chat_room->members = NULL;
  if (GNUNET_SYSERR == rejoin_room (chat_room))
  {
    GNUNET_CHAT_leave_room (chat_room);
    return NULL;
  }
  return chat_room;
}
Ejemplo n.º 3
0
int
main (int argc, char *argv[])
{
  int ok;
  struct GNUNET_HashCode rid1;
  struct GNUNET_HashCode id2;
  struct GNUNET_HashCode rid2;
  struct GNUNET_HashCode fid;
  struct GNUNET_HashCode id3;

  int old;
  int newVal;
  struct GNUNET_CONFIGURATION_Handle *cfg;
  char *name1;
  char *name2;
  char *name3;
  char *name1_unique;
  char *name2_unique;
  char *noname;
  int noname_is_a_dup;
  int notiCount, fakenotiCount;
  int count;
  static char m[1024 * 1024 * 10];

  memset (m, 'b', sizeof (m));
  m[sizeof (m) - 1] = '\0';

  GNUNET_log_setup ("test-pseudonym", "WARNING", NULL);
  ok = GNUNET_YES;
  GNUNET_CRYPTO_random_disable_entropy_gathering ();
  (void) GNUNET_DISK_directory_remove ("/tmp/gnunet-pseudonym-test");
  cfg = GNUNET_CONFIGURATION_create ();
  if (-1 == GNUNET_CONFIGURATION_parse (cfg, "test_pseudonym_data.conf"))
  {
    GNUNET_CONFIGURATION_destroy (cfg);
    GNUNET_break (0);
    return -1;
  }
  notiCount = 0;
  fakenotiCount = 0;
  count = 0;
  GNUNET_PSEUDONYM_discovery_callback_register (cfg, &fake_noti_callback,
                                                &fakenotiCount);
  GNUNET_PSEUDONYM_discovery_callback_register (cfg, &noti_callback,
                                                &notiCount);
  GNUNET_PSEUDONYM_discovery_callback_unregister (&false_callback, &count);
  GNUNET_PSEUDONYM_discovery_callback_unregister (&fake_noti_callback,
                                                  &fakenotiCount);

  /* ACTUAL TEST CODE */
  old = GNUNET_PSEUDONYM_list_all (cfg, NULL, NULL);
  meta = GNUNET_CONTAINER_meta_data_create ();
  GNUNET_CONTAINER_meta_data_insert (meta, "<test>", EXTRACTOR_METATYPE_TITLE,
                                     EXTRACTOR_METAFORMAT_UTF8, "text/plain",
                                     "test", strlen ("test") + 1);
  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &id1);
  GNUNET_PSEUDONYM_add (cfg, &id1, meta);
  CHECK (notiCount == 1);
  GNUNET_PSEUDONYM_add (cfg, &id1, meta);
  CHECK (notiCount == 2);
  newVal = GNUNET_PSEUDONYM_list_all (cfg, &iter, &ok);
  CHECK (old < newVal);
  old = newVal;
  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &id2);
  GNUNET_PSEUDONYM_add (cfg, &id2, meta);
  CHECK (notiCount == 3);
  newVal = GNUNET_PSEUDONYM_list_all (cfg, &iter, &ok);
  CHECK (old < newVal);
  GNUNET_assert (GNUNET_OK ==
                 GNUNET_CONTAINER_meta_data_insert (meta, "<test>",
                                                    EXTRACTOR_METATYPE_COMMENT,
                                                    EXTRACTOR_METAFORMAT_UTF8,
                                                    "text/plain", m,
                                                    strlen (m) + 1));
  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &id3);
  GNUNET_PSEUDONYM_add (cfg, &id3, meta);
  GNUNET_PSEUDONYM_get_info (cfg, &id3, NULL, NULL, &name3, NULL);
  CHECK (name3 != NULL);
  GNUNET_PSEUDONYM_get_info (cfg, &id2, NULL, NULL, &name2, NULL);
  CHECK (name2 != NULL);
  GNUNET_PSEUDONYM_get_info (cfg, &id1, NULL, NULL, &name1, NULL);
  CHECK (name1 != NULL);
  CHECK (0 == strcmp (name1, name2));
  name1_unique = GNUNET_PSEUDONYM_name_uniquify (cfg, &id1, name1, NULL);
  name2_unique = GNUNET_PSEUDONYM_name_uniquify (cfg, &id2, name2, NULL);
  CHECK (0 != strcmp (name1_unique, name2_unique));
  CHECK (GNUNET_SYSERR == GNUNET_PSEUDONYM_name_to_id (cfg, "fake", &rid2));
  CHECK (GNUNET_SYSERR == GNUNET_PSEUDONYM_name_to_id (cfg, name2, &rid2));
  CHECK (GNUNET_SYSERR == GNUNET_PSEUDONYM_name_to_id (cfg, name1, &rid1));
  CHECK (GNUNET_OK == GNUNET_PSEUDONYM_name_to_id (cfg, name2_unique, &rid2));
  CHECK (GNUNET_OK == GNUNET_PSEUDONYM_name_to_id (cfg, name1_unique, &rid1));
  CHECK (0 == memcmp (&id1, &rid1, sizeof (struct GNUNET_HashCode)));
  CHECK (0 == memcmp (&id2, &rid2, sizeof (struct GNUNET_HashCode)));

  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &fid);
  GNUNET_log_skip (1, GNUNET_NO);
  CHECK (0 == GNUNET_PSEUDONYM_rank (cfg, &fid, 0));
  GNUNET_log_skip (0, GNUNET_YES);
  CHECK (GNUNET_OK == GNUNET_PSEUDONYM_get_info (cfg, &fid, NULL, NULL, &noname, &noname_is_a_dup));
  CHECK (noname != NULL);
  CHECK (noname_is_a_dup == GNUNET_YES);
  CHECK (0 == GNUNET_PSEUDONYM_rank (cfg, &id1, 0));
  CHECK (5 == GNUNET_PSEUDONYM_rank (cfg, &id1, 5));
  CHECK (-5 == GNUNET_PSEUDONYM_rank (cfg, &id1, -10));
  CHECK (0 == GNUNET_PSEUDONYM_rank (cfg, &id1, 5));
  GNUNET_free (name1);
  GNUNET_free (name2);
  GNUNET_free (name1_unique);
  GNUNET_free (name2_unique);
  GNUNET_free (name3);
  GNUNET_free (noname);
  /* END OF TEST CODE */
FAILURE:
  GNUNET_PSEUDONYM_discovery_callback_unregister (&noti_callback, &notiCount);
  GNUNET_CONTAINER_meta_data_destroy (meta);
  GNUNET_CONFIGURATION_destroy (cfg);
  GNUNET_break (GNUNET_OK ==
                GNUNET_DISK_directory_remove ("/tmp/gnunet-pseudonym-test"));
  return (ok == GNUNET_YES) ? 0 : 1;
}