commit 1bdbb8bc0cec3650843daf5eb559ed46e9a69fd7
parent 022002438e4047d235a688cfd9da7b63ab990103
Author: Christian Grothoff <christian@grothoff.org>
Date: Wed, 29 May 2013 08:19:14 +0000
-removing chat from build
Diffstat:
13 files changed, 0 insertions(+), 5460 deletions(-)
diff --git a/configure.ac b/configure.ac
@@ -1223,8 +1223,6 @@ src/ats/Makefile
src/ats/ats.conf
src/ats-tool/Makefile
src/block/Makefile
-src/chat/Makefile
-src/chat/chat.conf
src/core/Makefile
src/core/core.conf
src/consensus/Makefile
diff --git a/src/chat/Makefile.am b/src/chat/Makefile.am
@@ -1,137 +0,0 @@
-INCLUDES = -I$(top_srcdir)/src/include
-
-pkgcfgdir= $(pkgdatadir)/config.d/
-
-libexecdir= $(pkglibdir)/libexec/
-
-pkgcfg_DATA = \
- chat.conf
-
-if MINGW
- WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
-endif
-
-if USE_COVERAGE
- AM_CFLAGS = -fprofile-arcs -ftest-coverage
-endif
-
-lib_LTLIBRARIES = libgnunetchat.la
-
-libgnunetchat_la_SOURCES = \
- chat.c chat.h
-
-libgnunetchat_la_LIBADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/fs/libgnunetfs.la
-
-libgnunetchat_la_DEPENDENCIES = \
- $(top_builddir)/src/fs/libgnunetfs.la
-
-libgnunetchat_la_LDFLAGS = \
- $(GN_LIB_LDFLAGS) $(WINFLAGS) \
- -version-info 0:0:0
-
-libexec_PROGRAMS = \
- gnunet-service-chat
-
-bin_PROGRAMS = \
- gnunet-chat
-
-gnunet_service_chat_SOURCES = \
- gnunet-service-chat.c
-gnunet_service_chat_LDADD = \
- $(top_builddir)/src/core/libgnunetcore.la \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(GN_LIBINTL)
-
-gnunet_chat_SOURCES = \
- gnunet-chat.c
-gnunet_chat_LDADD = \
- $(top_builddir)/src/chat/libgnunetchat.la \
- $(top_builddir)/src/fs/libgnunetfs.la \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(GN_LIBINTL)
-gnunet_chat_DEPENDENCIES = \
- libgnunetchat.la
-
-check_PROGRAMS = \
- test_chat \
- test_chat_acknowledgement \
- test_chat_anonymous \
- test_chat_authentication \
- test_chat_p2p \
- test_chat_acknowledgement_p2p \
- test_chat_anonymous_p2p \
- test_chat_authentication_p2p \
- test_chat_private \
- test_chat_private_p2p
-
-if ENABLE_TEST_RUN
-TESTS = $(check_PROGRAMS)
-endif
-
-test_chat_SOURCES = \
- test_chat.c
-test_chat_LDADD = \
- $(top_builddir)/src/chat/libgnunetchat.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
-test_chat_acknowledgement_SOURCES = \
- test_chat.c
-test_chat_acknowledgement_LDADD = \
- $(top_builddir)/src/chat/libgnunetchat.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
-test_chat_anonymous_SOURCES = \
- test_chat.c
-test_chat_anonymous_LDADD = \
- $(top_builddir)/src/chat/libgnunetchat.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
-test_chat_authentication_SOURCES = \
- test_chat.c
-test_chat_authentication_LDADD = \
- $(top_builddir)/src/chat/libgnunetchat.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
-test_chat_p2p_SOURCES = \
- test_chat.c
-test_chat_p2p_LDADD = \
- $(top_builddir)/src/chat/libgnunetchat.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
-test_chat_acknowledgement_p2p_SOURCES = \
- test_chat.c
-test_chat_acknowledgement_p2p_LDADD = \
- $(top_builddir)/src/chat/libgnunetchat.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
-test_chat_anonymous_p2p_SOURCES = \
- test_chat.c
-test_chat_anonymous_p2p_LDADD = \
- $(top_builddir)/src/chat/libgnunetchat.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
-test_chat_authentication_p2p_SOURCES = \
- test_chat.c
-test_chat_authentication_p2p_LDADD = \
- $(top_builddir)/src/chat/libgnunetchat.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
-test_chat_private_SOURCES = \
- test_chat_private.c
-test_chat_private_LDADD = \
- $(top_builddir)/src/chat/libgnunetchat.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
-test_chat_private_p2p_SOURCES = \
- test_chat_private.c
-test_chat_private_p2p_LDADD = \
- $(top_builddir)/src/chat/libgnunetchat.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
-EXTRA_DIST = \
- test_chat_data.conf \
- test_chat_peer1.conf \
- test_chat_peer2.conf \
- test_chat_peer3.conf
diff --git a/src/chat/chat.c b/src/chat/chat.c
@@ -1,822 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2008, 2011 Christian Grothoff (and other contributing authors)
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file chat/chat.c
- * @brief convenience API for sending and receiving chat messages
- * @author Christian Grothoff
- * @author Nathan Evans
- * @author Vitaly Minko
- */
-
-#include "platform.h"
-#include "gnunet_constants.h"
-#include "gnunet_protocols.h"
-#include "gnunet_signatures.h"
-#include "gnunet_fs_service.h"
-#include "chat.h"
-
-#define DEBUG_CHAT GNUNET_EXTRA_LOGGING
-#define NICK_IDENTITY_PREFIX ".chat_identity_"
-
-
-/**
- * Handle for a chat room.
- */
-struct GNUNET_CHAT_Room
-{
- struct GNUNET_CLIENT_Connection *client;
-
- const struct GNUNET_CONFIGURATION_Handle *cfg;
-
- struct GNUNET_CONTAINER_MetaData *member_info;
-
- char *room_name;
-
- struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
-
- struct MemberList *members;
-
- int is_joined;
-
- GNUNET_CHAT_JoinCallback join_callback;
-
- void *join_callback_cls;
-
- GNUNET_CHAT_MessageCallback message_callback;
-
- void *message_callback_cls;
-
- GNUNET_CHAT_MemberListCallback member_list_callback;
-
- void *member_list_callback_cls;
-
- GNUNET_CHAT_MessageConfirmation confirmation_callback;
-
- void *confirmation_cls;
-
- uint32_t sequence_number;
-
- uint32_t msg_options;
-
-};
-
-/**
- * Linked list of members in the chat room.
- */
-struct MemberList
-{
- struct MemberList *next;
-
- /**
- * Description of the member.
- */
- struct GNUNET_CONTAINER_MetaData *meta;
-
- /**
- * Member ID (pseudonym).
- */
- struct GNUNET_HashCode id;
-
-};
-
-/**
- * Context for transmitting a send-message request.
- */
-struct GNUNET_CHAT_SendMessageContext
-{
- /**
- * Handle for the chat room.
- */
- struct GNUNET_CHAT_Room *chat_room;
-
- /**
- * Message that we're sending.
- */
- char *message;
-
- /**
- * Options for the message.
- */
- enum GNUNET_CHAT_MsgOptions options;
-
- /**
- * Receiver of the message. NULL to send to everyone in the room.
- */
- const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *receiver;
-
- /**
- * Sequence id of the message.
- */
- uint32_t sequence_number;
-
-};
-
-/**
- * Context for transmitting a confirmation receipt.
- */
-struct GNUNET_CHAT_SendReceiptContext
-{
- /**
- * Handle for the chat room.
- */
- struct GNUNET_CHAT_Room *chat_room;
-
- /**
- * The original message that we're going to acknowledge.
- */
- struct ReceiveNotificationMessage *received_msg;
-
-};
-
-/**
- * Ask client to send a join request.
- */
-static int
-rejoin_room (struct GNUNET_CHAT_Room *chat_room);
-
-
-/**
- * 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;
-}
-
-
-/**
- * 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;
- struct GNUNET_HashCode id;
- const struct 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_FS_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 (struct 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 (struct 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;
- }
-}
-
-
-/**
- * Listen for incoming messages on this chat room. Also, support servers going
- * away/coming back (i.e. rejoin chat room to keep server state up to date).
- *
- * @param cls closure, pointer to the 'struct GNUNET_CHAT_Room'
- * @param msg message received, NULL on timeout or fatal error
- */
-static void
-receive_results (void *cls, const struct GNUNET_MessageHeader *msg)
-{
- struct GNUNET_CHAT_Room *chat_room = cls;
-
-#if DEBUG_CHAT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a message from the service\n");
-#endif
- if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & GNUNET_SCHEDULER_get_reason ()))
- return;
- if (NULL == msg)
- {
- GNUNET_break (0);
- rejoin_room (chat_room);
- return;
- }
- process_result (chat_room, msg);
- if (NULL == chat_room->client)
- return; /* fatal error */
- /* continue receiving */
- GNUNET_CLIENT_receive (chat_room->client, &receive_results, chat_room,
- GNUNET_TIME_UNIT_FOREVER_REL);
-}
-
-
-/**
- * Read existing private key from file or create a new one if it does not exist
- * yet.
- * Returns the private key on success, NULL on error.
- */
-static struct GNUNET_CRYPTO_RsaPrivateKey *
-init_private_key (const struct GNUNET_CONFIGURATION_Handle *cfg,
- const char *nick_name)
-{
- char *home;
- char *keyfile;
- struct GNUNET_CRYPTO_RsaPrivateKey *privKey;
-
-#if DEBUG_CHAT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Initializing private key\n");
-#endif
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (cfg, "chat", "HOME", &home))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "chat", "HOME");
- return NULL;
- }
- GNUNET_DISK_directory_create (home);
- if (GNUNET_YES != GNUNET_DISK_directory_test (home, GNUNET_YES))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Failed to access chat home directory `%s'\n"), home);
- GNUNET_free (home);
- return NULL;
- }
- /* read or create private key */
- keyfile =
- GNUNET_malloc (strlen (home) + strlen (NICK_IDENTITY_PREFIX) +
- strlen (nick_name) + 2);
- strcpy (keyfile, home);
- GNUNET_free (home);
- if (keyfile[strlen (keyfile) - 1] != DIR_SEPARATOR)
- strcat (keyfile, DIR_SEPARATOR_STR);
- strcat (keyfile, NICK_IDENTITY_PREFIX);
- strcat (keyfile, nick_name);
- privKey = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
- if (NULL == privKey)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Failed to create/open key in file `%s'\n"), keyfile);
- }
- GNUNET_free (keyfile);
- return privKey;
-}
-
-
-/**
- * Transmit a join request to the chat service.
- *
- * @param cls closure, pointer to the 'struct GNUNET_CHAT_Room'
- * @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_join_request (void *cls, size_t size, void *buf)
-{
- struct GNUNET_CHAT_Room *chat_room = cls;
- struct JoinRequestMessage *join_msg;
- char *room;
- char *meta;
- size_t room_len;
- ssize_t meta_len;
- size_t size_of_join;
-
- if (NULL == buf)
- {
-#if DEBUG_CHAT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Could not transmit join request, retrying...\n");
-#endif
- rejoin_room (chat_room);
- return 0;
- }
-#if DEBUG_CHAT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Transmitting join request to the service\n");
-#endif
- room_len = strlen (chat_room->room_name);
- meta_len =
- GNUNET_CONTAINER_meta_data_get_serialized_size (chat_room->member_info);
- size_of_join = sizeof (struct JoinRequestMessage) + meta_len + room_len;
- GNUNET_assert (size >= size_of_join);
- join_msg = buf;
- join_msg->header.size = htons (size);
- join_msg->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_JOIN_REQUEST);
- join_msg->msg_options = htonl (chat_room->msg_options);
- join_msg->room_name_len = htons (room_len);
- join_msg->reserved = htons (0);
- join_msg->reserved2 = htonl (0);
- GNUNET_CRYPTO_rsa_key_get_public (chat_room->my_private_key,
- &join_msg->public_key);
- room = (char *) &join_msg[1];
- memcpy (room, chat_room->room_name, room_len);
- meta = &room[room_len];
- if (GNUNET_SYSERR ==
- GNUNET_CONTAINER_meta_data_serialize (chat_room->member_info, &meta,
- meta_len,
- GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not serialize metadata\n"));
- return 0;
- }
- GNUNET_CLIENT_receive (chat_room->client, &receive_results, chat_room,
- GNUNET_TIME_UNIT_FOREVER_REL);
- return size_of_join;
-}
-
-
-/**
- * Ask to send a join request.
- */
-static int
-rejoin_room (struct GNUNET_CHAT_Room *chat_room)
-{
- size_t size_of_join;
-
- size_of_join =
- sizeof (struct JoinRequestMessage) +
- GNUNET_CONTAINER_meta_data_get_serialized_size (chat_room->member_info) +
- strlen (chat_room->room_name);
- if (NULL ==
- GNUNET_CLIENT_notify_transmit_ready (chat_room->client, size_of_join,
- GNUNET_CONSTANTS_SERVICE_TIMEOUT,
- GNUNET_YES, &transmit_join_request,
- chat_room))
- return GNUNET_SYSERR;
- return GNUNET_OK;
-}
-
-
-/**
- * Leave a chat room.
- */
-void
-GNUNET_CHAT_leave_room (struct GNUNET_CHAT_Room *chat_room)
-{
- struct MemberList *pos;
-
-#if DEBUG_CHAT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Leaving the room '%s'\n",
- chat_room->room_name);
-#endif
- GNUNET_CLIENT_disconnect (chat_room->client);
- GNUNET_free (chat_room->room_name);
- GNUNET_CONTAINER_meta_data_destroy (chat_room->member_info);
- GNUNET_CRYPTO_rsa_key_free (chat_room->my_private_key);
- while (NULL != chat_room->members)
- {
- pos = chat_room->members;
- chat_room->members = pos->next;
- GNUNET_CONTAINER_meta_data_destroy (pos->meta);
- GNUNET_free (pos);
- }
- GNUNET_free (chat_room);
-}
-
-
-/**
- * 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, struct 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_FS_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;
-}
-
-
-/**
- * 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 (struct 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;
-}
-
-
-/**
- * Send a message.
- *
- * @param room handle for the chat room
- * @param message message to be sent
- * @param options options for the message
- * @param receiver use NULL to send to everyone in the room
- * @param sequence_number where to write the sequence id of the message
- */
-void
-GNUNET_CHAT_send_message (struct GNUNET_CHAT_Room *room, const char *message,
- enum GNUNET_CHAT_MsgOptions options,
- const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded
- *receiver, uint32_t * sequence_number)
-{
- size_t msg_size;
- struct GNUNET_CHAT_SendMessageContext *smc;
-
-#if DEBUG_CHAT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending a message\n");
-#endif
- room->sequence_number++;
- if (NULL != sequence_number)
- *sequence_number = room->sequence_number;
- smc = GNUNET_malloc (sizeof (struct GNUNET_CHAT_SendMessageContext));
- smc->chat_room = room;
- smc->message = GNUNET_strdup (message);
- smc->options = options;
- smc->receiver = receiver;
- smc->sequence_number = room->sequence_number;
- msg_size = strlen (message) + sizeof (struct TransmitRequestMessage);
- GNUNET_CLIENT_notify_transmit_ready (room->client, msg_size,
- GNUNET_CONSTANTS_SERVICE_TIMEOUT,
- GNUNET_YES, &transmit_send_request, smc);
-}
-
-/* end of chat.c */
diff --git a/src/chat/chat.conf.in b/src/chat/chat.conf.in
@@ -1,21 +0,0 @@
-[chat]
-AUTOSTART = YES
-@UNIXONLY@ PORT = 2090
-HOSTNAME = localhost
-HOME = $SERVICEHOME
-BINARY = gnunet-service-chat
-ACCEPT_FROM = 127.0.0.1;
-ACCEPT_FROM6 = ::1;
-UNIXPATH = /tmp/gnunet-service-chat.sock
-UNIX_MATCH_UID = NO
-UNIX_MATCH_GID = YES
-# DISABLE_SOCKET_FORWARDING = NO
-# USERNAME =
-# MAXBUF =
-# TIMEOUT =
-# DISABLEV6 =
-# BINDTO =
-# REJECT_FROM =
-# REJECT_FROM6 =
-# PREFIX =
-
diff --git a/src/chat/chat.h b/src/chat/chat.h
@@ -1,485 +0,0 @@
-/*
- This file is part of GNUnet
- (C) 2008, 2011 Christian Grothoff (and other contributing authors)
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file chat/chat.h
- * @brief support for chat
- * @author Christian Grothoff
- * @author Nathan Evans
- * @author Vitaly Minko
- */
-
-#ifndef CHAT_H
-#define CHAT_H
-
-#include "gnunet_chat_service.h"
-
-/**
- * Constant IV since we generate a new session key per each message.
- */
-#define INITVALUE "InitializationVectorValue"
-
-
-/**
- * Client-service messages
- */
-
-GNUNET_NETWORK_STRUCT_BEGIN
-
-/**
- * Notification sent by service to client indicating that we've received a chat
- * message. After this struct, the remaining bytes are the actual text message.
- * If the mesasge is private, then the text is encrypted, otherwise it's
- * plaintext.
- */
-struct ReceiveNotificationMessage
-{
- /**
- * Message type will be GNUNET_MESSAGE_TYPE_CHAT_MESSAGE_NOTIFICATION
- */
- struct GNUNET_MessageHeader header;
-
- /**
- * Message options, see GNUNET_CHAT_MsgOptions.
- */
- uint32_t msg_options GNUNET_PACKED;
-
- /**
- * Sequence number of the message (unique per sender).
- */
- uint32_t sequence_number GNUNET_PACKED;
-
- /**
- * For alignment (should be zero).
- */
- uint32_t reserved GNUNET_PACKED;
-
- /**
- * Timestamp of the message.
- */
- struct GNUNET_TIME_AbsoluteNBO timestamp;
-
- /**
- * Hash of the public key of the pseudonym of the sender of the message.
- * Should be all zeros for anonymous.
- */
- struct GNUNET_HashCode sender;
-
- /**
- * The encrypted session key.
- */
- struct GNUNET_CRYPTO_RsaEncryptedData encrypted_key;
-
-};
-
-
-/**
- * Request sent by client to transmit a chat message to another room members.
- * After this struct, the remaining bytes are the actual message in plaintext.
- * Private messages are encrypted on the service side.
- */
-struct TransmitRequestMessage
-{
- /**
- * Message type will be GNUNET_MESSAGE_TYPE_CHAT_TRANSMIT_REQUEST
- */
- struct GNUNET_MessageHeader header;
-
- /**
- * For alignment (should be zero).
- */
- uint32_t reserved GNUNET_PACKED;
-
- /**
- * Signature confirming receipt. Signature covers everything from header
- * through content.
- */
- struct GNUNET_CRYPTO_RsaSignature signature;
-
- /**
- * What is being signed and why?
- */
- struct GNUNET_CRYPTO_RsaSignaturePurpose purpose;
-
- /**
- * Desired message options, see GNUNET_CHAT_MsgOptions.
- */
- uint32_t msg_options GNUNET_PACKED;
-
- /**
- * Sequence number of the message (unique per sender).
- */
- uint32_t sequence_number GNUNET_PACKED;
-
- /**
- * Timestamp of the message.
- */
- struct GNUNET_TIME_AbsoluteNBO timestamp;
-
- /**
- * Who should receive this message? Set to all zeros for "everyone".
- */
- struct GNUNET_HashCode target;
-
-};
-
-
-/**
- * Receipt sent from a message receiver to the service to confirm delivery of
- * a chat message and from the service to sender of the original message to
- * acknowledge delivery.
- */
-struct ConfirmationReceiptMessage
-{
- /**
- * Message type will be
- * GNUNET_MESSAGE_TYPE_CHAT_CONFIRMATION_RECEIPT when sending from client,
- * GNUNET_MESSAGE_TYPE_CHAT_CONFIRMATION_NOTIFICATION when sending to client.
- */
- struct GNUNET_MessageHeader header;
-
- /**
- * For alignment (should be zero).
- */
- uint32_t reserved GNUNET_PACKED;
-
- /**
- * Signature confirming receipt. Signature covers everything from header
- * through content.
- */
- struct GNUNET_CRYPTO_RsaSignature signature;
-
- /**
- * What is being signed and why?
- */
- struct GNUNET_CRYPTO_RsaSignaturePurpose purpose;
-
- /**
- * Sequence number of the original message.
- */
- uint32_t sequence_number GNUNET_PACKED;
-
- /**
- * For alignment (should be zero).
- */
- uint32_t reserved2 GNUNET_PACKED;
-
- /**
- * Time of receipt.
- */
- struct GNUNET_TIME_AbsoluteNBO timestamp;
-
- /**
- * Who is confirming the receipt?
- */
- struct GNUNET_HashCode target;
-
- /**
- * Who is the author of the chat message?
- */
- struct GNUNET_HashCode author;
-
- /**
- * Hash of the (possibly encrypted) content.
- */
- struct GNUNET_HashCode content;
-
-};
-
-
-/**
- * Message send from client to daemon to join a chat room.
- * This struct is followed by the room name and then
- * the serialized ECRS meta data describing the new member.
- */
-struct JoinRequestMessage
-{
- /**
- * Message type will be GNUNET_MESSAGE_TYPE_CHAT_JOIN_REQUEST
- */
- struct GNUNET_MessageHeader header;
-
- /**
- * Options. Set all options that this client is willing to receive.
- * For example, if the client does not want to receive anonymous or
- * OTR messages but is willing to generate acknowledgements and
- * receive private messages, this should be set to
- * GNUNET_CHAT_MSG_PRIVATE | GNUNET_CHAT_MSG_ACKNOWLEDGED.
- */
- uint32_t msg_options GNUNET_PACKED;
-
- /**
- * Length of the room name.
- */
- uint16_t room_name_len GNUNET_PACKED;
-
- /**
- * For alignment (should be zero).
- */
- uint16_t reserved GNUNET_PACKED;
- uint32_t reserved2 GNUNET_PACKED;
-
- /**
- * Public key of the joining member.
- */
- struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded public_key;
-
-};
-
-
-/**
- * Message send by server to client to indicate joining of another room member.
- * This struct is followed by the serialized ECRS MetaData describing the new
- * member.
- */
-struct JoinNotificationMessage
-{
- /**
- * Message type will be GNUNET_MESSAGE_TYPE_CHAT_JOIN_NOTIFICATION
- */
- struct GNUNET_MessageHeader header;
-
- /**
- * Options. Set to all options that the new user is willing to
- * process. For example, if the client does not want to receive
- * anonymous or OTR messages but is willing to generate
- * acknowledgements and receive private messages, this should be set
- * to GNUNET_CHAT_MSG_PRIVATE | GNUNET_CHAT_MSG_ACKNOWLEDGED.
- */
- uint32_t msg_options GNUNET_PACKED;
-
- /**
- * Public key of the new user.
- */
- struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded public_key;
-
-};
-
-
-/**
- * Message send by server to client to indicate leaving of another room member.
- */
-struct LeaveNotificationMessage
-{
- /**
- * Message type will be GNUNET_MESSAGE_TYPE_CHAT_LEAVE_NOTIFICATION
- */
- struct GNUNET_MessageHeader header;
-
- /**
- * Reserved (for alignment).
- */
- uint32_t reserved GNUNET_PACKED;
-
- /**
- * Who is leaving?
- */
- struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded user;
-
-};
-
-
-/**
- * Peer-to-peer messages
- */
-
-/**
- * Message send by one peer to another to indicate joining of another room
- * member. This struct is followed by the room name and then the serialized
- * ECRS MetaData describing the new member.
- */
-struct P2PJoinNotificationMessage
-{
- /**
- * Message type will be GNUNET_MESSAGE_TYPE_CHAT_P2P_JOIN_NOTIFICATION
- */
- struct GNUNET_MessageHeader header;
-
- /**
- * Options. Set all options that this client is willing to receive.
- * For example, if the client does not want to receive anonymous or
- * OTR messages but is willing to generate acknowledgements and
- * receive private messages, this should be set to
- * GNUNET_CHAT_MSG_PRIVATE | GNUNET_CHAT_MSG_ACKNOWLEDGED.
- */
- uint32_t msg_options GNUNET_PACKED;
-
- /**
- * Length of the room name.
- */
- uint16_t room_name_len GNUNET_PACKED;
-
- /**
- * Reserved (should be zero).
- */
- uint16_t reserved GNUNET_PACKED;
- uint32_t reserved2 GNUNET_PACKED;
-
- /**
- * Public key of the joining member.
- */
- struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded public_key;
-
-};
-
-
-/**
- * Message send by one peer to another to indicate leaving of another room
- * member.
- */
-struct P2PLeaveNotificationMessage
-{
- /**
- * Message type will be GNUNET_MESSAGE_TYPE_CHAT_P2P_LEAVE_NOTIFICATION
- */
- struct GNUNET_MessageHeader header;
-
- /**
- * Reserved (for alignment).
- */
- uint32_t reserved GNUNET_PACKED;
-
- /**
- * Who is leaving?
- */
- struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded user;
-
-};
-
-
-/**
- * Message send by one peer to another to indicate receiving of a chat message.
- * This struct is followed by the room name (only if the message is anonymous)
- * and then the remaining bytes are the actual text message. If the mesasge is
- * private, then the text is encrypted, otherwise it's plaintext.
- */
-struct P2PReceiveNotificationMessage
-{
- /**
- * Message type will be GNUNET_MESSAGE_TYPE_CHAT_P2P_MESSAGE_NOTIFICATION
- */
- struct GNUNET_MessageHeader header;
-
- /**
- * Message options, see GNUNET_CHAT_MsgOptions.
- */
- uint32_t msg_options GNUNET_PACKED;
-
- /**
- * Sequence number of the message (unique per sender).
- */
- uint32_t sequence_number GNUNET_PACKED;
-
- /**
- * Length of the room name. This is only used for anonymous messages.
- */
- uint16_t room_name_len GNUNET_PACKED;
-
- /**
- * Reserved (for alignment).
- */
- uint16_t reserved GNUNET_PACKED;
-
- /**
- * Timestamp of the message.
- */
- struct GNUNET_TIME_AbsoluteNBO timestamp;
-
- /**
- * Hash of the public key of the pseudonym of the sender of the message
- * Should be all zeros for anonymous.
- */
- struct GNUNET_HashCode sender;
-
- /**
- * Who should receive this message? Set to all zeros for "everyone".
- */
- struct GNUNET_HashCode target;
-
- /**
- * The encrypted session key.
- */
- struct GNUNET_CRYPTO_RsaEncryptedData encrypted_key;
-
-};
-
-
-/**
- * Receipt sent from one peer to another to confirm delivery of a chat message.
- */
-struct P2PConfirmationReceiptMessage
-{
- /**
- * Message type will be GNUNET_MESSAGE_TYPE_CHAT_P2P_CONFIRMATION_RECEIPT
- */
- struct GNUNET_MessageHeader header;
-
- /**
- * For alignment (should be zero).
- */
- uint32_t reserved GNUNET_PACKED;
-
- /**
- * Signature confirming receipt. Signature covers everything from header
- * through content.
- */
- struct GNUNET_CRYPTO_RsaSignature signature;
-
- /**
- * What is being signed and why?
- */
- struct GNUNET_CRYPTO_RsaSignaturePurpose purpose;
-
- /**
- * Sequence number of the original message.
- */
- uint32_t msg_sequence_number GNUNET_PACKED;
-
- /**
- * Sequence number of the receipt.
- */
- uint32_t sequence_number GNUNET_PACKED;
-
- /**
- * Time of receipt.
- */
- struct GNUNET_TIME_AbsoluteNBO timestamp;
-
- /**
- * Who is confirming the receipt?
- */
- struct GNUNET_HashCode target;
-
- /**
- * Who is the author of the chat message?
- */
- struct GNUNET_HashCode author;
-
- /**
- * Hash of the (possibly encrypted) content.
- */
- struct GNUNET_HashCode content;
-
-};
-GNUNET_NETWORK_STRUCT_END
-
-#endif
-
-/* end of chat.h */
diff --git a/src/chat/gnunet-chat.c b/src/chat/gnunet-chat.c
@@ -1,750 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2007, 2008, 2011 Christian Grothoff (and other contributing authors)
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file chat/gnunet-chat.c
- * @brief Minimal chat command line tool
- * @author Christian Grothoff
- * @author Nathan Evans
- * @author Vitaly Minko
- */
-
-#include "platform.h"
-#include "gnunet_getopt_lib.h"
-#include "gnunet_program_lib.h"
-#include "gnunet_chat_service.h"
-#include "gnunet_fs_service.h"
-#include <fcntl.h>
-
-static int ret;
-
-static const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-static char *nickname;
-
-static char *room_name;
-
-static struct GNUNET_CONTAINER_MetaData *meta;
-
-static struct GNUNET_CHAT_Room *room;
-
-static GNUNET_SCHEDULER_TaskIdentifier handle_cmd_task;
-
-typedef int (*ActionFunction)(const char *argumetns, const void *xtra);
-
-struct ChatCommand
-{
- const char *command;
- ActionFunction Action;
- const char *helptext;
-};
-
-struct UserList
-{
- struct UserList *next;
- struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
- int ignored;
-};
-
-static struct UserList *users;
-
-static void
-free_user_list ()
-{
- struct UserList *next;
-
- while (NULL != users)
- {
- next = users->next;
- GNUNET_free (users);
- users = next;
- }
-}
-
-static int
-do_help (const char *args, const void *xtra);
-
-
-/**
- * Callback used for notification that we have joined the room.
- *
- * @param cls closure
- * @return GNUNET_OK
- */
-static int
-join_cb (void *cls)
-{
- FPRINTF (stdout, "%s", _("Joined\n"));
- return GNUNET_OK;
-}
-
-
-/**
- * Callback used for notification about incoming messages.
- *
- * @param cls closure, NULL
- * @param room in which room was the message received?
- * @param sender what is the ID of the sender? (maybe NULL)
- * @param member_info information about the joining member
- * @param message the message text
- * @param timestamp time when the member joined
- * @param options options for the message
- * @return GNUNET_OK to accept the message now, GNUNET_NO to
- * accept (but user is away), GNUNET_SYSERR to signal denied delivery
- */
-static int
-receive_cb (void *cls, struct GNUNET_CHAT_Room *room,
- const struct GNUNET_HashCode * sender,
- const struct GNUNET_CONTAINER_MetaData *member_info,
- const char *message, struct GNUNET_TIME_Absolute timestamp,
- enum GNUNET_CHAT_MsgOptions options)
-{
- char *non_unique_nick;
- char *nick;
- int nick_is_a_dup;
- const char *timestr;
- const char *fmt;
-
- if (NULL == sender)
- nick = GNUNET_strdup (_("anonymous"));
- else
- {
- if (GNUNET_OK != GNUNET_FS_pseudonym_get_info (cfg,
- sender, NULL, NULL, &non_unique_nick, &nick_is_a_dup)
- || (nick_is_a_dup == GNUNET_YES))
- {
- GNUNET_free (non_unique_nick);
- non_unique_nick = GNUNET_strdup (_("anonymous"));
- }
- nick = GNUNET_FS_pseudonym_name_uniquify (cfg, sender, non_unique_nick, NULL);
- GNUNET_free (non_unique_nick);
- }
-
- fmt = NULL;
- switch ((int) options)
- {
- case GNUNET_CHAT_MSG_OPTION_NONE:
- case GNUNET_CHAT_MSG_ANONYMOUS:
- fmt = _("(%s) `%s' said: %s\n");
- break;
- case GNUNET_CHAT_MSG_PRIVATE:
- fmt = _("(%s) `%s' said to you: %s\n");
- break;
- case GNUNET_CHAT_MSG_PRIVATE | GNUNET_CHAT_MSG_ANONYMOUS:
- fmt = _("(%s) `%s' said to you: %s\n");
- break;
- case GNUNET_CHAT_MSG_AUTHENTICATED:
- fmt = _("(%s) `%s' said for sure: %s\n");
- break;
- case GNUNET_CHAT_MSG_PRIVATE | GNUNET_CHAT_MSG_AUTHENTICATED:
- fmt = _("(%s) `%s' said to you for sure: %s\n");
- break;
- case GNUNET_CHAT_MSG_ACKNOWLEDGED:
- fmt = _("(%s) `%s' was confirmed that you received: %s\n");
- break;
- case GNUNET_CHAT_MSG_PRIVATE | GNUNET_CHAT_MSG_ACKNOWLEDGED:
- fmt = _("(%s) `%s' was confirmed that you and only you received: %s\n");
- break;
- case GNUNET_CHAT_MSG_AUTHENTICATED | GNUNET_CHAT_MSG_ACKNOWLEDGED:
- fmt = _("(%s) `%s' was confirmed that you received from him or her: %s\n");
- break;
- case GNUNET_CHAT_MSG_AUTHENTICATED | GNUNET_CHAT_MSG_PRIVATE | GNUNET_CHAT_MSG_ACKNOWLEDGED:
- fmt =
- _
- ("(%s) `%s' was confirmed that you and only you received from him or her: %s\n");
- break;
- case GNUNET_CHAT_MSG_OFF_THE_RECORD:
- fmt = _("(%s) `%s' said off the record: %s\n");
- break;
- default:
- fmt = _("(%s) <%s> said using an unknown message type: %s\n");
- break;
- }
- timestr = GNUNET_STRINGS_absolute_time_to_string (timestamp);
- FPRINTF (stdout, fmt, timestr, nick, message);
- GNUNET_free (nick);
- return GNUNET_OK;
-}
-
-
-/**
- * Callback used for message delivery confirmations.
- *
- * @param cls closure, NULL
- * @param room in which room was the message received?
- * @param orig_seq_number sequence number of the original message
- * @param timestamp when was the message received?
- * @param receiver who is confirming the receipt?
- * @return GNUNET_OK to continue, GNUNET_SYSERR to refuse processing further
- * confirmations from anyone for this message
- */
-static int
-confirmation_cb (void *cls, struct GNUNET_CHAT_Room *room,
- uint32_t orig_seq_number,
- struct GNUNET_TIME_Absolute timestamp,
- const struct GNUNET_HashCode * receiver)
-{
- char *nick;
- char *unique_nick;
- int nick_is_a_dup;
-
- if (GNUNET_OK != GNUNET_FS_pseudonym_get_info (cfg,
- receiver, NULL, NULL, &nick, &nick_is_a_dup)
- || (nick_is_a_dup == GNUNET_YES))
- {
- GNUNET_free (nick);
- nick = GNUNET_strdup (_("anonymous"));
- }
- unique_nick = GNUNET_FS_pseudonym_name_uniquify (cfg, receiver, nick, NULL);
- GNUNET_free (nick);
- FPRINTF (stdout, _("'%s' acknowledged message #%d\n"), unique_nick, orig_seq_number);
- GNUNET_free (unique_nick);
- return GNUNET_OK;
-}
-
-
-/**
- * Callback used for notification that another room member has joined or left.
- *
- * @param cls closure (not used)
- * @param member_info will be non-null if the member is joining, NULL if he is
- * leaving
- * @param member_id hash of public key of the user (for unique identification)
- * @param options what types of messages is this member willing to receive?
- * @return GNUNET_OK
- */
-static int
-member_list_cb (void *cls, const struct GNUNET_CONTAINER_MetaData *member_info,
- const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *member_id,
- enum GNUNET_CHAT_MsgOptions options)
-{
- char *nick;
- char *non_unique_nick;
- int nick_is_a_dup;
- struct GNUNET_HashCode id;
- struct UserList *pos;
- struct UserList *prev;
-
- GNUNET_CRYPTO_hash (member_id,
- sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
- &id);
- if (GNUNET_OK != GNUNET_FS_pseudonym_get_info (cfg,
- &id, NULL, NULL, &non_unique_nick, &nick_is_a_dup)
- || (nick_is_a_dup == GNUNET_YES))
- {
- GNUNET_free (non_unique_nick);
- non_unique_nick = GNUNET_strdup (_("anonymous"));
- }
- nick = GNUNET_FS_pseudonym_name_uniquify (cfg, &id, non_unique_nick, NULL);
- GNUNET_free (non_unique_nick);
-
- FPRINTF (stdout,
- member_info !=
- NULL ? _("`%s' entered the room\n") : _("`%s' left the room\n"),
- nick);
- GNUNET_free (nick);
- if (NULL != member_info)
- {
- /* user joining */
- pos = GNUNET_malloc (sizeof (struct UserList));
- pos->next = users;
- pos->pkey = *member_id;
- pos->ignored = GNUNET_NO;
- users = pos;
- }
- else
- {
- /* user leaving */
- prev = NULL;
- pos = users;
- while ((NULL != pos) &&
- (0 !=
- memcmp (&pos->pkey, member_id,
- sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded))))
- {
- prev = pos;
- pos = pos->next;
- }
- if (NULL == pos)
- {
- GNUNET_break (0);
- }
- else
- {
- if (NULL == prev)
- users = pos->next;
- else
- prev->next = pos->next;
- GNUNET_free (pos);
- }
- }
- return GNUNET_OK;
-}
-
-
-static int
-do_join (const char *arg, const void *xtra)
-{
- char *my_name;
- int my_name_is_a_dup;
- struct GNUNET_HashCode me;
-
- if (arg[0] == '#')
- arg++; /* ignore first hash */
- GNUNET_CHAT_leave_room (room);
- free_user_list ();
- GNUNET_free (room_name);
- room_name = GNUNET_strdup (arg);
- room =
- GNUNET_CHAT_join_room (cfg, nickname, meta, room_name, -1, &join_cb, NULL,
- &receive_cb, NULL, &member_list_cb, NULL,
- &confirmation_cb, NULL, &me);
- if (NULL == room)
- {
- FPRINTF (stdout, "%s", _("Could not change username\n"));
- return GNUNET_SYSERR;
- }
- if ((GNUNET_OK != GNUNET_FS_pseudonym_get_info (cfg,
- &me, NULL, NULL, &my_name, &my_name_is_a_dup)) ||
- (my_name_is_a_dup == GNUNET_YES))
- {
- GNUNET_free (my_name);
- my_name = GNUNET_strdup (_("anonymous"));
- }
- /* Don't uniquify our own name - other people will have a different
- * suffix for our own name anyway.
- */
- FPRINTF (stdout, _("Joining room `%s' as user `%s'...\n"), room_name,
- my_name);
- GNUNET_free (my_name);
- return GNUNET_OK;
-}
-
-
-static int
-do_nick (const char *msg, const void *xtra)
-{
- char *my_name;
- int my_name_is_a_dup;
- struct GNUNET_HashCode me;
-
- GNUNET_CHAT_leave_room (room);
- free_user_list ();
- GNUNET_free (nickname);
- GNUNET_CONTAINER_meta_data_destroy (meta);
- nickname = GNUNET_strdup (msg);
- meta = GNUNET_CONTAINER_meta_data_create ();
- GNUNET_CONTAINER_meta_data_insert (meta, "<gnunet>", EXTRACTOR_METATYPE_TITLE,
- EXTRACTOR_METAFORMAT_UTF8, "text/plain",
- nickname, strlen (nickname) + 1);
- room =
- GNUNET_CHAT_join_room (cfg, nickname, meta, room_name, -1, &join_cb, NULL,
- &receive_cb, NULL, &member_list_cb, NULL,
- &confirmation_cb, NULL, &me);
- if (NULL == room)
- {
- FPRINTF (stdout, "%s", _("Could not change username\n"));
- return GNUNET_SYSERR;
- }
- if ((GNUNET_OK != GNUNET_FS_pseudonym_get_info (cfg,
- &me, NULL, NULL, &my_name, &my_name_is_a_dup)) ||
- (my_name_is_a_dup == GNUNET_YES))
- {
- GNUNET_free (my_name);
- my_name = GNUNET_strdup (_("anonymous"));
- }
- FPRINTF (stdout, _("Changed username to `%s'\n"), my_name);
- GNUNET_free (my_name);
- return GNUNET_OK;
-}
-
-
-static int
-do_names (const char *msg, const void *xtra)
-{
- char *name;
- char *unique_name;
- int name_is_a_dup;
- struct UserList *pos;
- struct GNUNET_HashCode pid;
-
- FPRINTF (stdout, _("Users in room `%s': "), room_name);
- pos = users;
- while (NULL != pos)
- {
- GNUNET_CRYPTO_hash (&pos->pkey,
- sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
- &pid);
- if (GNUNET_OK != GNUNET_FS_pseudonym_get_info (cfg,
- &pid, NULL, NULL, &name, &name_is_a_dup)
- || (name_is_a_dup == GNUNET_YES))
- {
- GNUNET_free (name);
- name = GNUNET_strdup (_("anonymous"));
- }
- unique_name = GNUNET_FS_pseudonym_name_uniquify (cfg, &pid, name, NULL);
- GNUNET_free (name);
- FPRINTF (stdout, "`%s' ", unique_name);
- GNUNET_free (unique_name);
- pos = pos->next;
- }
- FPRINTF (stdout, "%s", "\n");
- return GNUNET_OK;
-}
-
-
-static int
-do_send (const char *msg, const void *xtra)
-{
- uint32_t seq;
-
- GNUNET_CHAT_send_message (room, msg, GNUNET_CHAT_MSG_OPTION_NONE, NULL, &seq);
- return GNUNET_OK;
-}
-
-
-static int
-do_send_pm (const char *msg, const void *xtra)
-{
- char *user;
- struct GNUNET_HashCode uid;
- struct GNUNET_HashCode pid;
- uint32_t seq;
- struct UserList *pos;
-
- if (NULL == strstr (msg, " "))
- {
- FPRINTF (stderr, "%s", _("Syntax: /msg USERNAME MESSAGE"));
- return GNUNET_OK;
- }
- user = GNUNET_strdup (msg);
- strstr (user, " ")[0] = '\0';
- msg += strlen (user) + 1;
- if (GNUNET_OK != GNUNET_FS_pseudonym_name_to_id (cfg, user, &uid))
- {
- FPRINTF (stderr,
- _("Unknown user `%s'. Make sure you specify its numeric suffix, if any.\n"),
- user);
- GNUNET_free (user);
- return GNUNET_OK;
- }
- pos = users;
- while (NULL != pos)
- {
- GNUNET_CRYPTO_hash (&pos->pkey,
- sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
- &pid);
- if (0 == memcmp (&pid, &uid, sizeof (struct GNUNET_HashCode)))
- break;
- pos = pos->next;
- }
- if (NULL == pos)
- {
- FPRINTF (stderr, _("User `%s' is currently not in the room!\n"), user);
- GNUNET_free (user);
- return GNUNET_OK;
- }
- GNUNET_CHAT_send_message (room, msg, GNUNET_CHAT_MSG_PRIVATE, &pos->pkey,
- &seq);
- GNUNET_free (user);
- return GNUNET_OK;
-}
-
-
-static int
-do_send_sig (const char *msg, const void *xtra)
-{
- uint32_t seq;
-
- GNUNET_CHAT_send_message (room, msg, GNUNET_CHAT_MSG_AUTHENTICATED, NULL,
- &seq);
- return GNUNET_OK;
-}
-
-
-static int
-do_send_ack (const char *msg, const void *xtra)
-{
- uint32_t seq;
-
- GNUNET_CHAT_send_message (room, msg, GNUNET_CHAT_MSG_ACKNOWLEDGED, NULL,
- &seq);
- return GNUNET_OK;
-}
-
-
-static int
-do_send_anonymous (const char *msg, const void *xtra)
-{
- uint32_t seq;
-
- GNUNET_CHAT_send_message (room, msg, GNUNET_CHAT_MSG_ANONYMOUS, NULL, &seq);
- return GNUNET_OK;
-}
-
-
-static int
-do_quit (const char *args, const void *xtra)
-{
- return GNUNET_SYSERR;
-}
-
-
-static int
-do_unknown (const char *msg, const void *xtra)
-{
- FPRINTF (stderr, _("Unknown command `%s'\n"), msg);
- return GNUNET_OK;
-}
-
-
-/**
- * List of supported IRC commands. The order matters!
- */
-static struct ChatCommand commands[] = {
- {"/join ", &do_join,
- gettext_noop
- ("Use `/join #roomname' to join a chat room. Joining a room will cause you"
- " to leave the current room")},
- {"/nick ", &do_nick,
- gettext_noop
- ("Use `/nick nickname' to change your nickname. This will cause you to"
- " leave the current room and immediately rejoin it with the new name.")},
- {"/msg ", &do_send_pm,
- gettext_noop
- ("Use `/msg nickname message' to send a private message to the specified"
- " user")},
- {"/notice ", &do_send_pm,
- gettext_noop ("The `/notice' command is an alias for `/msg'")},
- {"/query ", &do_send_pm,
- gettext_noop ("The `/query' command is an alias for `/msg'")},
- {"/sig ", &do_send_sig,
- gettext_noop ("Use `/sig message' to send a signed public message")},
- {"/ack ", &do_send_ack,
- gettext_noop
- ("Use `/ack message' to require signed acknowledgment of the message")},
- {"/anonymous ", &do_send_anonymous,
- gettext_noop
- ("Use `/anonymous message' to send a public anonymous message")},
- {"/anon ", &do_send_anonymous,
- gettext_noop ("The `/anon' command is an alias for `/anonymous'")},
- {"/quit", &do_quit,
- gettext_noop ("Use `/quit' to terminate gnunet-chat")},
- {"/leave", &do_quit,
- gettext_noop ("The `/leave' command is an alias for `/quit'")},
- {"/names", &do_names,
- gettext_noop
- ("Use `/names' to list all of the current members in the chat room")},
- {"/help", &do_help,
- gettext_noop ("Use `/help command' to get help for a specific command")},
- /* Add standard commands:
- * /whois (print metadata),
- * /ignore (set flag, check on receive!) */
- /* the following three commands must be last! */
- {"/", &do_unknown, NULL},
- {"", &do_send, NULL},
- {NULL, NULL, NULL},
-};
-
-
-static int
-do_help (const char *args, const void *xtra)
-{
- int i;
-
- i = 0;
- while ((NULL != args) && (0 != strlen (args)) &&
- (commands[i].Action != &do_help))
- {
- if (0 == strncasecmp (&args[1], &commands[i].command[1], strlen (args) - 1))
- {
- FPRINTF (stdout, "%s\n", gettext (commands[i].helptext));
- return GNUNET_OK;
- }
- i++;
- }
- i = 0;
- FPRINTF (stdout, "%s", "Available commands:");
- while (commands[i].Action != &do_help)
- {
- FPRINTF (stdout, " %s", gettext (commands[i].command));
- i++;
- }
- FPRINTF (stdout, "%s", "\n");
- FPRINTF (stdout, "%s\n", gettext (commands[i].helptext));
- return GNUNET_OK;
-}
-
-
-static void
-do_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- GNUNET_CHAT_leave_room (room);
- if (handle_cmd_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (handle_cmd_task);
- handle_cmd_task = GNUNET_SCHEDULER_NO_TASK;
- }
- free_user_list ();
- GNUNET_CONTAINER_meta_data_destroy (meta);
- GNUNET_free (room_name);
- GNUNET_free (nickname);
-}
-
-
-void
-handle_command (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- char message[MAX_MESSAGE_LENGTH + 1];
- int i;
-
- /* read message from command line and handle it */
- memset (message, 0, MAX_MESSAGE_LENGTH + 1);
- if (NULL == fgets (message, MAX_MESSAGE_LENGTH, stdin))
- goto next;
- if (strlen (message) == 0)
- goto next;
- if (message[strlen (message) - 1] == '\n')
- message[strlen (message) - 1] = '\0';
- if (strlen (message) == 0)
- goto next;
- i = 0;
- while ((NULL != commands[i].command) &&
- (0 !=
- strncasecmp (commands[i].command, message,
- strlen (commands[i].command))))
- i++;
- if (GNUNET_OK !=
- commands[i].Action (&message[strlen (commands[i].command)], NULL))
- goto out;
-
-next:
- handle_cmd_task =
- GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_MILLISECONDS, 100),
- GNUNET_SCHEDULER_PRIORITY_UI,
- &handle_command, NULL);
- return;
-
-out:
- handle_cmd_task = GNUNET_SCHEDULER_NO_TASK;
- GNUNET_SCHEDULER_shutdown ();
-}
-
-
-/**
- * Main function that will be run by the scheduler.
- *
- * @param cls closure, NULL
- * @param args remaining command-line arguments
- * @param cfgfile name of the configuration file used (for saving, can be NULL!)
- * @param c configuration
- */
-static void
-run (void *cls, char *const *args, const char *cfgfile,
- const struct GNUNET_CONFIGURATION_Handle *c)
-{
- struct GNUNET_HashCode me;
- char *my_name;
- int my_name_is_a_dup;
-
- cfg = c;
- /* check arguments */
- if (NULL == nickname)
- {
- FPRINTF (stderr, "%s", _("You must specify a nickname\n"));
- ret = -1;
- return;
- }
- if (NULL == room_name)
- room_name = GNUNET_strdup ("gnunet");
- meta = GNUNET_CONTAINER_meta_data_create ();
- GNUNET_CONTAINER_meta_data_insert (meta, "<gnunet>", EXTRACTOR_METATYPE_TITLE,
- EXTRACTOR_METAFORMAT_UTF8, "text/plain",
- nickname, strlen (nickname) + 1);
- room =
- GNUNET_CHAT_join_room (cfg, nickname, meta, room_name, -1, &join_cb, NULL,
- &receive_cb, NULL, &member_list_cb, NULL,
- &confirmation_cb, NULL, &me);
- if (NULL == room)
- {
- FPRINTF (stderr, _("Failed to join room `%s'\n"), room_name);
- GNUNET_free (room_name);
- GNUNET_free (nickname);
- GNUNET_CONTAINER_meta_data_destroy (meta);
- ret = -1;
- return;
- }
- if ((GNUNET_OK != GNUNET_FS_pseudonym_get_info (cfg,
- &me, NULL, NULL, &my_name, &my_name_is_a_dup)) ||
- (my_name_is_a_dup == GNUNET_YES))
- {
- GNUNET_free (my_name);
- my_name = GNUNET_strdup (_("anonymous"));
- }
- FPRINTF (stdout, _("Joining room `%s' as user `%s'...\n"), room_name,
- my_name);
- GNUNET_free (my_name);
- handle_cmd_task =
- GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_UI,
- &handle_command, NULL);
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_stop_task,
- NULL);
-}
-
-
-/**
- * The main function to chat via GNUnet.
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- */
-int
-main (int argc, char *const *argv)
-{
- int flags;
-
- static const struct GNUNET_GETOPT_CommandLineOption options[] = {
- {'n', "nick", "NAME",
- gettext_noop ("set the nickname to use (required)"),
- 1, &GNUNET_GETOPT_set_string, &nickname},
- {'r', "room", "NAME",
- gettext_noop ("set the chat room to join"),
- 1, &GNUNET_GETOPT_set_string, &room_name},
- GNUNET_GETOPT_OPTION_END
- };
-
-#ifndef WINDOWS
- flags = fcntl (0, F_GETFL, 0);
- flags |= O_NONBLOCK;
- fcntl (0, F_SETFL, flags);
-#endif
-
- if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
- return 2;
-
- return (GNUNET_OK ==
- GNUNET_PROGRAM_run (argc, argv, "gnunet-chat",
- gettext_noop ("Join a chat on GNUnet."), options,
- &run, NULL)) ? ret : 1;
-}
-
-/* end of gnunet-chat.c */
diff --git a/src/chat/gnunet-service-chat.c b/src/chat/gnunet-service-chat.c
@@ -1,1713 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2009, 2011 Christian Grothoff (and other contributing authors)
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file chat/gnunet-service-chat.c
- * @brief service providing chat functionality
- * @author Christian Grothoff
- * @author Vitaly Minko
- */
-
-#include "platform.h"
-#include "gnunet_core_service.h"
-#include "gnunet_crypto_lib.h"
-#include "gnunet_protocols.h"
-#include "gnunet_service_lib.h"
-#include "gnunet_signatures.h"
-#include "chat.h"
-
-#define DEBUG_CHAT_SERVICE GNUNET_EXTRA_LOGGING
-#define MAX_TRANSMIT_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
-#define EXPECTED_NEIGHBOUR_COUNT 16
-#define MAX_ANONYMOUS_MSG_LIST_LENGTH 16
-
-
-/**
- * Linked list of our current clients.
- */
-struct ChatClient
-{
- struct ChatClient *next;
-
- /**
- * Handle for a chat client (NULL for external clients).
- */
- struct GNUNET_SERVER_Client *client;
-
- /**
- * Public key of the client.
- */
- struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded public_key;
-
- /**
- * Name of the room which the client is in.
- */
- char *room;
-
- /**
- * Serialized metadata of the client.
- */
- char *member_info;
-
- /**
- * Hash of the public key (for convenience).
- */
- struct GNUNET_HashCode id;
-
- /**
- * Options which the client is willing to receive.
- */
- uint32_t msg_options;
-
- /**
- * Length of serialized metadata in member_info.
- */
- uint16_t meta_len;
-
- /**
- * Sequence number of the last message sent by the client.
- */
- uint32_t msg_sequence_number;
-
- /**
- * Sequence number of the last receipt sent by the client.
- * Used to discard already processed receipts.
- */
- uint32_t rcpt_sequence_number;
-
-};
-
-/**
- * Information about a peer that we are connected to.
- * We track data that is useful for determining which
- * peers should receive our requests.
- */
-struct ConnectedPeer
-{
- /**
- * The peer's identity.
- */
- GNUNET_PEER_Id pid;
-};
-
-/**
- * Linked list of recent anonymous messages.
- */
-struct AnonymousMessage
-{
- struct AnonymousMessage *next;
-
- /**
- * Hash of the message.
- */
- struct GNUNET_HashCode hash;
-
-};
-
-
-/**
- * Handle to the core service (NULL until we've connected to it).
- */
-static struct GNUNET_CORE_Handle *core;
-
-/**
- * Our configuration.
- */
-static const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * The identity of this host.
- */
-static struct GNUNET_PeerIdentity me;
-
-/**
- * Head of the list of current clients.
- */
-static struct ChatClient *client_list_head = NULL;
-
-/**
- * Notification context containing all connected clients.
- */
-struct GNUNET_SERVER_NotificationContext *nc = NULL;
-
-/**
- * Head of the list of recent anonymous messages.
- */
-static struct AnonymousMessage *anonymous_list_head = NULL;
-
-/**
- * Map of peer identifiers to "struct ConnectedPeer" (for that peer).
- */
-static struct GNUNET_CONTAINER_MultiHashMap *connected_peers;
-
-
-static void
-remember_anonymous_message (const struct P2PReceiveNotificationMessage
- *p2p_rnmsg)
-{
- static struct GNUNET_HashCode hash;
- struct AnonymousMessage *anon_msg;
- struct AnonymousMessage *prev;
- int anon_list_len;
-
- GNUNET_CRYPTO_hash (p2p_rnmsg, ntohs (p2p_rnmsg->header.size), &hash);
- anon_msg = GNUNET_malloc (sizeof (struct AnonymousMessage));
- anon_msg->hash = hash;
- anon_msg->next = anonymous_list_head;
- anonymous_list_head = anon_msg;
- anon_list_len = 1;
- prev = NULL;
- while ((NULL != anon_msg->next))
- {
- prev = anon_msg;
- anon_msg = anon_msg->next;
- anon_list_len++;
- }
- if (anon_list_len == MAX_ANONYMOUS_MSG_LIST_LENGTH)
- {
- GNUNET_free (anon_msg);
- if (NULL != prev)
- prev->next = NULL;
- }
-}
-
-
-static int
-lookup_anonymous_message (const struct P2PReceiveNotificationMessage *p2p_rnmsg)
-{
- static struct GNUNET_HashCode hash;
- struct AnonymousMessage *anon_msg;
-
- GNUNET_CRYPTO_hash (p2p_rnmsg, ntohs (p2p_rnmsg->header.size), &hash);
- anon_msg = anonymous_list_head;
- while ((NULL != anon_msg) &&
- (0 != memcmp (&anon_msg->hash, &hash, sizeof (struct GNUNET_HashCode))))
- anon_msg = anon_msg->next;
- return (NULL != anon_msg);
-}
-
-
-/**
- * Transmit a message notification to the peer.
- *
- * @param cls closure, pointer to the 'struct P2PReceiveNotificationMessage'
- * @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_message_notification_to_peer (void *cls, size_t size, void *buf)
-{
- struct P2PReceiveNotificationMessage *my_msg = cls;
- struct P2PReceiveNotificationMessage *m = buf;
- size_t msg_size;
-
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Transmitting P2P message notification\n");
-#endif
- if (buf == NULL)
- {
- /* client disconnected */
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Buffer is NULL, dropping the message\n");
-#endif
- return 0;
- }
- msg_size = ntohs (my_msg->header.size);
- GNUNET_assert (size >= msg_size);
- memcpy (m, my_msg, msg_size);
- GNUNET_free (my_msg);
- return msg_size;
-}
-
-
-/**
- * Ask to send a message notification to the peer.
- */
-static int
-send_message_noficiation (void *cls, const struct GNUNET_HashCode * key, void *value)
-{
- struct P2PReceiveNotificationMessage *msg = cls;
- struct ConnectedPeer *cp = value;
- struct GNUNET_PeerIdentity pid;
- struct P2PReceiveNotificationMessage *my_msg;
-
- GNUNET_PEER_resolve (cp->pid, &pid);
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message notification to `%s'\n",
- GNUNET_i2s (&pid));
-#endif
- my_msg = GNUNET_memdup (msg, ntohs (msg->header.size));
- if (NULL ==
- GNUNET_CORE_notify_transmit_ready (core, GNUNET_NO, 1, MAX_TRANSMIT_DELAY,
- &pid, ntohs (msg->header.size),
- &transmit_message_notification_to_peer,
- my_msg))
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Failed to queue a message notification\n"));
- return GNUNET_YES;
-}
-
-
-/**
- * A client sent a chat message. Encrypt the message text if the message is
- * private. Send the message to local room members and to all connected peers.
- *
- * @param cls closure, NULL
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_transmit_request (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
-{
- static struct GNUNET_HashCode all_zeros;
- const struct TransmitRequestMessage *trmsg;
- struct ReceiveNotificationMessage *rnmsg;
- struct P2PReceiveNotificationMessage *p2p_rnmsg;
- struct ChatClient *pos;
- struct ChatClient *target;
- struct GNUNET_CRYPTO_AesSessionKey key;
- char encrypted_msg[MAX_MESSAGE_LENGTH];
- const char *room;
- size_t room_len;
- int msg_len;
- int is_priv;
- int is_anon;
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client sent a chat message\n");
- if (ntohs (message->size) <= sizeof (struct TransmitRequestMessage))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed message: wrong size\n");
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
- trmsg = (const struct TransmitRequestMessage *) message;
- msg_len = ntohs (trmsg->header.size) - sizeof (struct TransmitRequestMessage);
- is_priv = (0 != (ntohl (trmsg->msg_options) & GNUNET_CHAT_MSG_PRIVATE));
- if (is_priv)
- {
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting the message text\n");
-#endif
- GNUNET_CRYPTO_aes_create_session_key (&key);
- msg_len =
- GNUNET_CRYPTO_aes_encrypt (&trmsg[1], msg_len, &key,
- (const struct
- GNUNET_CRYPTO_AesInitializationVector *)
- INITVALUE, encrypted_msg);
- if (-1 == msg_len)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Could not encrypt the message text\n");
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
- }
- rnmsg = GNUNET_malloc (sizeof (struct ReceiveNotificationMessage) + msg_len);
- rnmsg->header.size =
- htons (sizeof (struct ReceiveNotificationMessage) + msg_len);
- rnmsg->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_MESSAGE_NOTIFICATION);
- rnmsg->msg_options = trmsg->msg_options;
- rnmsg->timestamp = trmsg->timestamp;
- pos = client_list_head;
- while ((NULL != pos) && (pos->client != client))
- pos = pos->next;
- if (NULL == pos)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "The client is not a member of a chat room. Client has to "
- "join a chat room first\n");
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- GNUNET_free (rnmsg);
- return;
- }
- room = pos->room;
- pos->msg_sequence_number = ntohl (trmsg->sequence_number);
- is_anon = (0 != (ntohl (trmsg->msg_options) & GNUNET_CHAT_MSG_ANONYMOUS));
- if (is_anon)
- {
- memset (&rnmsg->sender, 0, sizeof (struct GNUNET_HashCode));
- rnmsg->sequence_number = 0;
- }
- else
- {
- rnmsg->sender = pos->id;
- rnmsg->sequence_number = trmsg->sequence_number;
- }
- if (is_priv)
- {
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Encrypting the session key using the public key of '%s'\n",
- GNUNET_h2s (&trmsg->target));
-#endif
- if (0 == memcmp (&all_zeros, &trmsg->target, sizeof (struct GNUNET_HashCode)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Malformed message: private, but no target\n");
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- GNUNET_free (rnmsg);
- return;
- }
- memcpy (&rnmsg[1], encrypted_msg, msg_len);
- target = client_list_head;
- while ((NULL != target) &&
- (0 !=
- memcmp (&target->id, &trmsg->target, sizeof (struct GNUNET_HashCode))))
- target = target->next;
- if (NULL == target)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unknown target of the private message\n");
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- GNUNET_free (rnmsg);
- return;
- }
- if (GNUNET_SYSERR ==
- GNUNET_CRYPTO_rsa_encrypt (&key,
- sizeof (struct GNUNET_CRYPTO_AesSessionKey),
- &target->public_key, &rnmsg->encrypted_key))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Could not encrypt the session key\n");
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- GNUNET_free (rnmsg);
- return;
- }
- }
- else
- {
- memcpy (&rnmsg[1], &trmsg[1], msg_len);
- }
- pos = client_list_head;
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending message to local room members\n");
-#endif
- while (NULL != pos)
- {
- if ((0 == strcmp (room, pos->room)) && (NULL != pos->client) &&
- (pos->client != client))
- {
- if (((!is_priv) ||
- (0 == memcmp (&trmsg->target, &pos->id, sizeof (struct GNUNET_HashCode))))
- && (0 == (ntohl (trmsg->msg_options) & (~pos->msg_options))))
- {
- GNUNET_SERVER_notification_context_unicast (nc, pos->client,
- &rnmsg->header, GNUNET_NO);
- }
- }
- pos = pos->next;
- }
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Broadcasting message to neighbour peers\n");
-#endif
- if (is_anon)
- {
- room_len = strlen (room);
- p2p_rnmsg =
- GNUNET_malloc (sizeof (struct P2PReceiveNotificationMessage) + msg_len +
- room_len);
- p2p_rnmsg->header.size =
- htons (sizeof (struct P2PReceiveNotificationMessage) + msg_len +
- room_len);
- p2p_rnmsg->room_name_len = htons (room_len);
- memcpy ((char *) &p2p_rnmsg[1], room, room_len);
- memcpy ((char *) &p2p_rnmsg[1] + room_len, &trmsg[1], msg_len);
- }
- else
- {
- p2p_rnmsg =
- GNUNET_malloc (sizeof (struct P2PReceiveNotificationMessage) + msg_len);
- p2p_rnmsg->header.size =
- htons (sizeof (struct P2PReceiveNotificationMessage) + msg_len);
- if (is_priv)
- {
- memcpy (&p2p_rnmsg[1], encrypted_msg, msg_len);
- memcpy (&p2p_rnmsg->encrypted_key, &rnmsg->encrypted_key,
- sizeof (struct GNUNET_CRYPTO_RsaEncryptedData));
- }
- else
- memcpy (&p2p_rnmsg[1], &trmsg[1], msg_len);
- }
- p2p_rnmsg->header.type =
- htons (GNUNET_MESSAGE_TYPE_CHAT_P2P_MESSAGE_NOTIFICATION);
- p2p_rnmsg->msg_options = trmsg->msg_options;
- p2p_rnmsg->sequence_number = trmsg->sequence_number;
- p2p_rnmsg->timestamp = trmsg->timestamp;
- p2p_rnmsg->reserved = htons (0);
- p2p_rnmsg->sender = rnmsg->sender;
- p2p_rnmsg->target = trmsg->target;
- if (is_anon)
- remember_anonymous_message (p2p_rnmsg);
- GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
- &send_message_noficiation, p2p_rnmsg);
- GNUNET_free (p2p_rnmsg);
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
- GNUNET_free (rnmsg);
-}
-
-
-/**
- * Transmit a join notification to the peer.
- *
- * @param cls closure, pointer to the 'struct ChatClient'
- * @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_join_notification_to_peer (void *cls, size_t size, void *buf)
-{
- struct ChatClient *entry = cls;
- struct P2PJoinNotificationMessage *m = buf;
- size_t room_len;
- size_t meta_len;
- size_t msg_size;
- char *roomptr;
-
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting P2P join notification\n");
-#endif
- room_len = strlen (entry->room);
- meta_len = entry->meta_len;
- msg_size = sizeof (struct P2PJoinNotificationMessage) + meta_len + room_len;
- GNUNET_assert (size >= msg_size);
- GNUNET_assert (NULL != buf);
- m = buf;
- m->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_P2P_JOIN_NOTIFICATION);
- m->header.size = htons (msg_size);
- m->msg_options = htonl (entry->msg_options);
- m->room_name_len = htons (room_len);
- m->reserved = htons (0);
- m->reserved2 = htonl (0);
- m->public_key = entry->public_key;
- roomptr = (char *) &m[1];
- memcpy (roomptr, entry->room, room_len);
- if (meta_len > 0)
- memcpy (&roomptr[room_len], entry->member_info, meta_len);
- return msg_size;
-}
-
-
-/**
- * Ask to send a join notification to the peer.
- */
-static int
-send_join_noficiation (void *cls, const struct GNUNET_HashCode * key, void *value)
-{
- struct ChatClient *entry = cls;
- struct ConnectedPeer *cp = value;
- struct GNUNET_PeerIdentity pid;
- size_t msg_size;
-
- GNUNET_PEER_resolve (cp->pid, &pid);
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending join notification to `%s'\n",
- GNUNET_i2s (&pid));
-#endif
- msg_size =
- sizeof (struct P2PJoinNotificationMessage) + strlen (entry->room) +
- entry->meta_len;
- if (NULL ==
- GNUNET_CORE_notify_transmit_ready (core, GNUNET_NO, 1, MAX_TRANSMIT_DELAY,
- &pid, msg_size,
- &transmit_join_notification_to_peer,
- entry))
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Failed to queue a join notification\n"));
- return GNUNET_YES;
-}
-
-
-/**
- * A client asked for entering a chat room. Add the new member to the list of
- * clients and notify remaining room members.
- *
- * @param cls closure, NULL
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_join_request (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
-{
- const struct JoinRequestMessage *jrmsg;
- char *room_name;
- const char *roomptr;
- uint16_t header_size;
- uint16_t meta_len;
- uint16_t room_name_len;
- struct ChatClient *new_entry;
- struct ChatClient *entry;
- struct JoinNotificationMessage *jnmsg;
- struct JoinNotificationMessage *entry_jnmsg;
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client sent a join request\n");
- if (ntohs (message->size) <= sizeof (struct JoinRequestMessage))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed message: wrong size\n");
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
- jrmsg = (const struct JoinRequestMessage *) message;
- header_size = ntohs (jrmsg->header.size);
- room_name_len = ntohs (jrmsg->room_name_len);
- if (header_size - sizeof (struct JoinRequestMessage) <= room_name_len)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Malformed message: wrong length of the room name\n");
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
- meta_len = header_size - sizeof (struct JoinRequestMessage) - room_name_len;
- roomptr = (const char *) &jrmsg[1];
- room_name = GNUNET_malloc (room_name_len + 1);
- memcpy (room_name, roomptr, room_name_len);
- room_name[room_name_len] = '\0';
- new_entry = GNUNET_malloc (sizeof (struct ChatClient));
- memset (new_entry, 0, sizeof (struct ChatClient));
- new_entry->client = client;
- new_entry->room = room_name;
- new_entry->public_key = jrmsg->public_key;
- new_entry->meta_len = meta_len;
- if (meta_len > 0)
- {
- new_entry->member_info = GNUNET_malloc (meta_len);
- memcpy (new_entry->member_info, &roomptr[room_name_len], meta_len);
- }
- else
- new_entry->member_info = NULL;
- GNUNET_CRYPTO_hash (&new_entry->public_key,
- sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
- &new_entry->id);
- new_entry->msg_options = ntohl (jrmsg->msg_options);
- new_entry->next = client_list_head;
- client_list_head = new_entry;
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Synchronizing room members between local clients\n");
-#endif
- jnmsg = GNUNET_malloc (sizeof (struct JoinNotificationMessage) + meta_len);
- jnmsg->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_JOIN_NOTIFICATION);
- jnmsg->header.size =
- htons (sizeof (struct JoinNotificationMessage) + meta_len);
- jnmsg->msg_options = jrmsg->msg_options;
- jnmsg->public_key = new_entry->public_key;
- memcpy (&jnmsg[1], &roomptr[room_name_len], meta_len);
- GNUNET_SERVER_notification_context_add (nc, client);
- entry = client_list_head;
- while (NULL != entry)
- {
- if (0 == strcmp (room_name, entry->room))
- {
- if (NULL != entry->client)
- GNUNET_SERVER_notification_context_unicast (nc, entry->client,
- &jnmsg->header, GNUNET_NO);
- if (entry->client != client)
- {
- entry_jnmsg =
- GNUNET_malloc (sizeof (struct JoinNotificationMessage) +
- entry->meta_len);
- entry_jnmsg->header.type =
- htons (GNUNET_MESSAGE_TYPE_CHAT_JOIN_NOTIFICATION);
- entry_jnmsg->header.size =
- htons (sizeof (struct JoinNotificationMessage) + entry->meta_len);
- entry_jnmsg->msg_options = entry->msg_options;
- entry_jnmsg->public_key = entry->public_key;
- memcpy (&entry_jnmsg[1], entry->member_info, entry->meta_len);
- GNUNET_SERVER_notification_context_unicast (nc, client,
- &entry_jnmsg->header,
- GNUNET_NO);
- GNUNET_free (entry_jnmsg);
- }
- }
- entry = entry->next;
- }
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Broadcasting join notification to neighbour peers\n");
-#endif
- GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
- &send_join_noficiation, new_entry);
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
- GNUNET_free (jnmsg);
-}
-
-/**
- * Transmit a confirmation receipt to the peer.
- *
- * @param cls closure, pointer to the 'struct P2PConfirmationReceiptMessage'
- * @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_confirmation_receipt_to_peer (void *cls, size_t size, void *buf)
-{
- struct P2PConfirmationReceiptMessage *receipt = cls;
- size_t msg_size;
-
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Transmitting P2P confirmation receipt to '%s'\n",
- GNUNET_h2s (&receipt->target));
-#endif
- if (buf == NULL)
- {
- /* client disconnected */
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Buffer is NULL, dropping the message\n");
-#endif
- return 0;
- }
- msg_size = sizeof (struct P2PConfirmationReceiptMessage);
- GNUNET_assert (size >= msg_size);
- memcpy (buf, receipt, msg_size);
- GNUNET_free (receipt);
- return msg_size;
-}
-
-
-/**
- * Ask to send a confirmation receipt to the peer.
- */
-static int
-send_confirmation_receipt (void *cls, const struct GNUNET_HashCode * key, void *value)
-{
- struct P2PConfirmationReceiptMessage *receipt = cls;
- struct ConnectedPeer *cp = value;
- struct GNUNET_PeerIdentity pid;
- struct P2PConfirmationReceiptMessage *my_receipt;
- size_t msg_size;
-
- GNUNET_PEER_resolve (cp->pid, &pid);
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending confirmation receipt to `%s'\n",
- GNUNET_i2s (&pid));
-#endif
- msg_size = sizeof (struct P2PConfirmationReceiptMessage);
- my_receipt =
- GNUNET_memdup (receipt, sizeof (struct P2PConfirmationReceiptMessage));
- if (NULL ==
- GNUNET_CORE_notify_transmit_ready (core, GNUNET_YES, 1,
- MAX_TRANSMIT_DELAY, &pid, msg_size,
- &transmit_confirmation_receipt_to_peer,
- my_receipt))
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Failed to queue a confirmation receipt\n"));
- return GNUNET_YES;
-}
-
-
-/**
- * A client sent a confirmation receipt. Broadcast the receipt to all connected
- * peers if the author of the original message is a local client. Otherwise
- * check the signature and notify the user if the signature is valid.
- *
- * @param cls closure, NULL
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_acknowledge_request (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
-{
- const struct ConfirmationReceiptMessage *receipt;
- struct ConfirmationReceiptMessage *crmsg;
- struct P2PConfirmationReceiptMessage *p2p_crmsg;
- struct ChatClient *target;
- struct ChatClient *author;
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client sent a confirmation receipt\n");
- receipt = (const struct ConfirmationReceiptMessage *) message;
- author = client_list_head;
- while ((NULL != author) &&
- (0 !=
- memcmp (&receipt->author, &author->id, sizeof (struct GNUNET_HashCode))))
- author = author->next;
- if (NULL == author)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unknown author of the original message\n");
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
- target = client_list_head;
- while ((NULL != target) &&
- (0 !=
- memcmp (&receipt->target, &target->id, sizeof (struct GNUNET_HashCode))))
- target = target->next;
- if (NULL == target)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unknown target of the confirmation receipt\n");
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
- if (NULL == author->client)
- {
- target->rcpt_sequence_number++;
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Broadcasting %s's receipt #%u to neighbour peers\n",
- GNUNET_h2s (&target->id), target->rcpt_sequence_number);
-#endif
- p2p_crmsg = GNUNET_malloc (sizeof (struct P2PConfirmationReceiptMessage));
- p2p_crmsg->header.size =
- htons (sizeof (struct P2PConfirmationReceiptMessage));
- p2p_crmsg->header.type =
- htons (GNUNET_MESSAGE_TYPE_CHAT_P2P_CONFIRMATION_RECEIPT);
- p2p_crmsg->reserved = htonl (0);
- p2p_crmsg->signature = receipt->signature;
- p2p_crmsg->purpose = receipt->purpose;
- p2p_crmsg->msg_sequence_number = receipt->sequence_number;
- p2p_crmsg->timestamp = receipt->timestamp;
- p2p_crmsg->target = receipt->target;
- p2p_crmsg->author = receipt->author;
- p2p_crmsg->content = receipt->content;
- p2p_crmsg->sequence_number = htonl (target->rcpt_sequence_number);
- GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
- &send_confirmation_receipt,
- p2p_crmsg);
- GNUNET_free (p2p_crmsg);
- }
- else
- {
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Verifying signature of the receipt\n");
-#endif
- if (GNUNET_OK !=
- GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_CHAT_RECEIPT,
- &receipt->purpose, &receipt->signature,
- &target->public_key))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Invalid signature of the receipt\n");
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending receipt to the client which sent the original message\n");
-#endif
- crmsg = GNUNET_memdup (receipt, sizeof (struct ConfirmationReceiptMessage));
- crmsg->header.type =
- htons (GNUNET_MESSAGE_TYPE_CHAT_CONFIRMATION_NOTIFICATION);
- GNUNET_SERVER_notification_context_unicast (nc, author->client,
- &crmsg->header, GNUNET_NO);
- GNUNET_free (crmsg);
- }
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Transmit a leave notification to the peer.
- *
- * @param cls closure, pointer to the
- * 'struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded'
- * @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_leave_notification_to_peer (void *cls, size_t size, void *buf)
-{
- struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key = cls;
- struct P2PLeaveNotificationMessage *m = buf;
- size_t msg_size;
-
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting P2P leave notification\n");
-#endif
- if (buf == NULL)
- {
- /* client disconnected */
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Buffer is NULL, dropping the message\n");
-#endif
- return 0;
- }
- msg_size = sizeof (struct P2PLeaveNotificationMessage);
- GNUNET_assert (size >= msg_size);
- m = buf;
- m->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_P2P_LEAVE_NOTIFICATION);
- m->header.size = htons (msg_size);
- m->reserved = htonl (0);
- m->user = *public_key;
- GNUNET_free (public_key);
- return msg_size;
-}
-
-
-/**
- * Ask to send a leave notification to the peer.
- */
-static int
-send_leave_noficiation (void *cls, const struct GNUNET_HashCode * key, void *value)
-{
- struct ChatClient *entry = cls;
- struct ConnectedPeer *cp = value;
- struct GNUNET_PeerIdentity pid;
- struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key;
- size_t msg_size;
-
- GNUNET_PEER_resolve (cp->pid, &pid);
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending leave notification to `%s'\n",
- GNUNET_i2s (&pid));
-#endif
- msg_size = sizeof (struct P2PLeaveNotificationMessage);
- public_key =
- GNUNET_memdup (&entry->public_key,
- sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
- if (NULL ==
- GNUNET_CORE_notify_transmit_ready (core, GNUNET_YES, 1,
- MAX_TRANSMIT_DELAY, &pid, msg_size,
- &transmit_leave_notification_to_peer,
- public_key))
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Failed to queue a leave notification\n"));
- return GNUNET_YES;
-}
-
-
-/**
- * A client disconnected. Remove all of its data structure entries and notify
- * remaining room members.
- *
- * @param cls closure, NULL
- * @param client identification of the client
- */
-static void
-handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
-{
- struct ChatClient *entry;
- struct ChatClient *pos;
- struct ChatClient *prev;
- struct LeaveNotificationMessage lnmsg;
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client disconnected\n");
- pos = client_list_head;
- prev = NULL;
- while ((NULL != pos) && (pos->client != client))
- {
- prev = pos;
- pos = pos->next;
- }
- if (NULL == pos)
- {
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "No such client. There is nothing to do\n");
-#endif
- return;
- }
- if (NULL == prev)
- client_list_head = pos->next;
- else
- prev->next = pos->next;
- entry = client_list_head;
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Notifying local room members that the client has disconnected\n");
-#endif
- lnmsg.header.size = htons (sizeof (struct LeaveNotificationMessage));
- lnmsg.header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_LEAVE_NOTIFICATION);
- lnmsg.reserved = htonl (0);
- lnmsg.user = pos->public_key;
- while (NULL != entry)
- {
- if ((0 == strcmp (pos->room, entry->room)) && (NULL != entry->client))
- {
- GNUNET_SERVER_notification_context_unicast (nc, entry->client,
- &lnmsg.header, GNUNET_NO);
- }
- entry = entry->next;
- }
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Broadcasting leave notification to neighbour peers\n");
-#endif
- GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
- &send_leave_noficiation, pos);
- GNUNET_free (pos->room);
- GNUNET_free_non_null (pos->member_info);
- GNUNET_free (pos);
-}
-
-
-/**
- * Handle P2P join notification.
- *
- * @param cls closure, always NULL
- * @param other the other peer involved
- * @param message the actual message
-
- * @return GNUNET_OK to keep the connection open,
- * GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_p2p_join_notification (void *cls,
- const struct GNUNET_PeerIdentity *other,
- const struct GNUNET_MessageHeader *message)
-{
- const struct P2PJoinNotificationMessage *p2p_jnmsg;
- char *room_name;
- const char *roomptr;
- uint16_t header_size;
- uint16_t meta_len;
- uint16_t room_name_len;
- struct ChatClient *new_entry;
- struct ChatClient *entry;
- struct JoinNotificationMessage *jnmsg;
- struct GNUNET_HashCode id;
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got P2P join notification\n");
- if (ntohs (message->size) <= sizeof (struct P2PJoinNotificationMessage))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed message: wrong size\n");
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- p2p_jnmsg = (const struct P2PJoinNotificationMessage *) message;
- header_size = ntohs (p2p_jnmsg->header.size);
- room_name_len = ntohs (p2p_jnmsg->room_name_len);
- if (header_size - sizeof (struct P2PJoinNotificationMessage) <= room_name_len)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Malformed message: wrong length of the room name\n");
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- GNUNET_CRYPTO_hash (&p2p_jnmsg->public_key,
- sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
- &id);
- entry = client_list_head;
- while (NULL != entry)
- {
- if (0 == memcmp (&entry->id, &id, sizeof (struct GNUNET_HashCode)))
- {
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "The client has already joined. There is nothing to do\n");
-#endif
- return GNUNET_OK;
- }
- entry = entry->next;
- }
- meta_len =
- header_size - sizeof (struct P2PJoinNotificationMessage) - room_name_len;
- roomptr = (const char *) &p2p_jnmsg[1];
- room_name = GNUNET_malloc (room_name_len + 1);
- memcpy (room_name, roomptr, room_name_len);
- room_name[room_name_len] = '\0';
- new_entry = GNUNET_malloc (sizeof (struct ChatClient));
- memset (new_entry, 0, sizeof (struct ChatClient));
- new_entry->id = id;
- new_entry->client = NULL;
- new_entry->room = room_name;
- new_entry->public_key = p2p_jnmsg->public_key;
- new_entry->meta_len = meta_len;
- if (meta_len > 0)
- {
- new_entry->member_info = GNUNET_malloc (meta_len);
- memcpy (new_entry->member_info, &roomptr[room_name_len], meta_len);
- }
- else
- new_entry->member_info = NULL;
- new_entry->msg_options = ntohl (p2p_jnmsg->msg_options);
- new_entry->next = client_list_head;
- client_list_head = new_entry;
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Notifying local room members that we have a new client\n");
-#endif
- jnmsg = GNUNET_malloc (sizeof (struct JoinNotificationMessage) + meta_len);
- jnmsg->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_JOIN_NOTIFICATION);
- jnmsg->header.size =
- htons (sizeof (struct JoinNotificationMessage) + meta_len);
- jnmsg->msg_options = p2p_jnmsg->msg_options;
- jnmsg->public_key = new_entry->public_key;
- memcpy (&jnmsg[1], &roomptr[room_name_len], meta_len);
- entry = client_list_head;
- while (NULL != entry)
- {
- if ((0 == strcmp (room_name, entry->room)) && (NULL != entry->client))
- {
- GNUNET_SERVER_notification_context_unicast (nc, entry->client,
- &jnmsg->header, GNUNET_NO);
- }
- entry = entry->next;
- }
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Broadcasting join notification to neighbour peers\n");
-#endif
- GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
- &send_join_noficiation, new_entry);
- GNUNET_free (jnmsg);
- return GNUNET_OK;
-}
-
-
-/**
- * Handle P2P leave notification.
- *
- * @param cls closure, always NULL
- * @param other the other peer involved
- * @param message the actual message
- * @return GNUNET_OK to keep the connection open,
- * GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_p2p_leave_notification (void *cls,
- const struct GNUNET_PeerIdentity *other,
- const struct GNUNET_MessageHeader *message)
-{
- const struct P2PLeaveNotificationMessage *p2p_lnmsg;
- struct GNUNET_HashCode id;
- struct ChatClient *pos;
- struct ChatClient *prev;
- struct ChatClient *entry;
- struct LeaveNotificationMessage lnmsg;
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got P2P leave notification\n");
- p2p_lnmsg = (const struct P2PLeaveNotificationMessage *) message;
- GNUNET_CRYPTO_hash (&p2p_lnmsg->user,
- sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
- &id);
- pos = client_list_head;
- prev = NULL;
- while (NULL != pos)
- {
- if (0 == memcmp (&pos->id, &id, sizeof (struct GNUNET_HashCode)))
- break;
- prev = pos;
- pos = pos->next;
- }
- if (NULL == pos)
- {
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "No such client. There is nothing to do\n");
-#endif
- return GNUNET_OK;
- }
- if (NULL == prev)
- client_list_head = pos->next;
- else
- prev->next = pos->next;
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Notifying local room members that the client has gone away\n");
-#endif
- lnmsg.header.size = htons (sizeof (struct LeaveNotificationMessage));
- lnmsg.header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_LEAVE_NOTIFICATION);
- lnmsg.reserved = htonl (0);
- lnmsg.user = pos->public_key;
- entry = client_list_head;
- while (NULL != entry)
- {
- if (0 == strcmp (pos->room, entry->room) && (NULL != entry->client))
- {
- GNUNET_SERVER_notification_context_unicast (nc, entry->client,
- &lnmsg.header, GNUNET_NO);
- }
- entry = entry->next;
- }
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Broadcasting leave notification to neighbour peers\n");
-#endif
- GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
- &send_leave_noficiation, pos);
- GNUNET_free (pos->room);
- GNUNET_free_non_null (pos->member_info);
- GNUNET_free (pos);
- return GNUNET_OK;
-}
-
-
-/**
- * Handle P2P message notification.
- *
- * @param cls closure, always NULL
- * @param other the other peer involved
- * @param message the actual message
- * @return GNUNET_OK to keep the connection open,
- * GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_p2p_message_notification (void *cls,
- const struct GNUNET_PeerIdentity *other,
- const struct GNUNET_MessageHeader *message)
-{
- const struct P2PReceiveNotificationMessage *p2p_rnmsg;
- struct P2PReceiveNotificationMessage *my_p2p_rnmsg;
- struct ReceiveNotificationMessage *rnmsg;
- struct ChatClient *sender;
- struct ChatClient *pos;
- static struct GNUNET_HashCode all_zeros;
- int is_priv;
- int is_anon;
- uint16_t msg_len;
- uint16_t room_name_len;
- char *room_name = NULL;
- char *text;
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got P2P message notification\n");
- if (ntohs (message->size) <= sizeof (struct P2PReceiveNotificationMessage))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed message: wrong size\n");
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- p2p_rnmsg = (const struct P2PReceiveNotificationMessage *) message;
- msg_len =
- ntohs (p2p_rnmsg->header.size) -
- sizeof (struct P2PReceiveNotificationMessage);
-
- is_anon = (0 != (ntohl (p2p_rnmsg->msg_options) & GNUNET_CHAT_MSG_ANONYMOUS));
- if (is_anon)
- {
- room_name_len = ntohs (p2p_rnmsg->room_name_len);
- if (msg_len <= room_name_len)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Malformed message: wrong length of the room name\n");
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- msg_len -= room_name_len;
- if (lookup_anonymous_message (p2p_rnmsg))
- {
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "This anonymous message has already been handled.");
-#endif
- return GNUNET_OK;
- }
- remember_anonymous_message (p2p_rnmsg);
- room_name = GNUNET_malloc (room_name_len + 1);
- memcpy (room_name, (char *) &p2p_rnmsg[1], room_name_len);
- room_name[room_name_len] = '\0';
- text = (char *) &p2p_rnmsg[1] + room_name_len;
- }
- else
- {
- sender = client_list_head;
- while ((NULL != sender) &&
- (0 !=
- memcmp (&sender->id, &p2p_rnmsg->sender, sizeof (struct GNUNET_HashCode))))
- sender = sender->next;
- if (NULL == sender)
- {
- /* not an error since the sender may have left before we got the
- * message */
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Unknown source. Rejecting the message\n");
-#endif
- return GNUNET_OK;
- }
- if (sender->msg_sequence_number >= ntohl (p2p_rnmsg->sequence_number))
- {
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "This message has already been handled."
- " Sequence numbers (msg/sender): %u/%u\n",
- ntohl (p2p_rnmsg->sequence_number),
- sender->msg_sequence_number);
-#endif
- return GNUNET_OK;
- }
- sender->msg_sequence_number = ntohl (p2p_rnmsg->sequence_number);
- room_name = sender->room;
- text = (char *) &p2p_rnmsg[1];
- }
-
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending message to local room members\n");
-#endif
- rnmsg = GNUNET_malloc (sizeof (struct ReceiveNotificationMessage) + msg_len);
- rnmsg->header.size =
- htons (sizeof (struct ReceiveNotificationMessage) + msg_len);
- rnmsg->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_MESSAGE_NOTIFICATION);
- rnmsg->msg_options = p2p_rnmsg->msg_options;
- rnmsg->sequence_number = p2p_rnmsg->sequence_number;
- rnmsg->reserved = htonl (0);
- rnmsg->timestamp = p2p_rnmsg->timestamp;
- is_priv =
- (0 != memcmp (&all_zeros, &p2p_rnmsg->target, sizeof (struct GNUNET_HashCode)));
- if (is_priv)
- memcpy (&rnmsg->encrypted_key, &p2p_rnmsg->encrypted_key,
- sizeof (struct GNUNET_CRYPTO_RsaEncryptedData));
- rnmsg->sender = p2p_rnmsg->sender;
- memcpy (&rnmsg[1], text, msg_len);
- pos = client_list_head;
- while (NULL != pos)
- {
- if ((0 == strcmp (room_name, pos->room)) && (NULL != pos->client))
- {
- if (((!is_priv) ||
- (0 ==
- memcmp (&p2p_rnmsg->target, &pos->id, sizeof (struct GNUNET_HashCode)))) &&
- (0 == (ntohl (p2p_rnmsg->msg_options) & (~pos->msg_options))))
- {
- GNUNET_SERVER_notification_context_unicast (nc, pos->client,
- &rnmsg->header, GNUNET_NO);
- }
- }
- pos = pos->next;
- }
- if (is_anon)
- GNUNET_free (room_name);
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Broadcasting message notification to neighbour peers\n");
-#endif
- my_p2p_rnmsg = GNUNET_memdup (p2p_rnmsg, ntohs (p2p_rnmsg->header.size));
- GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
- &send_message_noficiation,
- my_p2p_rnmsg);
- GNUNET_free (rnmsg);
- return GNUNET_OK;
-}
-
-
-/**
- * Handle P2P sync request.
- *
- * @param cls closure, always NULL
- * @param other the other peer involved
- * @param message the actual message
- * @return GNUNET_OK to keep the connection open,
- * GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_p2p_sync_request (void *cls, const struct GNUNET_PeerIdentity *other,
- const struct GNUNET_MessageHeader *message)
-{
- struct ChatClient *entry;
- struct GNUNET_CORE_TransmitHandle *th;
- size_t msg_size;
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got P2P sync request\n");
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Notifying the requester of all known clients\n");
-#endif
- entry = client_list_head;
- while (NULL != entry)
- {
- msg_size =
- sizeof (struct P2PJoinNotificationMessage) + strlen (entry->room) +
- entry->meta_len;
- th = GNUNET_CORE_notify_transmit_ready (core, GNUNET_NO, 1,
- MAX_TRANSMIT_DELAY, other, msg_size,
- &transmit_join_notification_to_peer,
- entry);
- GNUNET_assert (NULL != th);
- entry = entry->next;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Handle P2P confirmation receipt.
- *
- * @param cls closure, always NULL
- * @param other the other peer involved
- * @param message the actual message
- * @return GNUNET_OK to keep the connection open,
- * GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_p2p_confirmation_receipt (void *cls,
- const struct GNUNET_PeerIdentity *other,
- const struct GNUNET_MessageHeader *message)
-{
- const struct P2PConfirmationReceiptMessage *p2p_crmsg;
- struct P2PConfirmationReceiptMessage *my_p2p_crmsg;
- struct ConfirmationReceiptMessage *crmsg;
- struct ChatClient *target;
- struct ChatClient *author;
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got P2P confirmation receipt\n");
- p2p_crmsg = (const struct P2PConfirmationReceiptMessage *) message;
- target = client_list_head;
- while ((NULL != target) &&
- (0 !=
- memcmp (&target->id, &p2p_crmsg->target, sizeof (struct GNUNET_HashCode))))
- target = target->next;
- if (NULL == target)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unknown source of the receipt. Rejecting the message\n");
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (target->rcpt_sequence_number >= ntohl (p2p_crmsg->sequence_number))
- {
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "This receipt has already been handled."
- " Sequence numbers (msg/sender): %u/%u\n",
- ntohl (p2p_crmsg->sequence_number),
- target->rcpt_sequence_number);
-#endif
- return GNUNET_OK;
- }
- target->rcpt_sequence_number = ntohl (p2p_crmsg->sequence_number);
- author = client_list_head;
- while ((NULL != author) &&
- (0 !=
- memcmp (&author->id, &p2p_crmsg->author, sizeof (struct GNUNET_HashCode))))
- author = author->next;
- if (NULL == author)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unknown addressee. Rejecting the receipt\n");
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- if (NULL == author->client)
- {
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "The author of the original message is not a local client."
- " Broadcasting receipt to neighbour peers\n");
-#endif
- my_p2p_crmsg =
- GNUNET_memdup (p2p_crmsg,
- sizeof (struct P2PConfirmationReceiptMessage));
- GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
- &send_confirmation_receipt,
- my_p2p_crmsg);
- GNUNET_free (my_p2p_crmsg);
- }
- else
- {
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "The author of the original message is a local client."
- " Verifying signature of the receipt\n");
-#endif
- crmsg = GNUNET_malloc (sizeof (struct ConfirmationReceiptMessage));
- crmsg->header.size = htons (sizeof (struct ConfirmationReceiptMessage));
- crmsg->header.type =
- htons (GNUNET_MESSAGE_TYPE_CHAT_CONFIRMATION_NOTIFICATION);
- crmsg->signature = p2p_crmsg->signature;
- crmsg->purpose = p2p_crmsg->purpose;
- crmsg->sequence_number = p2p_crmsg->msg_sequence_number;
- crmsg->reserved2 = 0;
- crmsg->timestamp = p2p_crmsg->timestamp;
- crmsg->target = p2p_crmsg->target;
- crmsg->author = p2p_crmsg->author;
- crmsg->content = p2p_crmsg->content;
- if (GNUNET_OK !=
- GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_CHAT_RECEIPT,
- &crmsg->purpose, &crmsg->signature,
- &target->public_key))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Invalid signature of the receipt\n");
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "The author of the original message is a local client."
- " Sending receipt to the client\n");
-#endif
- GNUNET_SERVER_notification_context_unicast (nc, author->client,
- &crmsg->header, GNUNET_NO);
- GNUNET_free (crmsg);
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Transmit a sync request to the peer.
- *
- * @param cls closure, NULL
- * @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_sync_request_to_peer (void *cls, size_t size, void *buf)
-{
- struct GNUNET_MessageHeader *m = buf;
- size_t msg_size;
-
-#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting P2P sync request\n");
-#endif
- msg_size = sizeof (struct GNUNET_MessageHeader);
- GNUNET_assert (size >= msg_size);
- GNUNET_assert (NULL != buf);
- m = buf;
- m->type = htons (GNUNET_MESSAGE_TYPE_CHAT_P2P_SYNC_REQUEST);
- m->size = htons (msg_size);
- return msg_size;
-}
-
-
-/**
- * Method called whenever a peer connects.
- *
- * @param cls closure
- * @param peer peer identity this notification is about
- */
-static void
-peer_connect_handler (void *cls, const struct GNUNET_PeerIdentity *peer)
-{
- struct ConnectedPeer *cp;
- struct GNUNET_CORE_TransmitHandle *th;
-
- if (0 == memcmp (peer, &me, sizeof (struct GNUNET_PeerIdentity)))
- return;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer connected: %s\n",
- GNUNET_i2s (peer));
- th = GNUNET_CORE_notify_transmit_ready (core, GNUNET_YES, 1,
- MAX_TRANSMIT_DELAY, peer,
- sizeof (struct GNUNET_MessageHeader),
- &transmit_sync_request_to_peer, NULL);
- GNUNET_assert (NULL != th);
- cp = GNUNET_CONTAINER_multihashmap_get (connected_peers, &peer->hashPubKey);
- if (NULL != cp)
- {
- GNUNET_break (0);
- return;
- }
- cp = GNUNET_malloc (sizeof (struct ConnectedPeer));
- cp->pid = GNUNET_PEER_intern (peer);
- GNUNET_break (GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_put (connected_peers,
- &peer->hashPubKey, cp,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-}
-
-
-/**
- * Iterator to free peer entries.
- *
- * @param cls closure, unused
- * @param key current key code
- * @param value value in the hash map (peer entry)
- * @return GNUNET_YES (we should continue to iterate)
- */
-static int
-clean_peer (void *cls, const struct GNUNET_HashCode * key, void *value)
-{
- struct ConnectedPeer *cp;
- const struct GNUNET_PeerIdentity *peer =
- (const struct GNUNET_PeerIdentity *) key;
-
- cp = GNUNET_CONTAINER_multihashmap_get (connected_peers, &peer->hashPubKey);
- if (cp == NULL)
- return GNUNET_YES;
- GNUNET_break (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_remove (connected_peers,
- &peer->hashPubKey, cp));
- GNUNET_PEER_change_rc (cp->pid, -1);
- GNUNET_free (cp);
- return GNUNET_YES;
-}
-
-
-/**
- * Method called whenever a peer disconnects.
- *
- * @param cls closure, not used
- * @param peer peer identity this notification is about
- */
-static void
-peer_disconnect_handler (void *cls, const struct GNUNET_PeerIdentity *peer)
-{
-
- if (0 == memcmp (peer, &me, sizeof (struct GNUNET_PeerIdentity)))
- return;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer disconnected: %s\n",
- GNUNET_i2s (peer));
- clean_peer (NULL, (const struct GNUNET_HashCode *) peer, NULL);
-}
-
-
-/**
- * Task run during shutdown.
- *
- * @param cls unused
- * @param tc unused
- */
-static void
-cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct AnonymousMessage *next_msg;
- struct ChatClient *next_client;
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Cleaning up\n");
- if (NULL != core)
- {
- GNUNET_CORE_disconnect (core);
- core = NULL;
- }
- if (NULL != nc)
- {
- GNUNET_SERVER_notification_context_destroy (nc);
- nc = NULL;
- }
- while (NULL != client_list_head)
- {
- next_client = client_list_head->next;
- GNUNET_free (client_list_head->room);
- GNUNET_free_non_null (client_list_head->member_info);
- GNUNET_free (client_list_head);
- client_list_head = next_client;
- }
- while (NULL != anonymous_list_head)
- {
- next_msg = anonymous_list_head->next;
- GNUNET_free (anonymous_list_head);
- anonymous_list_head = next_msg;
- }
- GNUNET_CONTAINER_multihashmap_iterate (connected_peers, &clean_peer, NULL);
- GNUNET_CONTAINER_multihashmap_destroy (connected_peers);
- connected_peers = NULL;
-}
-
-
-/**
- * To be called on core init/fail.
- *
- * @param cls closure, NULL
- * @param server handle to the server for this service
- * @param my_identity the public identity of this peer
- */
-static void
-core_init (void *cls, struct GNUNET_CORE_Handle *server,
- const struct GNUNET_PeerIdentity *my_identity)
-{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Core initialized\n");
- me = *my_identity;
-}
-
-
-/**
- * Process chat requests.
- *
- * @param cls closure, NULL
- * @param server the initialized server
- * @param c configuration to use
- */
-static void
-run (void *cls, struct GNUNET_SERVER_Handle *server,
- const struct GNUNET_CONFIGURATION_Handle *c)
-{
- static const struct GNUNET_SERVER_MessageHandler handlers[] = {
- {&handle_join_request, NULL,
- GNUNET_MESSAGE_TYPE_CHAT_JOIN_REQUEST, 0},
- {&handle_transmit_request, NULL,
- GNUNET_MESSAGE_TYPE_CHAT_TRANSMIT_REQUEST, 0},
- {&handle_acknowledge_request, NULL,
- GNUNET_MESSAGE_TYPE_CHAT_CONFIRMATION_RECEIPT,
- sizeof (struct ConfirmationReceiptMessage)},
- {NULL, NULL, 0, 0}
- };
- static const struct GNUNET_CORE_MessageHandler p2p_handlers[] = {
- {&handle_p2p_join_notification,
- GNUNET_MESSAGE_TYPE_CHAT_P2P_JOIN_NOTIFICATION, 0},
- {&handle_p2p_leave_notification,
- GNUNET_MESSAGE_TYPE_CHAT_P2P_LEAVE_NOTIFICATION,
- sizeof (struct P2PLeaveNotificationMessage)},
- {&handle_p2p_message_notification,
- GNUNET_MESSAGE_TYPE_CHAT_P2P_MESSAGE_NOTIFICATION, 0},
- {&handle_p2p_sync_request,
- GNUNET_MESSAGE_TYPE_CHAT_P2P_SYNC_REQUEST,
- sizeof (struct GNUNET_MessageHeader)},
- {&handle_p2p_confirmation_receipt,
- GNUNET_MESSAGE_TYPE_CHAT_P2P_CONFIRMATION_RECEIPT,
- sizeof (struct P2PConfirmationReceiptMessage)},
- {NULL, 0, 0}
- };
-
- GNUNET_log_setup ("gnunet-service-chat",
-#if DEBUG_CHAT_SERVICE
- "DEBUG",
-#else
- "WARNING",
-#endif
- NULL);
- cfg = c;
- nc = GNUNET_SERVER_notification_context_create (server, 16);
- connected_peers =
- GNUNET_CONTAINER_multihashmap_create (EXPECTED_NEIGHBOUR_COUNT, GNUNET_NO);
- GNUNET_SERVER_add_handlers (server, handlers);
- core =
- GNUNET_CORE_connect (cfg, NULL, &core_init,
- &peer_connect_handler, &peer_disconnect_handler,
- NULL, GNUNET_NO, NULL, GNUNET_NO, p2p_handlers);
- GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
- NULL);
-}
-
-
-/**
- * The main function for the chat service.
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- */
-int
-main (int argc, char *const *argv)
-{
- return (GNUNET_OK ==
- GNUNET_SERVICE_run (argc, argv, "chat", GNUNET_SERVICE_OPTION_NONE,
- &run, NULL)) ? 0 : 1;
-}
-
-/* end of gnunet-service-chat.c */
diff --git a/src/chat/test_chat.c b/src/chat/test_chat.c
@@ -1,556 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2005, 2006, 2007, 2008, 2011 Christian Grothoff (and other contributing authors)
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file chat/test_chat.c
- * @brief base test case for the chat library
- * @author Christian Grothoff
- * @author Nathan Evans
- * @author Vitaly Minko
- *
- * This test case serves as a base for simple chatting, anonymous chatting,
- * authenticated chatting and acknowledgements test cases. Based on the
- * executable being run the correct test case will be performed. Private
- * chatting is covered by a separate test case since it requires 3 users.
- */
-
-#include "platform.h"
-#include "gnunet_crypto_lib.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_arm_service.h"
-#include "gnunet_chat_service.h"
-
-/**
- * How long until we give up on passing the test?
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
-
-struct PeerContext
-{
- struct GNUNET_CONFIGURATION_Handle *cfg;
- struct GNUNET_OS_Process *arm_proc;
-};
-
-struct Wanted
-{
- struct GNUNET_CONTAINER_MetaData *meta;
-
- struct GNUNET_HashCode *sender;
-
- char *msg;
-
- const char *me;
-
- enum GNUNET_CHAT_MsgOptions opt;
-
- uint32_t sequence_number;
-
- struct GNUNET_TIME_Absolute timestamp;
-
- GNUNET_SCHEDULER_Task next_task;
-
- void *next_task_cls;
-
-};
-
-static struct PeerContext p1;
-
-static struct PeerContext p2;
-
-static struct GNUNET_HashCode alice;
-
-static struct GNUNET_HashCode bob;
-
-static struct GNUNET_CHAT_Room *alice_room;
-
-static struct GNUNET_CHAT_Room *bob_room;
-
-static struct GNUNET_CONTAINER_MetaData *alice_meta;
-
-static struct GNUNET_CONTAINER_MetaData *bob_meta;
-
-static struct Wanted alice_wanted;
-
-static struct Wanted bob_wanted;
-
-static GNUNET_SCHEDULER_TaskIdentifier kill_task;
-
-static GNUNET_SCHEDULER_TaskIdentifier wait_task;
-
-static int err;
-
-static int is_ready;
-
-static int is_p2p;
-
-static int is_ackn;
-
-static int is_anon;
-
-static int is_auth;
-
-
-static void
-setup_peer (struct PeerContext *p, const char *cfgname)
-{
- char *binary;
-
- binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
- p->cfg = GNUNET_CONFIGURATION_create ();
- p->arm_proc =
- GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, binary,
- "gnunet-service-arm",
- "-c", cfgname, NULL);
- GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
- GNUNET_free (binary);
-}
-
-
-static void
-stop_arm (struct PeerContext *p)
-{
- if (0 != GNUNET_OS_process_kill (p->arm_proc, SIGTERM))
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
- if (GNUNET_OS_process_wait (p->arm_proc) != GNUNET_OK)
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid");
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n",
- GNUNET_OS_process_get_pid (p->arm_proc));
- GNUNET_OS_process_destroy (p->arm_proc);
- p->arm_proc = NULL;
- GNUNET_CONFIGURATION_destroy (p->cfg);
-}
-
-
-static void
-abort_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- if (alice_room != NULL)
- {
- GNUNET_CHAT_leave_room (alice_room);
- alice_room = NULL;
- }
- if (bob_room != NULL)
- {
- GNUNET_CHAT_leave_room (bob_room);
- bob_room = NULL;
- }
- err = 1;
-}
-
-
-static void
-timeout_kill (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- fprintf (stderr,
- "Timed out, stopping the test.\n");
- kill_task = GNUNET_SCHEDULER_NO_TASK;
- if (wait_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (wait_task);
- wait_task = GNUNET_SCHEDULER_NO_TASK;
- }
- GNUNET_SCHEDULER_add_continuation (&abort_test, NULL,
- GNUNET_SCHEDULER_REASON_PREREQ_DONE);
-}
-
-
-static int
-join_cb (void *cls)
-{
- struct Wanted *want = cls;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s has joined\n", want->me);
- if (NULL != want->next_task)
- GNUNET_SCHEDULER_add_now (want->next_task, want->next_task_cls);
- return GNUNET_OK;
-}
-
-
-static int
-member_list_cb (void *cls, const struct GNUNET_CONTAINER_MetaData *member_info,
- const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *member_id,
- enum GNUNET_CHAT_MsgOptions options)
-{
- struct Wanted *want = cls;
- struct GNUNET_HashCode sender;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s - told that %s has %s\n", want->me,
- member_info ==
- NULL ? NULL : GNUNET_CONTAINER_meta_data_get_by_type (member_info,
- EXTRACTOR_METATYPE_TITLE),
- member_info == NULL ? "left" : "joined");
- GNUNET_CRYPTO_hash (member_id,
- sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
- &sender);
- if ((0 == memcmp (&sender, want->sender, sizeof (struct GNUNET_HashCode))) &&
- (((member_info == NULL) && (want->meta == NULL)) ||
- ((member_info != NULL) && (want->meta != NULL) &&
- (GNUNET_CONTAINER_meta_data_test_equal (member_info, want->meta)))) &&
- (options == want->opt))
- {
- if (NULL != want->next_task)
- GNUNET_SCHEDULER_add_now (want->next_task, want->next_task_cls);
- }
- else
- {
- GNUNET_SCHEDULER_cancel (kill_task);
- kill_task = GNUNET_SCHEDULER_NO_TASK;
- GNUNET_SCHEDULER_add_now (&abort_test, NULL);
- }
- return GNUNET_OK;
-}
-
-
-static int
-receive_cb (void *cls, struct GNUNET_CHAT_Room *room,
- const struct GNUNET_HashCode * sender,
- const struct GNUNET_CONTAINER_MetaData *meta, const char *message,
- struct GNUNET_TIME_Absolute timestamp,
- enum GNUNET_CHAT_MsgOptions options)
-{
- struct Wanted *want = cls;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-
- "%s - told that %s said %s\n", want->me,
- meta == NULL ? NULL : GNUNET_CONTAINER_meta_data_get_by_type (meta,
- EXTRACTOR_METATYPE_TITLE),
- message);
- if ((0 == strcmp (message, want->msg)) &&
- (((sender == NULL) && (want->sender == NULL)) ||
- ((sender != NULL) && (want->sender != NULL) &&
- (0 == memcmp (sender, want->sender, sizeof (struct GNUNET_HashCode))))) &&
- (GNUNET_CONTAINER_meta_data_test_equal (meta, want->meta)) &&
- (options == want->opt) &&
- /* Not == since the library sets the actual timestamp, so it may be
- * slightly greater
- */
- (timestamp.abs_value >= want->timestamp.abs_value))
- {
- if (NULL != want->next_task)
- GNUNET_SCHEDULER_add_now (want->next_task, want->next_task_cls);
- }
- else
- {
- GNUNET_SCHEDULER_cancel (kill_task);
- kill_task = GNUNET_SCHEDULER_NO_TASK;
- GNUNET_SCHEDULER_add_now (&abort_test, NULL);
- }
- return GNUNET_OK;
-}
-
-
-static int
-confirmation_cb (void *cls, struct GNUNET_CHAT_Room *room,
- uint32_t orig_seq_number,
- struct GNUNET_TIME_Absolute timestamp,
- const struct GNUNET_HashCode * receiver)
-{
- struct Wanted *want = cls;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s - told that %s acknowledged message #%d\n", want->me,
- GNUNET_CONTAINER_meta_data_get_by_type (want->meta,
- EXTRACTOR_METATYPE_TITLE),
- orig_seq_number);
- if ((0 == memcmp (receiver, want->sender, sizeof (struct GNUNET_HashCode))) &&
- (orig_seq_number == want->sequence_number) &&
- (timestamp.abs_value >= want->timestamp.abs_value))
- {
- if (NULL != want->next_task)
- GNUNET_SCHEDULER_add_now (want->next_task, want->next_task_cls);
- }
- else
- {
- GNUNET_SCHEDULER_cancel (kill_task);
- kill_task = GNUNET_SCHEDULER_NO_TASK;
- GNUNET_SCHEDULER_add_now (&abort_test, NULL);
- }
- return GNUNET_OK;
-}
-
-
-static void
-wait_until_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- GNUNET_SCHEDULER_Task task = cls;
-
- if (is_ready)
- {
- wait_task = GNUNET_SCHEDULER_NO_TASK;
- GNUNET_SCHEDULER_add_now (task, NULL);
- }
- else
- wait_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_MILLISECONDS, 50),
- &wait_until_ready, task);
-}
-
-
-static void
-disconnect_alice (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Alice is leaving.\n");
- if (is_p2p)
- stop_arm (&p2);
- GNUNET_CHAT_leave_room (alice_room);
- alice_room = NULL;
- GNUNET_SCHEDULER_cancel (kill_task);
- kill_task = GNUNET_SCHEDULER_NO_TASK;
-}
-
-
-static void
-disconnect_bob (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Bob is leaving.\n");
- alice_wanted.meta = NULL;
- alice_wanted.sender = &bob;
- alice_wanted.msg = NULL;
- alice_wanted.opt = 0;
- alice_wanted.next_task = &disconnect_alice;
- alice_wanted.next_task_cls = NULL;
- GNUNET_CHAT_leave_room (bob_room);
- bob_room = NULL;
-}
-
-
-static void
-set_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- is_ready = GNUNET_YES;
-}
-
-
-static void
-send_to_alice (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Bob says 'Hi!'\n");
- alice_wanted.meta = bob_meta;
- alice_wanted.sender = &bob;
- alice_wanted.msg = "Hi Alice!";
- alice_wanted.opt = GNUNET_CHAT_MSG_OPTION_NONE;
- alice_wanted.timestamp = GNUNET_TIME_absolute_get ();
- alice_wanted.next_task = &disconnect_bob;
- alice_wanted.next_task_cls = NULL;
- GNUNET_CHAT_send_message (bob_room, "Hi Alice!", GNUNET_CHAT_MSG_OPTION_NONE,
- NULL, NULL);
-}
-
-
-static void
-send_to_bob (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- enum GNUNET_CHAT_MsgOptions options;
- uint32_t *seq = NULL;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Alice says 'Hi!'\n");
- if (is_ackn)
- {
- options = GNUNET_CHAT_MSG_ACKNOWLEDGED;
- alice_wanted.meta = bob_meta;
- alice_wanted.sender = &bob;
- alice_wanted.timestamp = GNUNET_TIME_absolute_get ();
- alice_wanted.next_task = &disconnect_bob;
- alice_wanted.next_task_cls = NULL;
- bob_wanted.meta = alice_meta;
- bob_wanted.sender = &alice;
- bob_wanted.next_task = NULL;
- seq = &(alice_wanted.sequence_number);
- }
- else if (is_anon)
- {
- options = GNUNET_CHAT_MSG_ANONYMOUS;
- bob_wanted.meta = NULL;
- bob_wanted.sender = NULL;
- bob_wanted.next_task = &disconnect_bob;
- }
- else if (is_auth)
- {
- options = GNUNET_CHAT_MSG_AUTHENTICATED;
- bob_wanted.meta = alice_meta;
- bob_wanted.sender = &alice;
- bob_wanted.next_task = &disconnect_bob;
- }
- else
- {
- options = GNUNET_CHAT_MSG_OPTION_NONE;
- bob_wanted.meta = alice_meta;
- bob_wanted.sender = &alice;
- bob_wanted.next_task = &send_to_alice;
- }
- bob_wanted.msg = "Hi Bob!";
- bob_wanted.opt = options;
- bob_wanted.timestamp = GNUNET_TIME_absolute_get ();
- bob_wanted.next_task_cls = NULL;
- GNUNET_CHAT_send_message (alice_room, "Hi Bob!", options, NULL, seq);
-}
-
-
-static void
-prepare_for_alice_task (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- bob_wanted.meta = alice_meta;
- bob_wanted.sender = &alice;
- bob_wanted.msg = NULL;
- bob_wanted.opt = -1;
- bob_wanted.next_task = &set_ready;
- bob_wanted.next_task_cls = NULL;
-}
-
-
-static void
-join_bob_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Bob joining\n");
- alice_wanted.meta = bob_meta;
- alice_wanted.sender = &bob;
- alice_wanted.msg = NULL;
- alice_wanted.opt = -1;
- alice_wanted.next_task = &wait_until_ready;
- alice_wanted.next_task_cls = &send_to_bob;
- bob_wanted.next_task = &prepare_for_alice_task;
- bob_wanted.next_task_cls = NULL;
- is_ready = GNUNET_NO;
- bob_room =
- GNUNET_CHAT_join_room (is_p2p ? p2.cfg : p1.cfg, "bob", bob_meta, "test",
- -1, &join_cb, &bob_wanted, &receive_cb,
- &bob_wanted, &member_list_cb, &bob_wanted,
- &confirmation_cb, &bob_wanted, &bob);
- if (NULL == bob_room)
- {
- GNUNET_SCHEDULER_cancel (kill_task);
- kill_task = GNUNET_SCHEDULER_NO_TASK;
- GNUNET_CHAT_leave_room (alice_room);
- alice_room = NULL;
- err = 1;
- }
-}
-
-
-static void
-join_alice_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Alice joining\n");
- alice_wanted.next_task = &join_bob_task;
- alice_wanted.next_task_cls = NULL;
- alice_room =
- GNUNET_CHAT_join_room (p1.cfg, "alice", alice_meta, "test", -1, &join_cb,
- &alice_wanted, &receive_cb, &alice_wanted,
- &member_list_cb, &alice_wanted, &confirmation_cb,
- &alice_wanted, &alice);
- if (NULL == alice_room)
- {
- GNUNET_SCHEDULER_cancel (kill_task);
- kill_task = GNUNET_SCHEDULER_NO_TASK;
- err = 1;
- }
-}
-
-
-static void
-run (void *cls, char *const *args, const char *cfgfile,
- const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
- if (is_p2p)
- {
- setup_peer (&p1, "test_chat_peer1.conf");
- setup_peer (&p2, "test_chat_peer2.conf");
- }
- else
- setup_peer (&p1, "test_chat_data.conf");
-
- memset (&alice_wanted, 0, sizeof (struct Wanted));
- memset (&bob_wanted, 0, sizeof (struct Wanted));
- alice_wanted.me = "Alice";
- bob_wanted.me = "Bob";
- alice_meta = GNUNET_CONTAINER_meta_data_create ();
- GNUNET_CONTAINER_meta_data_insert (alice_meta, "<gnunet>",
- EXTRACTOR_METATYPE_TITLE,
- EXTRACTOR_METAFORMAT_UTF8, "text/plain",
- "Alice", strlen ("Alice") + 1);
- bob_meta = GNUNET_CONTAINER_meta_data_create ();
- GNUNET_CONTAINER_meta_data_insert (bob_meta, "<gnunet>",
- EXTRACTOR_METATYPE_TITLE,
- EXTRACTOR_METAFORMAT_UTF8, "text/plain",
- "Bob", strlen ("Bob") + 1);
- kill_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &timeout_kill, NULL);
- GNUNET_SCHEDULER_add_now (&join_alice_task, NULL);
-}
-
-
-int
-main (int argc, char *argv[])
-{
- char *const argvx[] = {
- "test-chat",
- "-c",
- "test_chat_data.conf",
- NULL
- };
- struct GNUNET_GETOPT_CommandLineOption options[] = {
- GNUNET_GETOPT_OPTION_END
- };
-
- GNUNET_log_setup ("test_chat",
- "WARNING",
- NULL);
- if (strstr (argv[0], "p2p") != NULL)
- {
- is_p2p = GNUNET_YES;
- }
- if (strstr (argv[0], "acknowledgment") != NULL)
- {
- is_ackn = GNUNET_YES;
- }
- else if (strstr (argv[0], "anonymous") != NULL)
- {
- is_anon = GNUNET_YES;
- }
- else if (strstr (argv[0], "authentication") != NULL)
- {
- is_auth = GNUNET_YES;
- }
- GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1, argvx,
- "test-chat", "nohelp", options, &run, NULL);
- stop_arm (&p1);
- GNUNET_CONTAINER_meta_data_destroy (alice_meta);
- GNUNET_CONTAINER_meta_data_destroy (bob_meta);
- if (is_p2p)
- {
- GNUNET_DISK_directory_remove ("/tmp/gnunet-test-chat-peer-1/");
- GNUNET_DISK_directory_remove ("/tmp/gnunet-test-chat-peer-2/");
- }
- else
- GNUNET_DISK_directory_remove ("/tmp/gnunet-test-chat/");
- return err;
-}
-
-/* end of test_chat.c */
diff --git a/src/chat/test_chat_data.conf b/src/chat/test_chat_data.conf
@@ -1,55 +0,0 @@
-[PATHS]
-SERVICEHOME = /tmp/gnunet-test-chat/
-
-[gnunetd]
-HOSTKEY = $SERVICEHOME/.hostkey
-
-[resolver]
-PORT = 42464
-HOSTNAME = localhost
-
-[transport]
-PORT = 42465
-PLUGINS =
-
-[arm]
-PORT = 42466
-HOSTNAME = localhost
-DEFAULTSERVICES = core chat
-
-[peerinfo]
-PORT = 42469
-HOSTNAME = localhost
-
-[core]
-PORT = 42470
-HOSTNAME = localhost
-
-[chat]
-PORT = 42471
-HOSTNAME = localhost
-HOME = $SERVICEHOME
-BINARY = gnunet-service-chat
-
-[testing]
-WEAKRANDOM = YES
-
-[nat]
-DISABLEV6 = YES
-BINDTO = 127.0.0.1
-ENABLE_UPNP = NO
-BEHIND_NAT = NO
-ALLOW_NAT = NO
-INTERNAL_ADDRESS = 127.0.0.1
-EXTERNAL_ADDRESS = 127.0.0.1
-
-[dns]
-AUTOSTART = NO
-
-[consensus]
-AUTOSTART = NO
-
-[nse]
-AUTOSTART = NO
-
-
diff --git a/src/chat/test_chat_peer1.conf b/src/chat/test_chat_peer1.conf
@@ -1,92 +0,0 @@
-[PATHS]
-SERVICEHOME = /tmp/gnunet-test-chat-peer-1/
-
-[gnunetd]
-HOSTKEY = $SERVICEHOME/.hostkey
-
-[hostlist]
-HTTPPORT = 31000
-OPTIONS = -p
-
-[resolver]
-PORT = 31001
-HOSTNAME = localhost
-UNIXPATH = /tmp/gnunet-chat-p1-service-resolver.sock
-
-[transport]
-PORT = 31002
-UNIXPATH = /tmp/gnunet-chat-p1-service-transport.sock
-PLUGINS = tcp
-#BINARY = /home/grothoff/bin/gnunet-service-transport
-#PREFIX = valgrind
-
-[transport-tcp]
-PORT = 31003
-
-[arm]
-PORT = 31004
-UNIXPATH = /tmp/gnunet-chat-p1-service-arm.sock
-HOSTNAME = localhost
-DEFAULTSERVICES = resolver transport core topology hostlist statistics chat
-
-[core]
-PORT = 31005
-UNIXPATH = /tmp/gnunet-chat-p1-service-core.sock
-HOSTNAME = localhost
-
-[topology]
-MINIMUM-FRIENDS = 0
-FRIENDS-ONLY = NO
-AUTOCONNECT = YES
-TARGET-CONNECTION-COUNT = 16
-FRIENDS = $SERVICEHOME/friends
-BINARY = gnunet-daemon-topology
-
-[peerinfo]
-PORT = 31006
-UNIXPATH = /tmp/gnunet-chat-p1-service-peerinfo.sock
-HOSTNAME = localhost
-
-[statistics]
-PORT = 31007
-HOSTNAME = localhost
-UNIXPATH = /tmp/gnunet-chat-p1-service-statistics.sock
-
-[chat]
-PORT = 31008
-HOSTNAME = localhost
-HOME = $SERVICEHOME
-BINARY = gnunet-service-chat
-
-[testing]
-WEAKRANDOM = YES
-
-[fs]
-AUTOSTART = NO
-
-[datastore]
-AUTOSTART = NO
-
-[dht]
-AUTOSTART = NO
-
-[mesh]
-AUTOSTART = NO
-[nat]
-DISABLEV6 = YES
-BINDTO = 127.0.0.1
-ENABLE_UPNP = NO
-BEHIND_NAT = NO
-ALLOW_NAT = NO
-INTERNAL_ADDRESS = 127.0.0.1
-EXTERNAL_ADDRESS = 127.0.0.1
-
-[dns]
-AUTOSTART = NO
-
-[nse]
-AUTOSTART = NO
-
-[ats]
-PORT = 31971
-UNIXPATH = /tmp/gnunet-chat-p1-service-ats.sock
diff --git a/src/chat/test_chat_peer2.conf b/src/chat/test_chat_peer2.conf
@@ -1,94 +0,0 @@
-[PATHS]
-SERVICEHOME = /tmp/gnunet-test-chat-peer-2/
-
-[gnunetd]
-HOSTKEY = $SERVICEHOME/.hostkey
-
-[hostlist]
-SERVERS = http://localhost:31000/
-OPTIONS = -b
-
-[resolver]
-PORT = 32001
-HOSTNAME = localhost
-UNIXPATH = /tmp/gnunet-chat-p2-service-resolver.sock
-
-[transport]
-PORT = 32002
-UNIXPATH = /tmp/gnunet-chat-p2-service-transport.sock
-PLUGINS = tcp
-#BINARY = /home/grothoff/bin/gnunet-service-transport
-#PREFIX = valgrind
-
-[transport-tcp]
-PORT = 32003
-
-[arm]
-PORT = 32004
-UNIXPATH = /tmp/gnunet-chat-p2-service-arm.sock
-HOSTNAME = localhost
-DEFAULTSERVICES = resolver transport core topology hostlist statistics chat
-
-[core]
-PORT = 32005
-UNIXPATH = /tmp/gnunet-chat-p2-service-core.sock
-HOSTNAME = localhost
-
-[topology]
-MINIMUM-FRIENDS = 0
-FRIENDS-ONLY = NO
-AUTOCONNECT = YES
-TARGET-CONNECTION-COUNT = 16
-FRIENDS = $SERVICEHOME/friends
-BINARY = gnunet-daemon-topology
-
-[peerinfo]
-PORT = 32006
-UNIXPATH = /tmp/gnunet-chat-p2-service-peerinfo.sock
-HOSTNAME = localhost
-
-[statistics]
-PORT = 32007
-HOSTNAME = localhost
-UNIXPATH = /tmp/gnunet-chat-p2-service-statistics.sock
-
-[chat]
-PORT = 32008
-HOSTNAME = localhost
-HOME = $SERVICEHOME
-BINARY = gnunet-service-chat
-
-[testing]
-WEAKRANDOM = YES
-
-[fs]
-AUTOSTART = NO
-
-[datastore]
-AUTOSTART = NO
-
-[dht]
-AUTOSTART = NO
-
-[mesh]
-AUTOSTART = NO
-
-[nat]
-DISABLEV6 = YES
-BINDTO = 127.0.0.1
-ENABLE_UPNP = NO
-BEHIND_NAT = NO
-ALLOW_NAT = NO
-INTERNAL_ADDRESS = 127.0.0.1
-EXTERNAL_ADDRESS = 127.0.0.1
-
-[dns]
-AUTOSTART = NO
-
-[nse]
-AUTOSTART = NO
-
-[ats]
-PORT = 32971
-UNIXPATH = /tmp/gnunet-chat-p2-service-ats.sock
-
diff --git a/src/chat/test_chat_peer3.conf b/src/chat/test_chat_peer3.conf
@@ -1,93 +0,0 @@
-[PATHS]
-SERVICEHOME = /tmp/gnunet-test-chat-peer-3/
-
-[gnunetd]
-HOSTKEY = $SERVICEHOME/.hostkey
-
-[hostlist]
-SERVERS = http://localhost:31000/
-OPTIONS = -b
-
-[resolver]
-PORT = 33001
-HOSTNAME = localhost
-UNIXPATH = /tmp/gnunet-chat-p3-service-resolver.sock
-
-[transport]
-PORT = 33002
-UNIXPATH = /tmp/gnunet-chat-p3-service-transport.sock
-PLUGINS = tcp
-#BINARY = /home/grothoff/bin/gnunet-service-transport
-#PREFIX = valgrind
-
-[transport-tcp]
-PORT = 33003
-
-[arm]
-PORT = 33004
-UNIXPATH = /tmp/gnunet-chat-p3-service-arm.sock
-HOSTNAME = localhost
-DEFAULTSERVICES = resolver transport core topology hostlist statistics chat
-
-[core]
-PORT = 33005
-UNIXPATH = /tmp/gnunet-chat-p3-service-core.sock
-HOSTNAME = localhost
-
-[topology]
-MINIMUM-FRIENDS = 0
-FRIENDS-ONLY = NO
-AUTOCONNECT = YES
-TARGET-CONNECTION-COUNT = 16
-FRIENDS = $SERVICEHOME/friends
-BINARY = gnunet-daemon-topology
-
-[peerinfo]
-PORT = 33006
-UNIXPATH = /tmp/gnunet-chat-p3-service-peerinfo.sock
-HOSTNAME = localhost
-
-[statistics]
-PORT = 33007
-HOSTNAME = localhost
-UNIXPATH = /tmp/gnunet-chat-p3-service-statistics.sock
-
-[chat]
-PORT = 33008
-HOSTNAME = localhost
-HOME = $SERVICEHOME
-BINARY = gnunet-service-chat
-
-[testing]
-WEAKRANDOM = YES
-
-[fs]
-AUTOSTART = NO
-
-[datastore]
-AUTOSTART = NO
-
-[dht]
-AUTOSTART = NO
-
-[mesh]
-AUTOSTART = NO
-
-[nat]
-DISABLEV6 = YES
-BINDTO = 127.0.0.1
-ENABLE_UPNP = NO
-BEHIND_NAT = NO
-ALLOW_NAT = NO
-INTERNAL_ADDRESS = 127.0.0.1
-EXTERNAL_ADDRESS = 127.0.0.1
-
-[dns]
-AUTOSTART = NO
-
-
-
-[nse]
-AUTOSTART = NO
-
-
diff --git a/src/chat/test_chat_private.c b/src/chat/test_chat_private.c
@@ -1,640 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2011 Christian Grothoff (and other contributing authors)
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file chat/test_chat_private.c
- * @brief testcase for private chatting
- * @author Vitaly Minko
- */
-
-#include "platform.h"
-#include "gnunet_crypto_lib.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_arm_service.h"
-#include "gnunet_chat_service.h"
-
-#define VERBOSE GNUNET_NO
-
-/**
- * How long until we give up on passing the test?
- */
-#define KILL_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
-
-/**
- * How long until we give up on receiving somebody else's private message?
- */
-#define PM_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
-
-struct PeerContext
-{
- struct GNUNET_CONFIGURATION_Handle *cfg;
- struct GNUNET_OS_Process *arm_proc;
-};
-
-struct Wanted
-{
- struct GNUNET_CONTAINER_MetaData *meta;
-
- struct GNUNET_HashCode *sender;
-
- /**
- * Alternative meta/sender is used when we expect join/leave notification
- * from two peers and don't know which one will come first.
- */
- struct GNUNET_CONTAINER_MetaData *meta2;
-
- struct GNUNET_HashCode *sender2;
-
- char *msg;
-
- const char *me;
-
- enum GNUNET_CHAT_MsgOptions opt;
-
- struct GNUNET_TIME_Absolute timestamp;
-
- GNUNET_SCHEDULER_Task next_task;
-
- void *next_task_cls;
-
-};
-
-static struct PeerContext p1;
-
-static struct PeerContext p2;
-
-static struct PeerContext p3;
-
-static struct GNUNET_HashCode alice;
-
-static struct GNUNET_HashCode bob;
-
-static struct GNUNET_HashCode carol;
-
-static struct GNUNET_CHAT_Room *alice_room;
-
-static struct GNUNET_CHAT_Room *bob_room;
-
-static struct GNUNET_CHAT_Room *carol_room;
-
-static struct GNUNET_CONTAINER_MetaData *alice_meta;
-
-static struct GNUNET_CONTAINER_MetaData *bob_meta;
-
-static struct GNUNET_CONTAINER_MetaData *carol_meta;
-
-static struct Wanted alice_wanted;
-
-static struct Wanted bob_wanted;
-
-static struct Wanted carol_wanted;
-
-static GNUNET_SCHEDULER_TaskIdentifier kill_task;
-
-static GNUNET_SCHEDULER_TaskIdentifier finish_task;
-
-static GNUNET_SCHEDULER_TaskIdentifier wait_task;
-
-static int err;
-
-static int alice_ready;
-
-static int bob_ready;
-
-static int is_p2p;
-
-static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *bob_public_key;
-
-
-static void
-setup_peer (struct PeerContext *p, const char *cfgname)
-{
- char *binary;
-
- binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
- p->cfg = GNUNET_CONFIGURATION_create ();
- p->arm_proc =
- GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, binary,
- "gnunet-service-arm",
- "-c", cfgname, NULL);
- GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
- GNUNET_free (binary);
-}
-
-
-static void
-stop_arm (struct PeerContext *p)
-{
- if (0 != GNUNET_OS_process_kill (p->arm_proc, SIGTERM))
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
- if (GNUNET_OS_process_wait (p->arm_proc) != GNUNET_OK)
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid");
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n",
- GNUNET_OS_process_get_pid (p->arm_proc));
- GNUNET_OS_process_destroy (p->arm_proc);
- p->arm_proc = NULL;
- GNUNET_CONFIGURATION_destroy (p->cfg);
-}
-
-
-static void
-abort_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- if (alice_room != NULL)
- {
- GNUNET_CHAT_leave_room (alice_room);
- alice_room = NULL;
- }
- if (bob_room != NULL)
- {
- GNUNET_CHAT_leave_room (bob_room);
- bob_room = NULL;
- }
- if (carol_room != NULL)
- {
- GNUNET_CHAT_leave_room (carol_room);
- carol_room = NULL;
- }
- err = 1;
-}
-
-
-static void
-timeout_kill (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-#if VERBOSE
- printf ("Timed out, stopping the test.\n");
-#endif
- kill_task = GNUNET_SCHEDULER_NO_TASK;
- if (wait_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (wait_task);
- wait_task = GNUNET_SCHEDULER_NO_TASK;
- }
- GNUNET_SCHEDULER_add_continuation (&abort_test, NULL,
- GNUNET_SCHEDULER_REASON_PREREQ_DONE);
-}
-
-
-static int
-join_cb (void *cls)
-{
- struct Wanted *want = cls;
-
-#if VERBOSE
- printf ("%s has joined\n", want->me);
-#endif
- if (NULL != want->next_task)
- GNUNET_SCHEDULER_add_now (want->next_task, want->next_task_cls);
- return GNUNET_OK;
-}
-
-
-static int
-member_list_cb (void *cls, const struct GNUNET_CONTAINER_MetaData *member_info,
- const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *member_id,
- enum GNUNET_CHAT_MsgOptions options)
-{
- struct Wanted *want = cls;
- struct GNUNET_HashCode sender;
-
-#if VERBOSE
- printf ("%s - told that %s has %s\n", want->me,
- member_info ==
- NULL ? NULL : GNUNET_CONTAINER_meta_data_get_by_type (member_info,
- EXTRACTOR_METATYPE_TITLE),
- member_info == NULL ? "left" : "joined");
-#endif
- GNUNET_CRYPTO_hash (member_id,
- sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
- &sender);
- /* entertain both primary and an alternative sender/meta */
- if (((0 == memcmp (&sender, want->sender, sizeof (struct GNUNET_HashCode))) ||
- ((want->sender2 != NULL) &&
- (0 == memcmp (&sender, want->sender2, sizeof (struct GNUNET_HashCode))))) &&
- (((member_info == NULL) && (want->meta == NULL)) ||
- ((member_info != NULL) &&
- (((want->meta != NULL) &&
- GNUNET_CONTAINER_meta_data_test_equal (member_info, want->meta)) ||
- ((want->meta2 != NULL) &&
- GNUNET_CONTAINER_meta_data_test_equal (member_info, want->meta2)))))
- && (options == want->opt))
- {
- /* remember Bob's public key, we need it to send private message */
- if (NULL == bob_public_key &&
- (0 == memcmp (&bob, want->sender, sizeof (struct GNUNET_HashCode))))
- bob_public_key =
- GNUNET_memdup (member_id,
- sizeof (struct
- GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
- if (want->sender2 != NULL)
- {
- /* flush alternative sender */
- if (0 == memcmp (&sender, want->sender, sizeof (struct GNUNET_HashCode)))
- {
- want->sender = want->sender2;
- want->meta = want->meta2;
- }
- want->sender2 = NULL;
- want->meta2 = NULL;
- }
- else if (NULL != want->next_task)
- GNUNET_SCHEDULER_add_now (want->next_task, want->next_task_cls);
- }
- else
- {
- GNUNET_SCHEDULER_cancel (kill_task);
- kill_task = GNUNET_SCHEDULER_NO_TASK;
- GNUNET_SCHEDULER_add_now (&abort_test, NULL);
- }
- return GNUNET_OK;
-}
-
-
-static int
-receive_cb (void *cls, struct GNUNET_CHAT_Room *room,
- const struct GNUNET_HashCode * sender,
- const struct GNUNET_CONTAINER_MetaData *meta, const char *message,
- struct GNUNET_TIME_Absolute timestamp,
- enum GNUNET_CHAT_MsgOptions options)
-{
- struct Wanted *want = cls;
-
-#if VERBOSE
- printf ("%s - told that %s said '%s'\n", want->me,
- meta == NULL ? NULL : GNUNET_CONTAINER_meta_data_get_by_type (meta,
- EXTRACTOR_METATYPE_TITLE),
- message);
-#endif
-
- if ((want->msg != NULL) && (0 == strcmp (message, want->msg)) &&
- (((sender == NULL) && (want->sender == NULL)) ||
- ((sender != NULL) && (want->sender != NULL) &&
- (0 == memcmp (sender, want->sender, sizeof (struct GNUNET_HashCode))))) &&
- (GNUNET_CONTAINER_meta_data_test_equal (meta, want->meta)) &&
- (options == want->opt) &&
- /* Not == since the library sets the actual timestamp, so it may be
- * slightly greater
- */
- (timestamp.abs_value >= want->timestamp.abs_value))
- {
- if (NULL != want->next_task)
- GNUNET_SCHEDULER_add_now (want->next_task, want->next_task_cls);
- }
- else
- {
- GNUNET_SCHEDULER_cancel (kill_task);
- kill_task = GNUNET_SCHEDULER_NO_TASK;
- GNUNET_SCHEDULER_cancel (finish_task);
- finish_task = GNUNET_SCHEDULER_NO_TASK;
- GNUNET_SCHEDULER_add_now (&abort_test, NULL);
- }
- return GNUNET_OK;
-}
-
-
-static void
-wait_until_all_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- GNUNET_SCHEDULER_Task task = cls;
-
-#if VERBOSE
- printf ("Waiting...\n");
-#endif
- if (alice_ready && bob_ready)
- {
- wait_task = GNUNET_SCHEDULER_NO_TASK;
- GNUNET_SCHEDULER_add_now (task, NULL);
- }
- else
- wait_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_MILLISECONDS, 5000),
- &wait_until_all_ready, task);
-}
-
-
-static void
-set_alice_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- alice_ready = GNUNET_YES;
-}
-
-
-static void
-set_bob_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- bob_ready = GNUNET_YES;
-}
-
-
-static void
-disconnect_alice (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-#if VERBOSE
- printf ("Alice is leaving.\n");
-#endif
- if (is_p2p)
- stop_arm (&p2);
- GNUNET_CHAT_leave_room (alice_room);
- alice_room = NULL;
- GNUNET_SCHEDULER_cancel (kill_task);
- kill_task = GNUNET_SCHEDULER_NO_TASK;
-}
-
-
-static void
-disconnect_bob (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-#if VERBOSE
- printf ("Bod is leaving.\n");
-#endif
- if (is_p2p)
- stop_arm (&p3);
- alice_wanted.meta = NULL;
- alice_wanted.sender = &bob;
- alice_wanted.msg = NULL;
- alice_wanted.opt = 0;
- alice_wanted.next_task = &disconnect_alice;
- alice_wanted.next_task_cls = NULL;
- GNUNET_CHAT_leave_room (bob_room);
- bob_room = NULL;
-}
-
-
-static void
-disconnect_carol (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-#if VERBOSE
- printf ("Carol is leaving.\n");
-#endif
- alice_wanted.meta = NULL;
- alice_wanted.sender = &carol;
- alice_wanted.msg = NULL;
- alice_wanted.opt = 0;
- alice_wanted.next_task = &set_alice_ready;
- alice_wanted.next_task_cls = NULL;
- alice_ready = GNUNET_NO;
- bob_wanted.meta = NULL;
- bob_wanted.sender = &carol;
- bob_wanted.msg = NULL;
- bob_wanted.opt = 0;
- bob_wanted.next_task = &wait_until_all_ready;
- bob_wanted.next_task_cls = &disconnect_bob;
- bob_ready = GNUNET_YES;
- GNUNET_CHAT_leave_room (carol_room);
- carol_room = NULL;
-}
-
-
-static void
-send_from_alice_to_bob (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- uint32_t seq;
-
-#if VERBOSE
- printf ("Alice says 'Hi!' to Bob\n");
-#endif
- alice_ready = GNUNET_YES;
- bob_ready = GNUNET_NO;
- bob_wanted.meta = alice_meta;
- bob_wanted.sender = &alice;
- bob_wanted.msg = "Hi Bob!";
- bob_wanted.opt = GNUNET_CHAT_MSG_PRIVATE;
- bob_wanted.next_task = &set_bob_ready;
- bob_wanted.next_task_cls = NULL;
- /* Carol should not receive this message */
- carol_wanted.meta = NULL;
- carol_wanted.sender = NULL;
- carol_wanted.msg = NULL;
- carol_wanted.opt = 0;
- carol_wanted.next_task = NULL;
- carol_wanted.next_task_cls = NULL;
- GNUNET_CHAT_send_message (alice_room, "Hi Bob!", GNUNET_CHAT_MSG_PRIVATE,
- bob_public_key, &seq);
- finish_task =
- GNUNET_SCHEDULER_add_delayed (PM_TIMEOUT, &wait_until_all_ready,
- &disconnect_carol);
-}
-
-
-static void
-prepare_bob_for_alice_task (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- bob_wanted.meta = alice_meta;
- bob_wanted.sender = &alice;
- bob_wanted.msg = NULL;
- bob_wanted.opt = -1;
- bob_wanted.next_task = &set_bob_ready;
- bob_wanted.next_task_cls = NULL;
-}
-
-
-static void
-prepare_carol_for_alice_and_bob_task (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext
- *tc)
-{
- carol_wanted.meta = alice_meta;
- carol_wanted.sender = &alice;
- /* set alternative meta/sender since we don't know from which peer
- * notification will come first */
- carol_wanted.meta2 = bob_meta;
- carol_wanted.sender2 = &bob;
- carol_wanted.msg = NULL;
- carol_wanted.opt = -1;
- carol_wanted.next_task = &wait_until_all_ready;
- carol_wanted.next_task_cls = &send_from_alice_to_bob;
-}
-
-
-static void
-join_carol_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-#if VERBOSE
- printf ("Carol joining\n");
-#endif
- alice_wanted.meta = carol_meta;
- alice_wanted.sender = &carol;
- alice_wanted.msg = NULL;
- alice_wanted.opt = -1;
- alice_wanted.next_task = &set_alice_ready;
- alice_wanted.next_task_cls = NULL;
- alice_ready = GNUNET_NO;
- bob_wanted.meta = carol_meta;
- bob_wanted.sender = &carol;
- bob_wanted.msg = NULL;
- bob_wanted.opt = -1;
- bob_wanted.next_task = &set_bob_ready;
- bob_wanted.next_task_cls = NULL;
- bob_ready = GNUNET_NO;
- carol_wanted.next_task = &prepare_carol_for_alice_and_bob_task;
- carol_wanted.next_task_cls = NULL;
- carol_room =
- GNUNET_CHAT_join_room (is_p2p ? p3.cfg : p1.cfg, "carol", carol_meta,
- "test", -1, &join_cb, &carol_wanted, &receive_cb,
- &carol_wanted, &member_list_cb, &carol_wanted,
- NULL, NULL, &carol);
- if (NULL == carol_room)
- {
- GNUNET_SCHEDULER_cancel (kill_task);
- kill_task = GNUNET_SCHEDULER_NO_TASK;
- GNUNET_CHAT_leave_room (alice_room);
- alice_room = NULL;
- GNUNET_CHAT_leave_room (bob_room);
- bob_room = NULL;
- err = 1;
- }
-}
-
-
-static void
-join_bob_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-#if VERBOSE
- printf ("Bob joining\n");
-#endif
- alice_wanted.meta = bob_meta;
- alice_wanted.sender = &bob;
- alice_wanted.msg = NULL;
- alice_wanted.opt = -1;
- alice_wanted.next_task = &wait_until_all_ready;
- alice_wanted.next_task_cls = &join_carol_task;
- alice_ready = GNUNET_YES;
- bob_wanted.next_task = &prepare_bob_for_alice_task;
- bob_wanted.next_task_cls = NULL;
- bob_ready = GNUNET_NO;
- bob_room =
- GNUNET_CHAT_join_room (is_p2p ? p2.cfg : p1.cfg, "bob", bob_meta, "test",
- -1, &join_cb, &bob_wanted, &receive_cb,
- &bob_wanted, &member_list_cb, &bob_wanted, NULL,
- NULL, &bob);
- if (NULL == bob_room)
- {
- GNUNET_SCHEDULER_cancel (kill_task);
- kill_task = GNUNET_SCHEDULER_NO_TASK;
- GNUNET_CHAT_leave_room (alice_room);
- alice_room = NULL;
- err = 1;
- }
-}
-
-
-static void
-join_alice_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-#if VERBOSE
- printf ("Alice joining\n");
-#endif
- alice_wanted.next_task = &join_bob_task;
- alice_wanted.next_task_cls = NULL;
- alice_room =
- GNUNET_CHAT_join_room (p1.cfg, "alice", alice_meta, "test", -1, &join_cb,
- &alice_wanted, &receive_cb, &alice_wanted,
- &member_list_cb, &alice_wanted, NULL, NULL,
- &alice);
- if (NULL == alice_room)
- {
- GNUNET_SCHEDULER_cancel (kill_task);
- kill_task = GNUNET_SCHEDULER_NO_TASK;
- err = 1;
- }
-}
-
-
-static void
-run (void *cls, char *const *args, const char *cfgfile,
- const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
- if (is_p2p)
- {
- setup_peer (&p1, "test_chat_peer1.conf");
- setup_peer (&p2, "test_chat_peer2.conf");
- setup_peer (&p3, "test_chat_peer3.conf");
- }
- else
- setup_peer (&p1, "test_chat_data.conf");
-
- memset (&alice_wanted, 0, sizeof (struct Wanted));
- memset (&bob_wanted, 0, sizeof (struct Wanted));
- memset (&carol_wanted, 0, sizeof (struct Wanted));
- alice_wanted.me = "Alice";
- bob_wanted.me = "Bob";
- carol_wanted.me = "Carol";
- alice_meta = GNUNET_CONTAINER_meta_data_create ();
- GNUNET_CONTAINER_meta_data_insert (alice_meta, "<gnunet>",
- EXTRACTOR_METATYPE_TITLE,
- EXTRACTOR_METAFORMAT_UTF8, "text/plain",
- "Alice", strlen ("Alice") + 1);
- bob_meta = GNUNET_CONTAINER_meta_data_create ();
- GNUNET_CONTAINER_meta_data_insert (bob_meta, "<gnunet>",
- EXTRACTOR_METATYPE_TITLE,
- EXTRACTOR_METAFORMAT_UTF8, "text/plain",
- "Bob", strlen ("Bob") + 1);
- carol_meta = GNUNET_CONTAINER_meta_data_create ();
- GNUNET_CONTAINER_meta_data_insert (carol_meta, "<gnunet>",
- EXTRACTOR_METATYPE_TITLE,
- EXTRACTOR_METAFORMAT_UTF8, "text/plain",
- "Carol", strlen ("Carol") + 1);
- kill_task = GNUNET_SCHEDULER_add_delayed (KILL_TIMEOUT, &timeout_kill, NULL);
- GNUNET_SCHEDULER_add_now (&join_alice_task, NULL);
-}
-
-
-int
-main (int argc, char *argv[])
-{
- char *const argvx[] = {
- "test-chat",
- "-c",
- "test_chat_data.conf",
- NULL
- };
- struct GNUNET_GETOPT_CommandLineOption options[] = {
- GNUNET_GETOPT_OPTION_END
- };
-
- GNUNET_log_setup ("test_chat",
- "WARNING",
- NULL);
- if (strstr (argv[0], "p2p") != NULL)
- {
- is_p2p = GNUNET_YES;
- }
- GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1, argvx,
- "test-chat", "nohelp", options, &run, NULL);
- stop_arm (&p1);
- GNUNET_CONTAINER_meta_data_destroy (alice_meta);
- GNUNET_CONTAINER_meta_data_destroy (bob_meta);
- GNUNET_CONTAINER_meta_data_destroy (carol_meta);
- if (is_p2p)
- {
- GNUNET_DISK_directory_remove ("/tmp/gnunet-test-chat-peer-1/");
- GNUNET_DISK_directory_remove ("/tmp/gnunet-test-chat-peer-2/");
- GNUNET_DISK_directory_remove ("/tmp/gnunet-test-chat-peer-3/");
- }
- else
- GNUNET_DISK_directory_remove ("/tmp/gnunet-test-chat/");
- return err;
-}
-
-/* end of test_chat_private.c */