GNUnet  0.11.x
gnunet-service-namecache.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2012, 2013 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 
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_dnsparser_lib.h"
33 #include "gnunet_signatures.h"
34 #include "namecache.h"
35 
36 #define LOG_STRERROR_FILE(kind, syscall, \
37  filename) GNUNET_log_from_strerror_file (kind, "util", \
38  syscall, \
39  filename)
40 
41 
46 {
51 
56 };
57 
58 
62 static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
63 
68 
73 
77 static char *db_lib_name;
78 
79 
85 static void
87 {
89  "Stopping namecache service\n");
90  GNUNET_break (NULL ==
92  GSN_database));
94  db_lib_name = NULL;
95  if (NULL != statistics)
96  {
97  GNUNET_STATISTICS_destroy (statistics,
98  GNUNET_NO);
99  statistics = NULL;
100  }
101 }
102 
103 
112 static void
115  void *app_ctx)
116 {
117  struct NamecacheClient *nc = app_ctx;
118 
120  "Client %p disconnected\n",
121  client);
122  GNUNET_free (nc);
123 }
124 
125 
134 static void *
135 client_connect_cb (void *cls,
137  struct GNUNET_MQ_Handle *mq)
138 {
139  struct NamecacheClient *nc;
140 
142  "Client %p connected\n",
143  client);
144  nc = GNUNET_new (struct NamecacheClient);
145  nc->client = client;
146  nc->mq = mq;
147  return nc;
148 }
149 
150 
156 {
161 
165  uint32_t request_id;
166 
170  int status;
171 };
172 
173 
180 static void
182  const struct GNUNET_GNSRECORD_Block *block)
183 {
184  struct LookupBlockContext *lnc = cls;
185  struct GNUNET_MQ_Envelope *env;
186  struct LookupBlockResponseMessage *r;
187  size_t esize;
188  size_t bsize;
189 
190  bsize = ntohl (block->purpose.size);
191  if (bsize <
192  (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof(struct
194  {
196  "Malformed block.");
197  lnc->status = GNUNET_SYSERR;
198  return;
199  }
200  esize = ntohl (block->purpose.size)
201  - sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
202  - sizeof(struct GNUNET_TIME_AbsoluteNBO);
203  env = GNUNET_MQ_msg_extra (r,
204  esize,
206  r->gns_header.r_id = htonl (lnc->request_id);
207  r->expire = block->expiration_time;
208  r->signature = block->signature;
209  r->derived_key = block->derived_key;
210  GNUNET_memcpy (&r[1],
211  &block[1],
212  esize);
213  GNUNET_STATISTICS_update (statistics,
214  "blocks found in cache",
215  1,
216  GNUNET_NO);
218  "Sending NAMECACHE_LOOKUP_BLOCK_RESPONSE message with expiration time %s\n",
221  GNUNET_MQ_send (lnc->nc->mq,
222  env);
223 }
224 
225 
232 static void
234  const struct LookupBlockMessage *ln_msg)
235 {
236  struct NamecacheClient *nc = cls;
237  struct GNUNET_MQ_Envelope *env;
238  struct LookupBlockContext lnc;
239  struct LookupBlockResponseMessage *zir_end;
240  int ret;
241 
243  "Received NAMECACHE_LOOKUP_BLOCK message\n");
244  GNUNET_STATISTICS_update (statistics,
245  "blocks looked up",
246  1,
247  GNUNET_NO);
248  lnc.request_id = ntohl (ln_msg->gns_header.r_id);
249  lnc.nc = nc;
250  lnc.status = GNUNET_OK;
251  if (GNUNET_SYSERR ==
252  (ret = GSN_database->lookup_block (GSN_database->cls,
253  &ln_msg->query,
255  &lnc)))
256  {
257  /* internal error (in database plugin); might be best to just hang up on
258  plugin rather than to signal that there are 'no' results, which
259  might also be false... */
260  GNUNET_break (0);
262  return;
263  }
264  if ((0 == ret) || (GNUNET_SYSERR == lnc.status))
265  {
266  /* no records match at all, generate empty response */
268  "Sending empty NAMECACHE_LOOKUP_BLOCK_RESPONSE message\n");
269  env = GNUNET_MQ_msg (zir_end,
271  zir_end->gns_header.r_id = ln_msg->gns_header.r_id;
272  GNUNET_MQ_send (nc->mq,
273  env);
274  }
276 }
277 
278 
286 static int
287 check_block_cache (void *cls,
288  const struct BlockCacheMessage *rp_msg)
289 {
290  return GNUNET_OK;
291 }
292 
293 
300 static void
302  const struct BlockCacheMessage *rp_msg)
303 {
304  struct NamecacheClient *nc = cls;
305  struct GNUNET_MQ_Envelope *env;
306  struct BlockCacheResponseMessage *rpr_msg;
307  struct GNUNET_GNSRECORD_Block *block;
308  size_t esize;
309  int res;
310 
311  GNUNET_STATISTICS_update (statistics,
312  "blocks cached",
313  1,
314  GNUNET_NO);
315  esize = ntohs (rp_msg->gns_header.header.size) - sizeof(struct
317  block = GNUNET_malloc (sizeof(struct GNUNET_GNSRECORD_Block) + esize);
318  block->signature = rp_msg->signature;
319  block->derived_key = rp_msg->derived_key;
320  block->purpose.size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
321  + sizeof(struct GNUNET_TIME_AbsoluteNBO)
322  + esize);
323  block->expiration_time = rp_msg->expire;
325  "Received NAMECACHE_BLOCK_CACHE message with expiration time %s\n",
328  GNUNET_memcpy (&block[1],
329  &rp_msg[1],
330  esize);
331  res = GSN_database->cache_block (GSN_database->cls,
332  block);
333  GNUNET_free (block);
334  env = GNUNET_MQ_msg (rpr_msg,
336  rpr_msg->gns_header.r_id = rp_msg->gns_header.r_id;
337  rpr_msg->op_result = htonl (res);
338  GNUNET_MQ_send (nc->mq,
339  env);
341 }
342 
343 
351 static void
352 run (void *cls,
353  const struct GNUNET_CONFIGURATION_Handle *cfg,
355 {
356  char *database;
357 
359  "Starting namecache service\n");
360  GSN_cfg = cfg;
361 
362  /* Loading database plugin */
363  if (GNUNET_OK !=
365  "namecache",
366  "database",
367  &database))
369  "No database backend configured\n");
370 
372  "libgnunet_plugin_namecache_%s",
373  database);
374  GSN_database = GNUNET_PLUGIN_load (db_lib_name,
375  (void *) GSN_cfg);
376  GNUNET_free (database);
377  if (NULL == GSN_database)
378  {
380  "Could not load database backend `%s'\n",
381  db_lib_name);
383  NULL);
384  return;
385  }
386  statistics = GNUNET_STATISTICS_create ("namecache",
387  cfg);
388 
389  /* Configuring server handles */
391  NULL);
392 }
393 
394 
399  ("namecache",
401  &run,
404  NULL,
405  GNUNET_MQ_hd_fixed_size (lookup_block,
407  struct LookupBlockMessage,
408  NULL),
409  GNUNET_MQ_hd_var_size (block_cache,
411  struct BlockCacheMessage,
412  NULL),
414 
415 
416 /* end of gnunet-service-namecache.c */
#define GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE
Service to client: result of block lookup.
#define GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE_RESPONSE
Service to client: result of block cache request.
Lookup a block in the namecache.
Definition: namecache.h:58
struct GNUNET_TIME_AbsoluteNBO expiration_time
Expiration time of the block.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
#define GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE
Client to service: cache a block.
void * cls
Closure to pass to all plugin functions.
struct GNUNET_CRYPTO_EcdsaSignature signature
Signature.
Definition: namecache.h:90
Lookup response.
Definition: namecache.h:75
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:673
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
Add a client to our list of active clients.
struct GNUNET_MQ_Handle * mq
The message queue to talk to client.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
Called whenever a client is disconnected.
struct GNUNET_CRYPTO_EcdsaPublicKey derived_key
Derived public key.
Definition: namecache.h:124
Handle to a service.
Definition: service.c:116
Context for name lookups passed from handle_lookup_block to handle_lookup_block_it as closure...
Response to a request to cache a block.
Definition: namecache.h:133
struct GNUNET_MessageHeader header
header.type will be GNUNET_MESSAGE_TYPE_NAMECACHE_* header.size will be message size ...
Definition: namecache.h:46
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1300
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
struct GNUNET_NAMECACHE_Header gns_header
Type will be GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK.
Definition: namecache.h:63
static void handle_lookup_block_it(void *cls, const struct GNUNET_GNSRECORD_Block *block)
A GNUNET_NAMECACHE_BlockCallback for name lookups in handle_lookup_block.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
static void handle_block_cache(void *cls, const struct BlockCacheMessage *rp_msg)
Handles a GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE message.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
#define GNUNET_NO
Definition: gnunet_common.h:78
static char * db_lib_name
Name of the database plugin.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct GNUNET_SERVICE_Client * client
The client.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
Information we have in an encrypted block with record data (i.e.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
Handle for the service.
Time for absolute time used by GNUnet, in microseconds and in network byte order. ...
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
uint32_t request_id
Operation id for the name lookup.
#define GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK
Client to service: lookup block.
void * GNUNET_PLUGIN_unload(const char *library_name, void *arg)
Unload plugin (runs the "done" callback and returns whatever "done" returned).
Definition: plugin.c:256
Handle to a client that is connected to a service.
Definition: service.c:250
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
int(* cache_block)(void *cls, const struct GNUNET_GNSRECORD_Block *block)
Cache a block in the datastore.
A namecache client.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
Cache a record in the namecache.
Definition: namecache.h:104
static struct GNUNET_STATISTICS_Handle * statistics
Handle to the statistics service.
static struct GNUNET_NAMECACHE_PluginFunctions * GSN_database
Database handle.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
int(* lookup_block)(void *cls, const struct GNUNET_HashCode *query, GNUNET_NAMECACHE_BlockCallback iter, void *iter_cls)
Get the block for a particular zone and label in the datastore.
static void handle_lookup_block(void *cls, const struct LookupBlockMessage *ln_msg)
Handles a GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK message.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1280
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!)...
static unsigned int bsize
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2324
static int res
struct GNUNET_NAMECACHE_Header gns_header
Type will be GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE_RESPONSE.
Definition: namecache.h:138
int GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
struct GNUNET_NAMECACHE_Header gns_header
Type will be GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE.
Definition: namecache.h:80
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static struct GNUNET_PEERINFO_NotifyContext * nc
Iterator context.
struct GNUNET_TIME_AbsoluteNBO expire
Expiration time.
Definition: namecache.h:114
static int check_block_cache(void *cls, const struct BlockCacheMessage *rp_msg)
Check a GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE message.
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
struct returned by the initialization function of the plugin
Handle to a message queue.
Definition: mq.c:85
struct GNUNET_CRYPTO_EcdsaSignature signature
Signature of the block.
struct GNUNET_HashCode query
The query.
Definition: namecache.h:68
static const struct GNUNET_CONFIGURATION_Handle * GSN_cfg
Configuration handle.
configuration data
Definition: configuration.c:85
struct GNUNET_CRYPTO_EcdsaPublicKey derived_key
Derived public key.
Definition: namecache.h:95
uint32_t r_id
Request ID in NBO.
Definition: namecache.h:51
static void cleanup_task(void *cls)
Task run during shutdown.
#define GNUNET_log(kind,...)
GNUNET_SERVICE_MAIN("namecache", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_fixed_size(lookup_block, GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK, struct LookupBlockMessage, NULL), GNUNET_MQ_hd_var_size(block_cache, GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE, struct BlockCacheMessage, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
struct GNUNET_TIME_AbsoluteNBO expire
Expiration time.
Definition: namecache.h:85
void * GNUNET_PLUGIN_load(const char *library_name, void *arg)
Setup plugin (runs the "init" callback and returns whatever "init" returned).
Definition: plugin.c:207
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:353
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:742
struct GNUNET_CRYPTO_EcdsaSignature signature
Signature.
Definition: namecache.h:119
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_SERVICE_Handle *service)
Process namecache requests.
int32_t op_result
GNUNET_OK on success, GNUNET_SYSERR error
Definition: namecache.h:143
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Number of bytes signed; also specifies the number of bytes of encrypted data that follow...
struct NamecacheClient * nc
The client to send the response to.
common internal definitions for namecache service
struct GNUNET_CRYPTO_EcdsaPublicKey derived_key
Derived key used for signing; hash of this is the query.
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2243
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_NAMECACHE_Header gns_header
Type will be GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE.
Definition: namecache.h:109