📄 messaging.c
字号:
/* This file is part of GNUnet. (C) 2008 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//** * @file applications/chat/lib/messaging.c * @brief convenience API for sending and receiving chat messages * @author Christian Grothoff * @author Nathan Evans */#include "platform.h"#include "gnunet_util.h"#include "gnunet_protocols.h"#include "gnunet_chat_lib.h"#include "gnunet_directories.h"#include "chat.h"#define NICK_IDENTITY_PREFIX ".chat_identity_"/** * Handle for a (joined) chat room. */struct GNUNET_CHAT_Room{ struct GNUNET_ClientServerConnection *sock; struct GNUNET_ThreadHandle *listen_thread; struct GNUNET_GE_Context *ectx; struct GNUNET_GC_Configuration *cfg; struct GNUNET_MetaData *member_info; char *room_name; GNUNET_RSA_PrivateKeyEncoded *my_private_key; GNUNET_CHAT_MessageCallback message_callback; void *message_callback_cls; GNUNET_CHAT_MemberListCallback member_list_callback; void *member_list_callback_cls; GNUNET_CHAT_MessageConfirmation confirmation_callback; void *confirmation_cls; int shutdown_flag; unsigned int sequence_number; unsigned int msg_options;};/** * Linked list of members in the chat room. */struct MemberList{ struct MemberList *next; /** * Description of the member. */ struct GNUNET_MetaData *meta; /** * Member ID (pseudonym). */ GNUNET_HashCode id;};static intGNUNET_CHAT_rejoin_room (struct GNUNET_CHAT_Room *chat_room){ CS_chat_MESSAGE_JoinRequest *join_msg; unsigned int size_of_join; unsigned int room_len; unsigned int meta_len; char *room; meta_len = GNUNET_meta_data_get_serialized_size (chat_room->member_info, GNUNET_YES); room_len = strlen (chat_room->room_name); size_of_join = sizeof (CS_chat_MESSAGE_JoinRequest) + meta_len + room_len + ntohs (chat_room->my_private_key->len) - sizeof (GNUNET_RSA_PrivateKeyEncoded); if (size_of_join >= GNUNET_MAX_BUFFER_SIZE - 8) return GNUNET_SYSERR; join_msg = GNUNET_malloc (size_of_join); join_msg->header.size = htons (size_of_join); join_msg->header.type = htons (GNUNET_CS_PROTO_CHAT_JOIN_REQUEST); join_msg->msg_options = htonl (chat_room->msg_options); join_msg->room_name_len = htons (room_len); join_msg->reserved = htons (0); memcpy (&join_msg->private_key, chat_room->my_private_key, ntohs (chat_room->my_private_key->len)); room = (char *) &join_msg[1]; room += ntohs (chat_room->my_private_key->len) - sizeof (GNUNET_RSA_PrivateKeyEncoded); memcpy (room, chat_room->room_name, room_len); if (GNUNET_SYSERR == GNUNET_meta_data_serialize (chat_room->ectx, chat_room->member_info, &room[room_len], meta_len, GNUNET_YES)) { GNUNET_free (join_msg); return GNUNET_SYSERR; } if (GNUNET_SYSERR == GNUNET_client_connection_write (chat_room->sock, &join_msg->header)) { GNUNET_free (join_msg); return GNUNET_SYSERR; } GNUNET_free (join_msg); return GNUNET_OK;}/** * Listen for incoming messages on this chat room. When received, * call the proper client callback. Also, support servers going * away/coming back (i.e. rejoin chat room to keep server state up to * date)... */static void *poll_thread (void *rcls){ struct GNUNET_CHAT_Room *room = rcls; GNUNET_MessageHeader *reply; CS_chat_MESSAGE_ConfirmationReceipt *receipt; CS_chat_MESSAGE_LeaveNotification *leave_msg; CS_chat_MESSAGE_JoinNotification *join_msg; CS_chat_MESSAGE_ReceiveNotification *received_msg; GNUNET_HashCode id; struct GNUNET_MetaData *meta; struct MemberList *members; struct MemberList *pos; struct MemberList *prev; unsigned int size; unsigned int meta_len; unsigned int msg_len; char *message_content; int disconnected; int malformed; int ret; disconnected = GNUNET_NO; malformed = GNUNET_NO; ret = GNUNET_OK; reply = NULL; members = NULL; while ((ret == GNUNET_OK) && (room->shutdown_flag != GNUNET_YES)) { if (malformed) { GNUNET_GE_BREAK (NULL, 0); GNUNET_client_connection_close_temporarily (room->sock); disconnected = GNUNET_YES; malformed = GNUNET_NO; } if (reply != NULL) { GNUNET_free (reply); reply = NULL; } if (disconnected) { GNUNET_thread_sleep (15 * GNUNET_CRON_SECONDS); if (GNUNET_client_connection_ensure_connected (room->sock) == GNUNET_OK) { /* send join! */ disconnected = GNUNET_NO; GNUNET_CHAT_rejoin_room (room); continue; } else break; } reply = NULL; if (GNUNET_OK != GNUNET_client_connection_read (room->sock, &reply)) { disconnected = GNUNET_YES; continue; } size = ntohs (reply->size); switch (ntohs (reply->type)) { case GNUNET_CS_PROTO_CHAT_JOIN_NOTIFICATION: if (size < sizeof (CS_chat_MESSAGE_JoinNotification)) { malformed = GNUNET_YES; continue; } join_msg = (CS_chat_MESSAGE_JoinNotification *) reply; meta_len = size - sizeof (CS_chat_MESSAGE_JoinNotification); meta = GNUNET_meta_data_deserialize (room->ectx, (const char *) &join_msg[1], meta_len); if (meta == NULL) { malformed = GNUNET_YES; continue; } pos = GNUNET_malloc (sizeof (struct MemberList)); pos->meta = meta; GNUNET_hash (&join_msg->public_key, sizeof (GNUNET_RSA_PublicKey), &pos->id); GNUNET_pseudonym_add (room->ectx, room->cfg, &pos->id, meta); room->member_list_callback (room->member_list_callback_cls, meta, &join_msg->public_key, ntohl (join_msg->msg_options)); pos->next = members; members = pos; break; case GNUNET_CS_PROTO_CHAT_LEAVE_NOTIFICATION: if (size < sizeof (CS_chat_MESSAGE_LeaveNotification)) { malformed = GNUNET_YES; continue; } leave_msg = (CS_chat_MESSAGE_LeaveNotification *) reply; room->member_list_callback (room->member_list_callback_cls, NULL, &leave_msg->user, GNUNET_CHAT_MSG_OPTION_NONE); GNUNET_hash (&leave_msg->user, sizeof (GNUNET_RSA_PublicKey), &id); prev = NULL; pos = members; while ((pos != NULL) && (0 != memcmp (&pos->id, &id, sizeof (GNUNET_HashCode)))) { prev = pos; pos = pos->next; } GNUNET_GE_ASSERT (NULL, pos != NULL); if (prev == NULL) members = pos->next; else prev->next = pos->next; GNUNET_meta_data_destroy (pos->meta); GNUNET_free (pos); break; case GNUNET_CS_PROTO_CHAT_MESSAGE_NOTIFICATION: if (size < sizeof (CS_chat_MESSAGE_ReceiveNotification)) { malformed = GNUNET_YES; continue; } received_msg = (CS_chat_MESSAGE_ReceiveNotification *) reply; msg_len = size - sizeof (CS_chat_MESSAGE_ReceiveNotification); message_content = GNUNET_malloc (msg_len + 1); memcpy (message_content, &received_msg[1], msg_len); message_content[msg_len] = '\0'; pos = members; while ((pos != NULL) && (0 != memcmp (&pos->id,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -