[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r14364 - in gnunet: . src/chat src/core src/include
From: |
gnunet |
Subject: |
[GNUnet-SVN] r14364 - in gnunet: . src/chat src/core src/include |
Date: |
Mon, 7 Feb 2011 00:27:01 +0100 |
Author: grothoff
Date: 2011-02-07 00:27:01 +0100 (Mon, 07 Feb 2011)
New Revision: 14364
Modified:
gnunet/AUTHORS
gnunet/src/chat/Makefile.am
gnunet/src/chat/chat.c
gnunet/src/chat/chat.h
gnunet/src/chat/gnunet-chat.c
gnunet/src/chat/gnunet-service-chat.c
gnunet/src/core/core.h
gnunet/src/include/gnunet_chat_service.h
Log:
more chat code from Mantis #1657
Modified: gnunet/AUTHORS
===================================================================
--- gnunet/AUTHORS 2011-02-06 23:25:56 UTC (rev 14363)
+++ gnunet/AUTHORS 2011-02-06 23:27:01 UTC (rev 14364)
@@ -8,6 +8,7 @@
Nils Durner <address@hidden>
Safey Allah Mohammed <address@hidden>
Philipp T�lke <address@hidden>
+Vitaly Minko <address@hidden>
Code contributions also came from:
Adam Warrington [ UPnP ]
Modified: gnunet/src/chat/Makefile.am
===================================================================
--- gnunet/src/chat/Makefile.am 2011-02-06 23:25:56 UTC (rev 14363)
+++ gnunet/src/chat/Makefile.am 2011-02-06 23:27:01 UTC (rev 14364)
@@ -37,3 +37,85 @@
$(top_builddir)/src/chat/libgnunetchat.la \
$(top_builddir)/src/util/libgnunetutil.la \
$(GN_LIBINTL)
+
+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 !DISABLE_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
Modified: gnunet/src/chat/chat.c
===================================================================
--- gnunet/src/chat/chat.c 2011-02-06 23:25:56 UTC (rev 14363)
+++ gnunet/src/chat/chat.c 2011-02-06 23:27:01 UTC (rev 14364)
@@ -32,12 +32,12 @@
#include "gnunet_signatures.h"
#include "chat.h"
-#define DEBUG_CHAT GNUNET_YES
+#define DEBUG_CHAT GNUNET_NO
#define NICK_IDENTITY_PREFIX ".chat_identity_"
/**
- * Handle for a (joined) chat room.
+ * Handle for a chat room.
*/
struct GNUNET_CHAT_Room
{
@@ -53,6 +53,12 @@
struct MemberList *members;
+ int is_joined;
+
+ GNUNET_CHAT_JoinCallback join_callback;
+
+ void *join_callback_cls;
+
GNUNET_CHAT_MessageCallback message_callback;
void *message_callback_cls;
@@ -221,7 +227,9 @@
struct JoinNotificationMessage *join_msg;
struct ReceiveNotificationMessage *received_msg;
struct ConfirmationReceiptMessage *receipt;
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
GNUNET_HashCode id;
+ const GNUNET_HashCode *sender;
struct GNUNET_CONTAINER_MetaData *meta;
struct GNUNET_CHAT_SendReceiptContext *src;
struct MemberList *pos;
@@ -261,11 +269,30 @@
sizeof (struct
GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
&pos->id);
GNUNET_PSEUDONYM_add (room->cfg, &pos->id, meta);
+ pos->next = room->members;
+ room->members = pos;
+ if (GNUNET_NO == room->is_joined)
+ {
+ GNUNET_CRYPTO_rsa_key_get_public (room->my_private_key, &pkey);
+ if (0 == memcmp (&join_msg->public_key,
+ &pkey,
+ sizeof (struct
GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)))
+ {
+ room->join_callback (room->join_callback_cls);
+ room->is_joined = GNUNET_YES;
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("The current user must be the the first one
joined\n"));
+ GNUNET_break (0);
+ return;
+ }
+ }
+ else
room->member_list_callback (room->member_list_callback_cls,
meta, &join_msg->public_key,
ntohl (join_msg->msg_options));
- pos->next = room->members;
- room->members = pos;
break;
case GNUNET_MESSAGE_TYPE_CHAT_LEAVE_NOTIFICATION:
#if DEBUG_CHAT
@@ -347,6 +374,13 @@
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,
@@ -354,11 +388,15 @@
sizeof (GNUNET_HashCode))))
pos = pos->next;
GNUNET_assert (NULL != pos);
+ sender = &received_msg->sender;
+ meta = pos->meta;
+ }
room->message_callback (room->message_callback_cls,
room,
- &received_msg->sender,
- pos->meta,
+ 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);
@@ -378,9 +416,7 @@
room,
ntohl (receipt->sequence_number),
GNUNET_TIME_absolute_ntoh
(receipt->timestamp),
- &receipt->target,
- &receipt->content,
- &receipt->signature);
+ &receipt->target);
break;
default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -510,8 +546,9 @@
{
#if DEBUG_CHAT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Could not transmit join request\n");
+ "Could not transmit join request, retrying...\n");
#endif
+ GNUNET_CHAT_rejoin_room (chat_room);
return 0;
}
#if DEBUG_CHAT
@@ -542,6 +579,10 @@
_("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;
}
@@ -623,6 +664,8 @@
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,
@@ -654,11 +697,32 @@
_("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;
@@ -668,10 +732,6 @@
chat_room->cfg = cfg;
chat_room->client = client;
chat_room->members = NULL;
- GNUNET_CLIENT_receive (client,
- &receive_results,
- chat_room,
- GNUNET_TIME_UNIT_FOREVER_REL);
if (GNUNET_SYSERR == GNUNET_CHAT_rejoin_room (chat_room))
{
GNUNET_CHAT_leave_room (chat_room);
@@ -717,6 +777,8 @@
msg_to_send->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_TRANSMIT_REQUEST);
msg_to_send->msg_options = htonl (smc->options);
msg_to_send->sequence_number = htonl (smc->sequence_number);
+ msg_to_send->timestamp =
+ GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
msg_to_send->reserved = htonl (0);
if (NULL == smc->receiver)
memset (&msg_to_send->target, 0, sizeof (GNUNET_HashCode));
@@ -770,13 +832,15 @@
#if DEBUG_CHAT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending a message\n");
#endif
- *sequence_number = ++room->sequence_number;
+ 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 = *sequence_number;
+ smc->sequence_number = room->sequence_number;
msg_size = strlen (message) + sizeof (struct TransmitRequestMessage);
GNUNET_CLIENT_notify_transmit_ready (room->client,
msg_size,
Modified: gnunet/src/chat/chat.h
===================================================================
--- gnunet/src/chat/chat.h 2011-02-06 23:25:56 UTC (rev 14363)
+++ gnunet/src/chat/chat.h 2011-02-06 23:27:01 UTC (rev 14364)
@@ -70,8 +70,13 @@
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.
- * TBD: Should be all zeros for anonymous.
+ * Should be all zeros for anonymous.
*/
GNUNET_HashCode sender;
@@ -122,6 +127,11 @@
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".
*/
GNUNET_HashCode target;
@@ -131,12 +141,15 @@
/**
* Receipt sent from a message receiver to the service to confirm delivery of
- * a chat message.
+ * 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
+ * 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;
@@ -351,8 +364,9 @@
/**
* Message send by one peer to another to indicate receiving of 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.
+ * 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
{
@@ -372,13 +386,23 @@
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).
*/
- uint32_t reserved GNUNET_PACKED;
+ 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
- * TBD: Should be all zeros for anonymous.
+ * Should be all zeros for anonymous.
*/
GNUNET_HashCode sender;
Modified: gnunet/src/chat/gnunet-chat.c
===================================================================
--- gnunet/src/chat/gnunet-chat.c 2011-02-06 23:25:56 UTC (rev 14363)
+++ gnunet/src/chat/gnunet-chat.c 2011-02-06 23:27:01 UTC (rev 14364)
@@ -78,6 +78,20 @@
/**
+ * Callback used for notification that we have joined the room.
+ *
+ * @param cls closure
+ * @return GNUNET_OK
+ */
+static int
+join_cb (void *cls)
+{
+ fprintf (stdout, _("Joined\n"));
+ return GNUNET_OK;
+}
+
+
+/**
* Callback used for notification about incoming messages.
*
* @param cls closure, NULL
@@ -93,11 +107,13 @@
receive_cb (void *cls,
struct GNUNET_CHAT_Room *room,
const GNUNET_HashCode *sender,
- const struct GNUNET_CONTAINER_MetaData *meta,
+ const struct GNUNET_CONTAINER_MetaData *member_info,
const char *message,
+ struct GNUNET_TIME_Absolute timestamp,
enum GNUNET_CHAT_MsgOptions options)
{
char *nick;
+ char *time;
const char *fmt;
if (NULL != sender)
@@ -109,43 +125,43 @@
{
case GNUNET_CHAT_MSG_OPTION_NONE:
case GNUNET_CHAT_MSG_ANONYMOUS:
- fmt = _("`%s' said: %s\n");
+ fmt = _("(%s) `%s' said: %s\n");
break;
case GNUNET_CHAT_MSG_PRIVATE:
- fmt = _("`%s' said to you: %s\n");
+ fmt = _("(%s) `%s' said to you: %s\n");
break;
case GNUNET_CHAT_MSG_PRIVATE | GNUNET_CHAT_MSG_ANONYMOUS:
- fmt = _("`%s' said to you: %s\n");
+ fmt = _("(%s) `%s' said to you: %s\n");
break;
case GNUNET_CHAT_MSG_AUTHENTICATED:
- fmt = _("`%s' said for sure: %s\n");
+ fmt = _("(%s) `%s' said for sure: %s\n");
break;
case GNUNET_CHAT_MSG_PRIVATE | GNUNET_CHAT_MSG_AUTHENTICATED:
- fmt = _("`%s' said to you for sure: %s\n");
+ fmt = _("(%s) `%s' said to you for sure: %s\n");
break;
case GNUNET_CHAT_MSG_ACKNOWLEDGED:
- fmt = _("`%s' was confirmed that you received: %s\n");
+ fmt = _("(%s) `%s' was confirmed that you received: %s\n");
break;
case GNUNET_CHAT_MSG_PRIVATE | GNUNET_CHAT_MSG_ACKNOWLEDGED:
- fmt = _("`%s' was confirmed that you and only you received: %s\n");
+ 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' was confirmed that you received from him or her: %s\n");
+ 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' was confirmed that you and only you received from him or her:
%s\n");
+ 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' said off the record: %s\n");
+ fmt = _("(%s) `%s' said off the record: %s\n");
break;
default:
- fmt = _("<%s> said using an unknown message type: %s\n");
+ fmt = _("(%s) <%s> said using an unknown message type: %s\n");
break;
}
- fprintf (stdout, fmt, nick, message);
+ time = GNUNET_STRINGS_absolute_time_to_string (timestamp);
+ fprintf (stdout, fmt, time, nick, message);
GNUNET_free (nick);
+ GNUNET_free (time);
return GNUNET_OK;
}
@@ -168,9 +184,7 @@
struct GNUNET_CHAT_Room *room,
uint32_t orig_seq_number,
struct GNUNET_TIME_Absolute timestamp,
- const GNUNET_HashCode *receiver,
- const GNUNET_HashCode *msg_hash,
- const struct GNUNET_CRYPTO_RsaSignature *receipt)
+ const GNUNET_HashCode *receiver)
{
char *nick;
@@ -248,18 +262,6 @@
static int
-do_transmit (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_join (const char *arg, const void *xtra)
{
char *my_name;
@@ -276,6 +278,7 @@
meta,
room_name,
-1,
+ &join_cb, NULL,
&receive_cb, NULL,
&member_list_cb, NULL,
&confirmation_cb, NULL, &me);
@@ -285,7 +288,7 @@
return GNUNET_SYSERR;
}
my_name = GNUNET_PSEUDONYM_id_to_name (cfg, &me);
- fprintf (stdout, _("Joined room `%s' as user `%s'\n"), room_name, my_name);
+ fprintf (stdout, _("Joining room `%s' as user `%s'...\n"), room_name,
my_name);
GNUNET_free (my_name);
return GNUNET_OK;
}
@@ -315,6 +318,7 @@
meta,
room_name,
-1,
+ &join_cb, NULL,
&receive_cb, NULL,
&member_list_cb, NULL,
&confirmation_cb, NULL, &me);
@@ -355,8 +359,20 @@
static int
-do_pm (const char *msg, const void *xtra)
+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;
GNUNET_HashCode uid;
GNUNET_HashCode pid;
@@ -404,7 +420,7 @@
static int
-do_transmit_sig (const char *msg, const void *xtra)
+do_send_sig (const char *msg, const void *xtra)
{
uint32_t seq;
GNUNET_CHAT_send_message (room,
@@ -416,7 +432,7 @@
static int
-do_transmit_ack (const char *msg, const void *xtra)
+do_send_ack (const char *msg, const void *xtra)
{
uint32_t seq;
GNUNET_CHAT_send_message (room,
@@ -428,6 +444,18 @@
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;
@@ -454,19 +482,24 @@
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_pm,
+ {"/msg ", &do_send_pm,
gettext_noop
("Use `/msg nickname message' to send a private message to the specified"
" user")},
- {"/notice ", &do_pm,
+ {"/notice ", &do_send_pm,
gettext_noop ("The `/notice' command is an alias for `/msg'")},
- {"/query ", &do_pm,
+ {"/query ", &do_send_pm,
gettext_noop ("The `/query' command is an alias for `/msg'")},
- {"/sig ", &do_transmit_sig,
+ {"/sig ", &do_send_sig,
gettext_noop ("Use `/sig message' to send a signed public message")},
- {"/ack ", &do_transmit_ack,
+ {"/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,
@@ -479,13 +512,9 @@
/* Add standard commands:
/whois (print metadata),
/ignore (set flag, check on receive!) */
- /* Add special commands (currently supported):
- + anonymous msgs
- + authenticated msgs
- */
/* the following three commands must be last! */
{"/", &do_unknown, NULL},
- {"", &do_transmit, NULL},
+ {"", &do_send, NULL},
{NULL, NULL, NULL},
};
@@ -615,6 +644,7 @@
meta,
room_name,
-1,
+ &join_cb, NULL,
&receive_cb, NULL,
&member_list_cb, NULL,
&confirmation_cb, NULL, &me);
@@ -628,7 +658,7 @@
return;
}
my_name = GNUNET_PSEUDONYM_id_to_name (cfg, &me);
- fprintf (stdout, _("Joined room `%s' as user `%s'\n"), room_name, my_name);
+ 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,
Modified: gnunet/src/chat/gnunet-service-chat.c
===================================================================
--- gnunet/src/chat/gnunet-service-chat.c 2011-02-06 23:25:56 UTC (rev
14363)
+++ gnunet/src/chat/gnunet-service-chat.c 2011-02-06 23:27:01 UTC (rev
14364)
@@ -33,9 +33,10 @@
#include "gnunet_signatures.h"
#include "chat.h"
-#define DEBUG_CHAT_SERVICE GNUNET_YES
+#define DEBUG_CHAT_SERVICE GNUNET_NO
#define MAX_TRANSMIT_DELAY GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS, 60)
#define QUEUE_SIZE 16
+#define MAX_ANONYMOUS_MSG_LIST_LENGTH 16
/**
@@ -93,7 +94,21 @@
};
+/**
+ * Linked list of recent anonymous messages.
+ */
+struct AnonymousMessage
+{
+ struct AnonymousMessage *next;
+ /**
+ * Hash of the message.
+ */
+ GNUNET_HashCode hash;
+
+};
+
+
/**
* Handle to the core service (NULL until we've connected to it).
*/
@@ -119,7 +134,57 @@
*/
struct GNUNET_SERVER_NotificationContext *nc = NULL;
+/**
+ * Head of the list of recent anonymous messages.
+ */
+static struct AnonymousMessage *anonymous_list_head = NULL;
+
+static void
+remember_anonymous_message (const struct P2PReceiveNotificationMessage
*p2p_rnmsg)
+{
+ static 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 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 (GNUNET_HashCode))))
+ anon_msg = anon_msg->next;
+ return (NULL != anon_msg);
+}
+
+
/**
* Transmit a message notification to the peer.
*
@@ -141,9 +206,17 @@
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);
- GNUNET_assert (NULL != buf);
memcpy (m, my_msg, msg_size);
GNUNET_free (my_msg);
return msg_size;
@@ -205,8 +278,10 @@
struct GNUNET_CRYPTO_AesSessionKey key;
char encrypted_msg[MAX_MESSAGE_LENGTH];
const char *room;
+ size_t room_len;
int msg_len;
- int priv_msg;
+ 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))
@@ -218,8 +293,8 @@
}
trmsg = (const struct TransmitRequestMessage *) message;
msg_len = ntohs (trmsg->header.size) - sizeof (struct
TransmitRequestMessage);
- priv_msg = (ntohl (trmsg->msg_options) & GNUNET_CHAT_MSG_PRIVATE) != 0;
- if (priv_msg)
+ 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");
@@ -244,7 +319,7 @@
msg_len);
rnmsg->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_MESSAGE_NOTIFICATION);
rnmsg->msg_options = trmsg->msg_options;
- rnmsg->sequence_number = trmsg->sequence_number;
+ rnmsg->timestamp = trmsg->timestamp;
pos = client_list_head;
while ((NULL != pos) && (pos->client != client))
pos = pos->next;
@@ -260,12 +335,19 @@
}
room = pos->room;
pos->msg_sequence_number = ntohl (trmsg->sequence_number);
- if (0 == (ntohl (trmsg->msg_options) & GNUNET_CHAT_MSG_ANONYMOUS))
- rnmsg->sender = pos->id;
+ is_anon = (0 != (ntohl (trmsg->msg_options) & GNUNET_CHAT_MSG_ANONYMOUS));
+ if (is_anon)
+ {
+ memset (&rnmsg->sender, 0, sizeof (GNUNET_HashCode));
+ rnmsg->sequence_number = 0;
+ }
else
- memset (&rnmsg->sender, 0, sizeof (GNUNET_HashCode));
- if (priv_msg)
{
+ 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",
@@ -323,7 +405,7 @@
(NULL != pos->client) &&
(pos->client != client))
{
- if (((!priv_msg) ||
+ if (((!is_priv) ||
(0 == memcmp (&trmsg->target,
&pos->id,
sizeof (GNUNET_HashCode)))) &&
@@ -341,16 +423,25 @@
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);
- 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;
- memcpy (&p2p_rnmsg->sender, &rnmsg->sender, sizeof (GNUNET_HashCode));
- p2p_rnmsg->target = trmsg->target;
- if (priv_msg)
+ 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,
@@ -358,9 +449,17 @@
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 = 0;
+ p2p_rnmsg->sender = rnmsg->sender;
+ p2p_rnmsg->target = trmsg->target;
+ if (is_anon)
+ remember_anonymous_message (p2p_rnmsg);
GNUNET_CORE_iterate_peers (cfg,
&send_message_noficiation,
p2p_rnmsg);
@@ -591,9 +690,17 @@
"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);
- GNUNET_assert (NULL != buf);
memcpy (buf, receipt, msg_size);
GNUNET_free (receipt);
return msg_size;
@@ -765,9 +872,17 @@
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);
- GNUNET_assert (NULL != buf);
m = buf;
m->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_P2P_LEAVE_NOTIFICATION);
m->header.size = htons (msg_size);
@@ -787,7 +902,6 @@
const struct GNUNET_TRANSPORT_ATS_Information *atsi)
{
struct ChatClient *entry = cls;
- struct GNUNET_CORE_TransmitHandle *th;
struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key;
size_t msg_size;
@@ -806,14 +920,15 @@
msg_size = sizeof (struct P2PLeaveNotificationMessage);
public_key = GNUNET_memdup (&entry->public_key,
sizeof (struct
GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
- th = GNUNET_CORE_notify_transmit_ready (core,
+ if (NULL == GNUNET_CORE_notify_transmit_ready (core,
1,
MAX_TRANSMIT_DELAY,
peer,
msg_size,
&transmit_leave_notification_to_peer,
- public_key);
- GNUNET_assert (NULL != th);
+ public_key))
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Failed to queue a leave notification\n"));
}
}
@@ -1108,8 +1223,12 @@
struct ChatClient *sender;
struct ChatClient *pos;
static GNUNET_HashCode all_zeros;
- int priv_msg;
+ 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))
@@ -1119,6 +1238,37 @@
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,
@@ -1127,10 +1277,13 @@
sender = sender->next;
if (NULL == sender)
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ /* 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");
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
+#endif
+ return GNUNET_OK;
}
if (sender->msg_sequence_number >= ntohl (p2p_rnmsg->sequence_number))
{
@@ -1138,15 +1291,19 @@
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);
+ ntohl (p2p_rnmsg->sequence_number),
+ sender->msg_sequence_number);
#endif
return GNUNET_OK;
}
sender->msg_sequence_number = ntohl (p2p_rnmsg->sequence_number);
- msg_len = ntohs (p2p_rnmsg->header.size) -
- sizeof (struct P2PReceiveNotificationMessage);
+ 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");
+ 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) +
@@ -1154,21 +1311,22 @@
rnmsg->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_MESSAGE_NOTIFICATION);
rnmsg->msg_options = p2p_rnmsg->msg_options;
rnmsg->sequence_number = p2p_rnmsg->sequence_number;
- priv_msg = (0 != memcmp (&all_zeros,
+ rnmsg->timestamp = p2p_rnmsg->timestamp;
+ is_priv = (0 != memcmp (&all_zeros,
&p2p_rnmsg->target, sizeof (GNUNET_HashCode)));
- if (priv_msg)
+ if (is_priv)
memcpy (&rnmsg->encrypted_key,
&p2p_rnmsg->encrypted_key,
sizeof (struct GNUNET_CRYPTO_RsaEncryptedData));
- memcpy (&rnmsg->sender, &p2p_rnmsg->sender, sizeof (GNUNET_HashCode));
- memcpy (&rnmsg[1], &p2p_rnmsg[1], msg_len);
+ rnmsg->sender = p2p_rnmsg->sender;
+ memcpy (&rnmsg[1], text, msg_len);
pos = client_list_head;
while (NULL != pos)
{
- if ((0 == strcmp (sender->room, pos->room)) &&
+ if ((0 == strcmp (room_name, pos->room)) &&
(NULL != pos->client))
{
- if (((!priv_msg) ||
+ if (((!is_priv) ||
(0 == memcmp (&p2p_rnmsg->target,
&pos->id,
sizeof (GNUNET_HashCode)))) &&
@@ -1182,6 +1340,8 @@
}
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");
@@ -1441,6 +1601,9 @@
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)
{
@@ -1452,6 +1615,20 @@
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;
+ }
}
Modified: gnunet/src/core/core.h
===================================================================
--- gnunet/src/core/core.h 2011-02-06 23:25:56 UTC (rev 14363)
+++ gnunet/src/core/core.h 2011-02-06 23:27:01 UTC (rev 14364)
@@ -30,7 +30,7 @@
/**
* General core debugging.
*/
-#define DEBUG_CORE GNUNET_NO
+#define DEBUG_CORE GNUNET_YES
/**
* Debugging interaction core-clients.
Modified: gnunet/src/include/gnunet_chat_service.h
===================================================================
--- gnunet/src/include/gnunet_chat_service.h 2011-02-06 23:25:56 UTC (rev
14363)
+++ gnunet/src/include/gnunet_chat_service.h 2011-02-06 23:27:01 UTC (rev
14364)
@@ -89,6 +89,14 @@
struct GNUNET_CHAT_Room;
/**
+ * Callback used for notification that we have joined the room.
+ *
+ * @param cls closure
+ * @return GNUNET_OK
+ */
+typedef int (*GNUNET_CHAT_JoinCallback) (void *cls);
+
+/**
* Callback used for notification about incoming messages.
*
* @param cls closure
@@ -96,6 +104,7 @@
* @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 when was the message sent?
* @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
@@ -105,11 +114,13 @@
const GNUNET_HashCode *sender,
const struct
GNUNET_CONTAINER_MetaData *member_info,
const char *message,
+ struct GNUNET_TIME_Absolute
timestamp,
enum GNUNET_CHAT_MsgOptions
options);
/**
* Callback used for notification that another room member has joined or left.
*
+ * @param cls closure
* @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)
@@ -129,8 +140,6 @@
* @param orig_seq_number sequence number of the original message
* @param timestamp when was the message received?
* @param receiver who is confirming the receipt?
- * @param msg_hash hash of the original message
- * @param receipt signature confirming delivery
* @return GNUNET_OK to continue, GNUNET_SYSERR to refuse processing further
* confirmations from anyone for this message
*/
@@ -138,9 +147,7 @@
struct GNUNET_CHAT_Room *room,
uint32_t orig_seq_number,
struct GNUNET_TIME_Absolute
timestamp,
- const GNUNET_HashCode *receiver,
- const GNUNET_HashCode *msg_hash,
- const struct
GNUNET_CRYPTO_RsaSignature *receipt);
+ const GNUNET_HashCode
*receiver);
/**
* Join a chat room.
@@ -153,6 +160,8 @@
* @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 which function to call when we've joined the room
+ * @param join_cls argument to callback
* @param messageCallback which function to call if a message has
* been received?
* @param message_cls argument to callback
@@ -170,6 +179,8 @@
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,
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r14364 - in gnunet: . src/chat src/core src/include,
gnunet <=