gnunet_chat_lib_uml.c (6919B)
1 /* 2 This file is part of GNUnet. 3 Copyright (C) 2024--2026 GNUnet e.V. 4 5 GNUnet is free software: you can redistribute it and/or modify it 6 under the terms of the GNU Affero General Public License as published 7 by the Free Software Foundation, either version 3 of the License, 8 or (at your option) any later version. 9 10 GNUnet is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Affero General Public License for more details. 14 15 You should have received a copy of the GNU Affero General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 SPDX-License-Identifier: AGPL3.0-or-later 19 */ 20 /* 21 * @author Tobias Frisch 22 * @file gnunet_chat_lib_uml.c 23 */ 24 25 #include "gnunet/gnunet_chat_lib.h" 26 #include <gnunet/gnunet_common.h> 27 #include <gnunet/gnunet_scheduler_lib.h> 28 #include <gnunet/gnunet_time_lib.h> 29 #include <string.h> 30 31 struct GNUNET_CHAT_Tool 32 { 33 struct GNUNET_CHAT_Handle *handle; 34 struct GNUNET_SCHEDULER_Task *task; 35 char *account_name; 36 char *group_name; 37 char *contact_name; 38 char *secret; 39 bool quit; 40 }; 41 42 static enum GNUNET_GenericReturnValue 43 accounts_iterate (void *cls, 44 struct GNUNET_CHAT_Handle *handle, 45 struct GNUNET_CHAT_Account *account) 46 { 47 struct GNUNET_CHAT_Tool *tool = cls; 48 49 const char *account_name = GNUNET_CHAT_account_get_name(account); 50 51 if (0 == strcmp(tool->account_name, account_name)) 52 { 53 GNUNET_CHAT_connect( 54 tool->handle, 55 account, 56 tool->secret, 57 tool->secret? strlen(tool->secret) : 0 58 ); 59 60 return GNUNET_NO; 61 } 62 63 return GNUNET_YES; 64 } 65 66 static void 67 idle (void *cls) 68 { 69 struct GNUNET_CHAT_Tool *tool = cls; 70 71 tool->task = NULL; 72 tool->quit = true; 73 74 GNUNET_CHAT_stop(tool->handle); 75 } 76 77 static enum GNUNET_GenericReturnValue 78 chat_message (void *cls, 79 struct GNUNET_CHAT_Context *context, 80 struct GNUNET_CHAT_Message *message) 81 { 82 struct GNUNET_CHAT_Tool *tool = cls; 83 84 if (tool->task) 85 { 86 GNUNET_SCHEDULER_cancel(tool->task); 87 tool->task = NULL; 88 } 89 90 const char *kind_name = "UNKNOWN"; 91 enum GNUNET_CHAT_MessageKind kind = GNUNET_CHAT_message_get_kind( 92 message 93 ); 94 95 switch (kind) 96 { 97 case GNUNET_CHAT_KIND_WARNING: 98 kind_name = "WARNING"; 99 break; 100 case GNUNET_CHAT_KIND_REFRESH: 101 kind_name = "REFRESH"; 102 break; 103 case GNUNET_CHAT_KIND_LOGIN: 104 kind_name = "LOGIN"; 105 break; 106 case GNUNET_CHAT_KIND_LOGOUT: 107 kind_name = "LOGOUT"; 108 break; 109 case GNUNET_CHAT_KIND_CREATED_ACCOUNT: 110 kind_name = "CREATED_ACCOUNT"; 111 break; 112 case GNUNET_CHAT_KIND_DELETED_ACCOUNT: 113 kind_name = "DELETED_ACCOUNT"; 114 break; 115 case GNUNET_CHAT_KIND_UPDATE_ACCOUNT: 116 kind_name = "UPDATE_ACCOUNT"; 117 break; 118 case GNUNET_CHAT_KIND_UPDATE_CONTEXT: 119 kind_name = "UPDATE_CONTEXT"; 120 break; 121 case GNUNET_CHAT_KIND_JOIN: 122 kind_name = "JOIN"; 123 break; 124 case GNUNET_CHAT_KIND_LEAVE: 125 kind_name = "LEAVE"; 126 break; 127 case GNUNET_CHAT_KIND_CONTACT: 128 kind_name = "CONTACT"; 129 break; 130 case GNUNET_CHAT_KIND_INVITATION: 131 kind_name = "INVITATION"; 132 break; 133 case GNUNET_CHAT_KIND_TEXT: 134 kind_name = "TEXT"; 135 break; 136 case GNUNET_CHAT_KIND_FILE: 137 kind_name = "FILE"; 138 break; 139 case GNUNET_CHAT_KIND_DELETION: 140 kind_name = "DELETION"; 141 break; 142 case GNUNET_CHAT_KIND_TAG: 143 kind_name = "TAG"; 144 break; 145 case GNUNET_CHAT_KIND_ATTRIBUTES: 146 kind_name = "ATTRIBUTES"; 147 break; 148 case GNUNET_CHAT_KIND_SHARED_ATTRIBUTES: 149 kind_name = "SHARED_ATTRIBUTES"; 150 break; 151 default: 152 break; 153 } 154 155 const struct GNUNET_CHAT_Group *group = GNUNET_CHAT_context_get_group(context); 156 const struct GNUNET_CHAT_Contact *contact = GNUNET_CHAT_context_get_contact(context); 157 158 bool ignore = true; 159 160 if (group) 161 { 162 const char *group_name = GNUNET_CHAT_group_get_name(group); 163 164 if ((group_name) && (tool->group_name) && (0 == strcmp(tool->group_name, group_name))) 165 ignore = false; 166 } 167 168 if (contact) 169 { 170 const char *contact_name = GNUNET_CHAT_contact_get_name(contact); 171 172 if ((contact_name) && (tool->contact_name) && (0 == strcmp(tool->contact_name, contact_name))) 173 ignore = false; 174 } 175 176 if (!ignore) 177 { 178 const struct GNUNET_CHAT_Contact *sender = GNUNET_CHAT_message_get_sender(message); 179 const struct GNUNET_CHAT_Contact *recipient = GNUNET_CHAT_message_get_recipient(message); 180 181 const char *sender_name = GNUNET_CHAT_contact_get_name(sender); 182 const char *text = GNUNET_CHAT_message_get_text(message); 183 184 printf( 185 "%llx -> %llx: %s", 186 (unsigned long long) sender, 187 (unsigned long long) recipient, 188 kind_name 189 ); 190 191 if (sender_name) 192 printf("\\n%s", sender_name); 193 194 if (text) 195 printf("\\n%s", text); 196 197 printf("\n"); 198 } 199 200 if (GNUNET_CHAT_KIND_REFRESH == kind) 201 GNUNET_CHAT_iterate_accounts( 202 tool->handle, 203 accounts_iterate, 204 tool 205 ); 206 207 if ((!(tool->quit)) && (!(tool->task))) 208 tool->task = GNUNET_SCHEDULER_add_delayed_with_priority( 209 GNUNET_TIME_relative_get_second_(), 210 GNUNET_SCHEDULER_PRIORITY_IDLE, 211 idle, 212 tool 213 ); 214 215 return GNUNET_YES; 216 } 217 218 static void 219 run (void *cls, 220 char* const* args, 221 const char *cfgfile, 222 const struct GNUNET_CONFIGURATION_Handle *cfg) 223 { 224 struct GNUNET_CHAT_Tool *tool = cls; 225 226 if (!(tool->account_name)) 227 return; 228 229 tool->handle = GNUNET_CHAT_start( 230 cfg, 231 chat_message, 232 tool 233 ); 234 } 235 236 int 237 main (int argc, 238 char* const* argv) 239 { 240 struct GNUNET_CHAT_Tool tool; 241 memset(&tool, 0, sizeof(tool)); 242 243 const struct GNUNET_OS_ProjectData *data; 244 data = GNUNET_OS_project_data_gnunet (); 245 246 struct GNUNET_GETOPT_CommandLineOption options[] = { 247 GNUNET_GETOPT_option_string( 248 'a', 249 "account", 250 "ACCOUNT_NAME", 251 "name of account to read messages from", 252 &(tool.account_name) 253 ), 254 GNUNET_GETOPT_option_string( 255 'c', 256 "contact", 257 "CONTACT_NAME", 258 "name of contact chat to read messages from", 259 &(tool.contact_name) 260 ), 261 GNUNET_GETOPT_option_string( 262 'g', 263 "group", 264 "GROUP_NAME", 265 "name of group chat to read messages from", 266 &(tool.group_name) 267 ), 268 GNUNET_GETOPT_option_string( 269 'S', 270 "secret", 271 "SECRET", 272 "storage secret for local keys", 273 &(tool.secret) 274 ), 275 GNUNET_GETOPT_OPTION_END 276 }; 277 278 printf("@startuml\n"); 279 280 enum GNUNET_GenericReturnValue result = GNUNET_PROGRAM_run( 281 data, 282 argc, 283 argv, 284 "libgnunetchat_uml", 285 gettext_noop("A tool to debug the Messenger service of GNUnet."), 286 options, 287 &run, 288 &tool 289 ); 290 291 printf("@enduml\n"); 292 293 return GNUNET_OK == result? 0 : 1; 294 }