Line data Source code
1 : /* 2 : This file is part of TALER 3 : Copyright (C) 2021 Taler Systems SA 4 : 5 : TALER is free software; you can redistribute it and/or modify it under the 6 : terms of the GNU Affero General Public License as published by the Free Software 7 : Foundation; either version 3, or (at your option) any later version. 8 : 9 : TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 : WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 : A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. 12 : You should have received a copy of the GNU Affero General Public License along with 13 : TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 14 : */ 15 : /** 16 : * @file taler-exchange-httpd_extensions.c 17 : * @brief Handle extensions (age-restriction, peer2peer) 18 : * @author Özgür Kesim 19 : */ 20 : #include "platform.h" 21 : #include <gnunet/gnunet_json_lib.h> 22 : #include "taler_dbevents.h" 23 : #include "taler-exchange-httpd_responses.h" 24 : #include "taler-exchange-httpd_extensions.h" 25 : #include "taler_json_lib.h" 26 : #include "taler_mhd_lib.h" 27 : #include "taler_extensions.h" 28 : #include <jansson.h> 29 : 30 : /** 31 : * Handler listening for extensions updates by other exchange 32 : * services. 33 : */ 34 : static struct GNUNET_DB_EventHandler *extensions_eh; 35 : 36 : /** 37 : * Function called whenever another exchange process has updated 38 : * the extensions data in the database. 39 : * 40 : * @param cls NULL 41 : * @param extra type of the extension 42 : * @param extra_size number of bytes in @a extra 43 : */ 44 : static void 45 0 : extension_update_event_cb (void *cls, 46 : const void *extra, 47 : size_t extra_size) 48 : { 49 : (void) cls; 50 : uint32_t nbo_type; 51 : enum TALER_Extension_Type type; 52 : const struct TALER_Extension *extension; 53 : 54 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO, 55 : "Received extensions update event\n"); 56 : 57 0 : if (sizeof(nbo_type) != extra_size) 58 : { 59 0 : GNUNET_break (0); 60 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 61 : "Oops, incorrect size of extra for TALER_Extension_type\n"); 62 0 : return; 63 : } 64 : 65 0 : GNUNET_assert (NULL != extra); 66 : 67 0 : nbo_type = *(uint32_t *) extra; 68 0 : type = (enum TALER_Extension_Type) ntohl (nbo_type); 69 : 70 : /* Get the corresponding extension */ 71 0 : extension = TALER_extensions_get_by_type (type); 72 0 : if (NULL == extension) 73 : { 74 0 : GNUNET_break (0); 75 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 76 : "Oops, unknown extension type: %d\n", type); 77 0 : return; 78 : } 79 : 80 : // Get the config from the database as string 81 : { 82 0 : char *config_str = NULL; 83 : enum GNUNET_DB_QueryStatus qs; 84 : json_error_t err; 85 : json_t *config; 86 : enum GNUNET_GenericReturnValue ret; 87 : 88 0 : qs = TEH_plugin->get_extension_config (TEH_plugin->cls, 89 0 : extension->name, 90 : &config_str); 91 : 92 0 : if (qs < 0) 93 : { 94 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 95 : "Couldn't get extension config\n"); 96 0 : GNUNET_break (0); 97 0 : return; 98 : } 99 : 100 : // No config found -> disable extension 101 0 : if (NULL == config_str) 102 : { 103 0 : extension->disable ((struct TALER_Extension *) extension); 104 0 : return; 105 : } 106 : 107 : // Parse the string as JSON 108 0 : config = json_loads (config_str, JSON_DECODE_ANY, &err); 109 0 : if (NULL == config) 110 : { 111 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 112 : "Failed to parse config for extension `%s' as JSON: %s (%s)\n", 113 : extension->name, 114 : err.text, 115 : err.source); 116 0 : GNUNET_break (0); 117 0 : return; 118 : } 119 : 120 : // Call the parser for the extension 121 0 : ret = extension->load_json_config ( 122 : (struct TALER_Extension *) extension, 123 : config); 124 : 125 0 : if (GNUNET_OK != ret) 126 : { 127 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 128 : "Couldn't parse configuration for extension %s from the database", 129 : extension->name); 130 0 : GNUNET_break (0); 131 : } 132 : } 133 : 134 : /* Special case age restriction: Update global flag and mask */ 135 0 : if (TALER_Extension_AgeRestriction == type) 136 : { 137 0 : TEH_age_restriction_enabled = 138 0 : TALER_extensions_age_restriction_is_enabled (); 139 : } 140 : } 141 : 142 : 143 : enum GNUNET_GenericReturnValue 144 0 : TEH_extensions_init () 145 : { 146 0 : GNUNET_assert (GNUNET_OK == 147 : TALER_extension_age_restriction_register ()); 148 : 149 : /* Set the event handler for updates */ 150 0 : struct GNUNET_DB_EventHeaderP ev = { 151 0 : .size = htons (sizeof (ev)), 152 0 : .type = htons (TALER_DBEVENT_EXCHANGE_EXTENSIONS_UPDATED), 153 : }; 154 0 : extensions_eh = TEH_plugin->event_listen (TEH_plugin->cls, 155 0 : GNUNET_TIME_UNIT_FOREVER_REL, 156 : &ev, 157 : &extension_update_event_cb, 158 : NULL); 159 0 : if (NULL == extensions_eh) 160 : { 161 0 : GNUNET_break (0); 162 0 : return GNUNET_SYSERR; 163 : } 164 : 165 : /* FIXME #7270: shall we load the extensions from the config right away? 166 : * We do have to for now, as otherwise denominations with age restriction 167 : * will not have the age mask set right upon initial generation. 168 : */ 169 0 : TALER_extensions_load_taler_config (TEH_cfg); 170 : 171 : /* Trigger the initial load of configuration from the db */ 172 0 : for (const struct TALER_Extension *it = TALER_extensions_get_head (); 173 0 : NULL != it->next; 174 0 : it = it->next) 175 0 : extension_update_event_cb (NULL, &it->type, sizeof(it->type)); 176 : 177 0 : return GNUNET_OK; 178 : } 179 : 180 : 181 : void 182 0 : TEH_extensions_done () 183 : { 184 0 : if (NULL != extensions_eh) 185 : { 186 0 : TEH_plugin->event_listen_cancel (TEH_plugin->cls, 187 : extensions_eh); 188 0 : extensions_eh = NULL; 189 : } 190 0 : } 191 : 192 : 193 : /* end of taler-exchange-httpd_extensions.c */