*/
/**
- * @file chat/gnunet-service-caht.c
- * @brief program that tracks template
+ * @file chat/gnunet-service-chat.c
+ * @brief service providing chat functionality
* @author Christian Grothoff
* @author Vitaly Minko
*/
#include "gnunet_signatures.h"
#include "chat.h"
-#define DEBUG_CHAT_SERVICE GNUNET_YES
+#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 QUEUE_SIZE 16
+#define MAX_ANONYMOUS_MSG_LIST_LENGTH 16
/**
};
+/**
+ * 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.
+ */
+ GNUNET_HashCode hash;
+
+};
+
/**
* Handle to the core service (NULL until we've connected to it).
*/
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 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.
* @return number of bytes written to buf
*/
static size_t
-transmit_message_notification_to_peer (void *cls,
- size_t size,
- void *buf)
+transmit_message_notification_to_peer (void *cls, size_t size, void *buf)
{
struct P2PReceiveNotificationMessage *my_msg = cls;
struct P2PReceiveNotificationMessage *m = buf;
#if DEBUG_CHAT_SERVICE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Transmitting P2P message notification\n");
+ "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;
/**
* Ask to send a message notification to the peer.
*/
-static void
-send_message_noficiation (void *cls,
- const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+static int
+send_message_noficiation (void *cls, const GNUNET_HashCode * key, void *value)
{
struct P2PReceiveNotificationMessage *msg = cls;
+ struct ConnectedPeer *cp = value;
+ struct GNUNET_PeerIdentity pid;
struct P2PReceiveNotificationMessage *my_msg;
- struct GNUNET_CORE_TransmitHandle *th;
- if (NULL == peer)
- GNUNET_free (msg);
- else
- {
+ GNUNET_PEER_resolve (cp->pid, &pid);
#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending message notification to `%s'\n", GNUNET_i2s (peer));
+ 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));
- th = GNUNET_CORE_notify_transmit_ready (core,
- 1,
- MAX_TRANSMIT_DELAY,
- peer,
- ntohs (msg->header.size),
- &transmit_message_notification_to_peer,
- my_msg);
- GNUNET_assert (NULL != th);
- }
+ 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;
}
* @param message the actual message
*/
static void
-handle_transmit_request (void *cls,
- struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
+handle_transmit_request (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
{
static GNUNET_HashCode all_zeros;
const struct TransmitRequestMessage *trmsg;
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))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed message: wrong size\n");
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
+ {
+ 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);
- 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");
+ 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;
- }
+ 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.size =
+ htons (sizeof (struct ReceiveNotificationMessage) + 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;
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 (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 (GNUNET_HashCode)))
{
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");
+ "Malformed message: private, but no target\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);
- if (0 == (ntohl (trmsg->msg_options) & GNUNET_CHAT_MSG_ANONYMOUS))
- rnmsg->sender = pos->id;
- else
- memset (&rnmsg->sender, 0, sizeof (GNUNET_HashCode));
- if (priv_msg)
+ memcpy (&rnmsg[1], encrypted_msg, msg_len);
+ target = client_list_head;
+ while ((NULL != target) &&
+ (0 !=
+ memcmp (&target->id, &trmsg->target, sizeof (GNUNET_HashCode))))
+ target = target->next;
+ if (NULL == target)
{
-#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 (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 (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;
- }
+ 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;
}
- else
+ if (GNUNET_SYSERR ==
+ GNUNET_CRYPTO_rsa_encrypt (&key,
+ sizeof (struct GNUNET_CRYPTO_AesSessionKey),
+ &target->public_key, &rnmsg->encrypted_key))
{
- memcpy (&rnmsg[1], &trmsg[1], msg_len);
+ 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");
+ 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 ((0 == strcmp (room, pos->room)) &&
- (NULL != pos->client) &&
- (pos->client != client))
- {
- if (((!priv_msg) ||
- (0 == memcmp (&trmsg->target,
- &pos->id,
- sizeof (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 (((!is_priv) ||
+ (0 == memcmp (&trmsg->target, &pos->id, sizeof (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");
+ "Broadcasting message to neighbour peers\n");
#endif
- 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)
+ 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));
+ memcpy (&p2p_rnmsg->encrypted_key, &rnmsg->encrypted_key,
+ sizeof (struct GNUNET_CRYPTO_RsaEncryptedData));
}
- else
- {
+ else
memcpy (&p2p_rnmsg[1], &trmsg[1], msg_len);
- }
- GNUNET_CORE_iterate_peers (cfg,
- &send_message_noficiation,
- p2p_rnmsg);
+ }
+ 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);
}
* @return number of bytes written to buf
*/
static size_t
-transmit_join_notification_to_peer (void *cls,
- size_t size,
- void *buf)
+transmit_join_notification_to_peer (void *cls, size_t size, void *buf)
{
struct ChatClient *entry = cls;
struct P2PJoinNotificationMessage *m = buf;
char *roomptr;
#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Transmitting P2P join notification\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting P2P join notification\n");
#endif
room_len = strlen (entry->room);
meta_len = entry->meta_len;
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);
/**
* Ask to send a join notification to the peer.
*/
-static void
-send_join_noficiation (void *cls,
- const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+static int
+send_join_noficiation (void *cls, const GNUNET_HashCode * key, void *value)
{
struct ChatClient *entry = cls;
- struct GNUNET_CORE_TransmitHandle *th;
+ struct ConnectedPeer *cp = value;
+ struct GNUNET_PeerIdentity pid;
size_t msg_size;
- if (NULL != peer)
- {
+ GNUNET_PEER_resolve (cp->pid, &pid);
#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending join notification to `%s'\n", GNUNET_i2s (peer));
+ 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;
- th = GNUNET_CORE_notify_transmit_ready (core,
- 1,
- MAX_TRANSMIT_DELAY,
- peer,
- msg_size,
- &transmit_join_notification_to_peer,
- entry);
- GNUNET_assert (NULL != th);
- }
+ 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;
}
* @param message the actual message
*/
static void
-handle_join_request (void *cls,
- struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
+handle_join_request (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
{
const struct JoinRequestMessage *jrmsg;
char *room_name;
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;
- }
+ {
+ 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;
+ 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);
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);
- }
+ {
+ 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);
+ 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");
+ "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);
+ 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 (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 (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");
+ "Broadcasting join notification to neighbour peers\n");
#endif
- GNUNET_CORE_iterate_peers (cfg,
- &send_join_noficiation,
- new_entry);
+ GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
+ &send_join_noficiation, new_entry);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
GNUNET_free (jnmsg);
}
* @return number of bytes written to buf
*/
static size_t
-transmit_confirmation_receipt_to_peer (void *cls,
- size_t size,
- void *buf)
+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));
+ "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;
/**
* Ask to send a confirmation receipt to the peer.
*/
-static void
-send_confirmation_receipt (void *cls,
- const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+static int
+send_confirmation_receipt (void *cls, const GNUNET_HashCode * key, void *value)
{
struct P2PConfirmationReceiptMessage *receipt = cls;
+ struct ConnectedPeer *cp = value;
+ struct GNUNET_PeerIdentity pid;
struct P2PConfirmationReceiptMessage *my_receipt;
- struct GNUNET_CORE_TransmitHandle *th;
size_t msg_size;
- if (NULL == peer)
- GNUNET_free (receipt);
- else
- {
+ GNUNET_PEER_resolve (cp->pid, &pid);
#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending confirmation receipt to `%s'\n", GNUNET_i2s (peer));
+ 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));
- th = GNUNET_CORE_notify_transmit_ready (core,
- 1,
- MAX_TRANSMIT_DELAY,
- peer,
- msg_size,
- &transmit_confirmation_receipt_to_peer,
- my_receipt);
- GNUNET_assert (NULL != th);
- }
+ 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;
}
* @param message the actual message
*/
static void
-handle_acknowledge_request (void *cls,
- struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
+handle_acknowledge_request (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
{
const struct ConfirmationReceiptMessage *receipt;
struct ConfirmationReceiptMessage *crmsg;
receipt = (const struct ConfirmationReceiptMessage *) message;
author = client_list_head;
while ((NULL != author) &&
- (0 != memcmp (&receipt->author,
- &author->id,
- sizeof (GNUNET_HashCode))))
+ (0 !=
+ memcmp (&receipt->author, &author->id, sizeof (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;
- }
+ {
+ 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 (GNUNET_HashCode))))
+ (0 !=
+ memcmp (&receipt->target, &target->id, sizeof (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;
- }
+ {
+ 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++;
+ {
+ 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);
+ 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->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_CORE_iterate_peers (cfg,
- &send_confirmation_receipt,
- p2p_crmsg);
- }
+ 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");
+ 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 (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");
+ 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);
- }
+ 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);
}
* @return number of bytes written to buf
*/
static size_t
-transmit_leave_notification_to_peer (void *cls,
- size_t size,
- void *buf)
+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");
+ 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);
- m->reserved = htons (0);
+ 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 void
-send_leave_noficiation (void *cls,
- const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+static int
+send_leave_noficiation (void *cls, const GNUNET_HashCode * key, void *value)
{
struct ChatClient *entry = cls;
- struct GNUNET_CORE_TransmitHandle *th;
+ struct ConnectedPeer *cp = value;
+ struct GNUNET_PeerIdentity pid;
struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key;
size_t msg_size;
- if (NULL == peer)
- {
- GNUNET_free (entry->room);
- GNUNET_free_non_null (entry->member_info);
- GNUNET_free (entry);
- }
- else
- {
+ GNUNET_PEER_resolve (cp->pid, &pid);
#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending leave notification to `%s'\n", GNUNET_i2s (peer));
+ 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));
- th = GNUNET_CORE_notify_transmit_ready (core,
- 1,
- MAX_TRANSMIT_DELAY,
- peer,
- msg_size,
- &transmit_leave_notification_to_peer,
- public_key);
- GNUNET_assert (NULL != th);
- }
+ 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;
}
* @param client identification of the client
*/
static void
-handle_client_disconnect (void *cls,
- struct GNUNET_SERVER_Client *client)
+handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
{
struct ChatClient *entry;
struct ChatClient *pos;
pos = client_list_head;
prev = NULL;
while ((NULL != pos) && (pos->client != client))
- {
- prev = pos;
- pos = pos->next;
- }
+ {
+ 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");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "No such client. There is nothing to do\n");
#endif
- return;
- }
+ return;
+ }
if (NULL == prev)
client_list_head = pos->next;
else
entry = client_list_head;
#if DEBUG_CHAT_SERVICE
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Notifying local room members that the client has disconnected\n");
+ "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))
{
- 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;
+ 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");
+ "Broadcasting leave notification to neighbour peers\n");
#endif
- GNUNET_CORE_iterate_peers (cfg,
- &send_leave_noficiation,
- pos);
+ GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
+ &send_leave_noficiation, pos);
+ GNUNET_free (pos->room);
+ GNUNET_free_non_null (pos->member_info);
+ GNUNET_free (pos);
}
* @param other the other peer involved
* @param message the actual message
* @param atsi performance information
+ * @param atsi_count number of entries in atsi
* @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 GNUNET_TRANSPORT_ATS_Information *atsi)
+ const struct GNUNET_PeerIdentity *other,
+ const struct GNUNET_MessageHeader *message,
+ const struct GNUNET_ATS_Information *atsi,
+ unsigned int atsi_count)
{
const struct P2PJoinNotificationMessage *p2p_jnmsg;
char *room_name;
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;
- }
+ {
+ 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;
- }
+ 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);
+ sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+ &id);
entry = client_list_head;
while (NULL != entry)
+ {
+ if (0 == memcmp (&entry->id, &id, sizeof (GNUNET_HashCode)))
{
- if (0 == memcmp (&entry->id, &id, sizeof (GNUNET_HashCode)))
- {
#if DEBUG_CHAT_SERVICE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "The client has already joined. There is nothing to do\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "The client has already joined. There is nothing to do\n");
#endif
- return GNUNET_OK;
- }
- entry = entry->next;
+ return GNUNET_OK;
}
+ entry = entry->next;
+ }
meta_len =
- header_size - sizeof (struct P2PJoinNotificationMessage) - room_name_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);
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);
- }
+ {
+ 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);
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");
+ "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);
+ 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))
{
- 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;
+ 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");
+ "Broadcasting join notification to neighbour peers\n");
#endif
- GNUNET_CORE_iterate_peers (cfg,
- &send_join_noficiation,
- new_entry);
+ GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
+ &send_join_noficiation, new_entry);
GNUNET_free (jnmsg);
return GNUNET_OK;
}
* @param other the other peer involved
* @param message the actual message
* @param atsi performance information
+ * @param atsi_count number of entries in atsi
* @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 GNUNET_TRANSPORT_ATS_Information *atsi)
+ const struct GNUNET_PeerIdentity *other,
+ const struct GNUNET_MessageHeader *message,
+ const struct GNUNET_ATS_Information *atsi,
+ unsigned int atsi_count)
{
const struct P2PLeaveNotificationMessage *p2p_lnmsg;
GNUNET_HashCode id;
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);
+ sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+ &id);
pos = client_list_head;
prev = NULL;
while (NULL != pos)
- {
- if (0 == memcmp (&pos->id, &id, sizeof (GNUNET_HashCode)))
- break;
- prev = pos;
- pos = pos->next;
- }
+ {
+ if (0 == memcmp (&pos->id, &id, sizeof (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");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "No such client. There is nothing to do\n");
#endif
- return GNUNET_OK;
- }
+ 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");
+ "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.user = pos->public_key;
entry = client_list_head;
while (NULL != entry)
+ {
+ if (0 == strcmp (pos->room, entry->room) && (NULL != entry->client))
{
- 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;
+ 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");
+ "Broadcasting leave notification to neighbour peers\n");
#endif
- GNUNET_CORE_iterate_peers (cfg,
- &send_leave_noficiation,
- pos);
+ 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;
}
* @param other the other peer involved
* @param message the actual message
* @param atsi performance information
+ * @param atsi_count number of entries in atsi
* @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 GNUNET_TRANSPORT_ATS_Information *atsi)
+ const struct GNUNET_PeerIdentity *other,
+ const struct GNUNET_MessageHeader *message,
+ const struct GNUNET_ATS_Information *atsi,
+ unsigned int atsi_count)
{
const struct P2PReceiveNotificationMessage *p2p_rnmsg;
struct P2PReceiveNotificationMessage *my_p2p_rnmsg;
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))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed message: wrong size\n");
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed message: wrong size\n");
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
p2p_rnmsg = (const struct P2PReceiveNotificationMessage *) message;
- sender = client_list_head;
- while ((NULL != sender) &&
- (0 != memcmp (&sender->id,
- &p2p_rnmsg->sender,
- sizeof (GNUNET_HashCode))))
- sender = sender->next;
- if (NULL == sender)
+ 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,
- "Unknown source. Rejecting the message\n");
+ "Malformed message: wrong length of the room name\n");
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
- if (sender->msg_sequence_number >= ntohl (p2p_rnmsg->sequence_number))
+ msg_len -= room_name_len;
+ if (lookup_anonymous_message (p2p_rnmsg))
{
#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);
+ "This anonymous message has already been handled.");
#endif
return GNUNET_OK;
}
- sender->msg_sequence_number = ntohl (p2p_rnmsg->sequence_number);
- msg_len = ntohs (p2p_rnmsg->header.size) -
- sizeof (struct P2PReceiveNotificationMessage);
+ 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 (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");
+ 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.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;
- priv_msg = (0 != memcmp (&all_zeros,
- &p2p_rnmsg->target, sizeof (GNUNET_HashCode)));
- if (priv_msg)
- 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->reserved = htonl (0);
+ rnmsg->timestamp = p2p_rnmsg->timestamp;
+ is_priv =
+ (0 != memcmp (&all_zeros, &p2p_rnmsg->target, sizeof (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 ((0 == strcmp (sender->room, pos->room)) &&
- (NULL != pos->client))
- {
- if (((!priv_msg) ||
- (0 == memcmp (&p2p_rnmsg->target,
- &pos->id,
- sizeof (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_priv) ||
+ (0 ==
+ memcmp (&p2p_rnmsg->target, &pos->id, sizeof (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");
+ "Broadcasting message notification to neighbour peers\n");
#endif
my_p2p_rnmsg = GNUNET_memdup (p2p_rnmsg, ntohs (p2p_rnmsg->header.size));
- GNUNET_CORE_iterate_peers (cfg,
- &send_message_noficiation,
- my_p2p_rnmsg);
+ GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
+ &send_message_noficiation,
+ my_p2p_rnmsg);
GNUNET_free (rnmsg);
return GNUNET_OK;
}
* @param other the other peer involved
* @param message the actual message
* @param atsi performance information
+ * @param atsi_count number of entries in atsi
* @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,
- const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+handle_p2p_sync_request (void *cls, const struct GNUNET_PeerIdentity *other,
+ const struct GNUNET_MessageHeader *message,
+ const struct GNUNET_ATS_Information *atsi,
+ unsigned int atsi_count)
{
struct ChatClient *entry;
struct GNUNET_CORE_TransmitHandle *th;
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");
+ "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,
- 1,
- MAX_TRANSMIT_DELAY,
- other,
- msg_size,
- &transmit_join_notification_to_peer,
- entry);
- GNUNET_assert (NULL != th);
- entry = entry->next;
- }
+ {
+ 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;
}
* @param other the other peer involved
* @param message the actual message
* @param atsi performance information
+ * @param atsi_count number of entries in atsi
* @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 GNUNET_TRANSPORT_ATS_Information *atsi)
+ const struct GNUNET_PeerIdentity *other,
+ const struct GNUNET_MessageHeader *message,
+ const struct GNUNET_ATS_Information *atsi,
+ unsigned int atsi_count)
{
const struct P2PConfirmationReceiptMessage *p2p_crmsg;
struct P2PConfirmationReceiptMessage *my_p2p_crmsg;
p2p_crmsg = (const struct P2PConfirmationReceiptMessage *) message;
target = client_list_head;
while ((NULL != target) &&
- (0 != memcmp (&target->id,
- &p2p_crmsg->target,
- sizeof (GNUNET_HashCode))))
+ (0 !=
+ memcmp (&target->id, &p2p_crmsg->target, sizeof (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;
- }
+ {
+ 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);
+ 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;
- }
+ 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 (GNUNET_HashCode))))
+ (0 !=
+ memcmp (&author->id, &p2p_crmsg->author, sizeof (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;
- }
+ {
+ 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");
+ 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_CORE_iterate_peers (cfg,
- &send_confirmation_receipt,
- my_p2p_crmsg);
- }
+ 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");
+ 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;
- }
+ 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");
+ 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);
- }
+ GNUNET_SERVER_notification_context_unicast (nc, author->client,
+ &crmsg->header, GNUNET_NO);
+ GNUNET_free (crmsg);
+ }
return GNUNET_OK;
}
* @return number of bytes written to buf
*/
static size_t
-transmit_sync_request_to_peer (void *cls,
- size_t size,
- void *buf)
+transmit_sync_request_to_peer (void *cls, size_t size, void *buf)
{
struct GNUNET_MessageHeader *m = buf;
size_t msg_size;
* @param cls closure
* @param peer peer identity this notification is about
* @param atsi performance data
+ * @param atsi_count number of entries in atsi
*/
-static void
-peer_connect_handler (void *cls,
- const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+static void
+peer_connect_handler (void *cls, const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_ATS_Information *atsi,
+ unsigned int atsi_count)
{
+ struct ConnectedPeer *cp;
struct GNUNET_CORE_TransmitHandle *th;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Peer connected: %s\n", GNUNET_i2s (peer));
if (0 == memcmp (peer, me, sizeof (struct GNUNET_PeerIdentity)))
return;
- th = GNUNET_CORE_notify_transmit_ready (core,
- 1,
- MAX_TRANSMIT_DELAY,
- peer,
- sizeof (struct GNUNET_MessageHeader),
- &transmit_sync_request_to_peer,
- NULL);
+ 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 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;
}
* @param peer peer identity this notification is about
*/
static void
-peer_disconnect_handler (void *cls,
- const struct GNUNET_PeerIdentity *peer)
+peer_disconnect_handler (void *cls, const struct GNUNET_PeerIdentity *peer)
{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Peer disconnected: %s\n", GNUNET_i2s (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 GNUNET_HashCode *) peer, NULL);
}
* @param tc unused
*/
static void
-cleanup_task (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
+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;
- }
+ {
+ GNUNET_CORE_disconnect (core);
+ core = NULL;
+ }
if (NULL != nc)
- {
- GNUNET_SERVER_notification_context_destroy (nc);
- nc = NULL;
- }
+ {
+ 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;
}
*
* @param cls closure, NULL
* @param server handle to the server for this service
- * @param identity the public identity of this peer
- * @param publicKey the public key of this peer
+ * @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,
- const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
+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;
*
* @param cls closure, NULL
* @param server the initialized server
- * @param cfg configuration to use
+ * @param c configuration to use
*/
static void
-run (void *cls,
- struct GNUNET_SERVER_Handle *server,
+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 }
- };
+ 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",
+ "DEBUG",
#else
- "WARNING",
+ "WARNING",
#endif
- NULL);
+ NULL);
cfg = c;
nc = GNUNET_SERVER_notification_context_create (server, 16);
+ connected_peers =
+ GNUNET_CONTAINER_multihashmap_create (EXPECTED_NEIGHBOUR_COUNT);
GNUNET_SERVER_add_handlers (server, handlers);
- core = GNUNET_CORE_connect (cfg,
- QUEUE_SIZE,
- NULL,
- &core_init,
- &peer_connect_handler,
- &peer_disconnect_handler,
- NULL,
- 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);
+ core =
+ GNUNET_CORE_connect (cfg, QUEUE_SIZE, 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);
}
main (int argc, char *const *argv)
{
return (GNUNET_OK ==
- GNUNET_SERVICE_run (argc,
- argv,
- "chat",
- GNUNET_SERVICE_OPTION_NONE,
- &run, NULL)) ? 0 : 1;
+ GNUNET_SERVICE_run (argc, argv, "chat", GNUNET_SERVICE_OPTION_NONE,
+ &run, NULL)) ? 0 : 1;
}
/* end of gnunet-service-chat.c */