aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-06-15 23:46:00 +0200
committerChristian Grothoff <christian@grothoff.org>2019-06-15 23:46:00 +0200
commita99752d30c73cd5040c9da3c05da3bbc2dc1b67e (patch)
tree4319210d4664aa3354404e67911ebe771b1e43f3 /src
parentb3ddc93861a6a171eee7c855f83c7a1314f6eaf9 (diff)
downloadgnunet-a99752d30c73cd5040c9da3c05da3bbc2dc1b67e.tar.gz
gnunet-a99752d30c73cd5040c9da3c05da3bbc2dc1b67e.zip
fix gnunet-gns performance issue for many egos
Diffstat (limited to 'src')
-rw-r--r--src/gns/gns_tld_api.c88
-rw-r--r--src/identity/Makefile.am1
-rw-r--r--src/identity/gnunet-service-identity.c71
-rw-r--r--src/identity/identity.h3
-rw-r--r--src/include/gnunet_identity_service.h34
-rw-r--r--src/include/gnunet_protocols.h9
6 files changed, 140 insertions, 66 deletions
diff --git a/src/gns/gns_tld_api.c b/src/gns/gns_tld_api.c
index fa4c9c057..f36b31acf 100644
--- a/src/gns/gns_tld_api.c
+++ b/src/gns/gns_tld_api.c
@@ -72,7 +72,7 @@ struct GNUNET_GNS_LookupWithTldRequest
72 /** 72 /**
73 * Lookup an ego with the identity service. 73 * Lookup an ego with the identity service.
74 */ 74 */
75 struct GNUNET_IDENTITY_Handle *id_co; 75 struct GNUNET_IDENTITY_EgoSuffixLookup *id_co;
76 76
77 /** 77 /**
78 * Name of the longest matching ego found so far. 78 * Name of the longest matching ego found so far.
@@ -191,68 +191,37 @@ lookup_with_public_key (struct GNUNET_GNS_LookupWithTldRequest *ltr,
191 */ 191 */
192static void 192static void
193identity_zone_cb (void *cls, 193identity_zone_cb (void *cls,
194 struct GNUNET_IDENTITY_Ego *ego, 194 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
195 void **ctx, 195 const char *ego_name)
196 const char *name)
197{ 196{
198 struct GNUNET_GNS_LookupWithTldRequest *ltr = cls; 197 struct GNUNET_GNS_LookupWithTldRequest *ltr = cls;
199 struct GNUNET_CRYPTO_EcdsaPublicKey pkey; 198 struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
200 199
201 if (NULL == ego) 200 ltr->id_co = NULL;
201 if (NULL == priv)
202 { 202 {
203 if (NULL != ltr->longest_match) 203 /* no matching ego found */
204 { 204 ltr->lookup_proc (ltr->lookup_proc_cls, GNUNET_NO, 0, NULL);
205 /* Final case: TLD matches one of our egos */
206 // FIXME: eat all of the match (not just TLD!)
207 if (0 == strcmp (ltr->name, ltr->longest_match))
208 {
209 /* name matches ego name perfectly, only "@" remains */
210 strcpy (ltr->name, GNUNET_GNS_EMPTY_LABEL_AT);
211 }
212 else
213 {
214 GNUNET_assert (strlen (ltr->longest_match) < strlen (ltr->name));
215 ltr->name[strlen (ltr->name) - strlen (ltr->longest_match) - 1] = '\0';
216 }
217
218 /* if the name is of the form 'label' (and not 'label.SUBDOMAIN'), never go to the DHT */
219 GNUNET_free (ltr->longest_match);
220 ltr->longest_match = NULL;
221 if (NULL == strchr (ltr->name, (unsigned char) '.'))
222 ltr->options = GNUNET_GNS_LO_NO_DHT;
223 else
224 ltr->options = GNUNET_GNS_LO_LOCAL_MASTER;
225
226 GNUNET_IDENTITY_ego_get_public_key (ltr->longest_match_ego, &pkey);
227 GNUNET_IDENTITY_disconnect (ltr->id_co);
228 ltr->id_co = NULL;
229 lookup_with_public_key (ltr, &pkey);
230 }
231 else
232 {
233 /* no matching ego found */
234 GNUNET_IDENTITY_disconnect (ltr->id_co);
235 ltr->id_co = NULL;
236 ltr->lookup_proc (ltr->lookup_proc_cls, GNUNET_NO, 0, NULL);
237 GNUNET_GNS_lookup_with_tld_cancel (ltr);
238 }
239 return; 205 return;
240 } 206 }
241 else if (NULL != name) 207 /* Final case: TLD matches one of our egos */
208 if (0 == strcmp (ltr->name, ego_name))
242 { 209 {
243 if ((strlen (name) <= strlen (ltr->name)) && 210 /* name matches ego name perfectly, only "@" remains */
244 (0 == strcmp (name, &ltr->name[strlen (ltr->name) - strlen (name)])) && 211 strcpy (ltr->name, GNUNET_GNS_EMPTY_LABEL_AT);
245 ((strlen (name) == strlen (ltr->name)) ||
246 ('.' == ltr->name[strlen (ltr->name) - strlen (name) - 1])) &&
247 ((NULL == ltr->longest_match) ||
248 (strlen (name) > strlen (ltr->longest_match))))
249 {
250 /* found better match, update! */
251 GNUNET_free_non_null (ltr->longest_match);
252 ltr->longest_match = GNUNET_strdup (name);
253 ltr->longest_match_ego = ego;
254 }
255 } 212 }
213 else
214 {
215 GNUNET_assert (strlen (ego_name) < strlen (ltr->name));
216 ltr->name[strlen (ltr->name) - strlen (ego_name) - 1] = '\0';
217 }
218 /* if the name is of the form 'label' (and not 'label.SUBDOMAIN'), never go to the DHT */
219 if (NULL == strchr (ltr->name, (unsigned char) '.'))
220 ltr->options = GNUNET_GNS_LO_NO_DHT;
221 else
222 ltr->options = GNUNET_GNS_LO_LOCAL_MASTER;
223 GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pkey);
224 lookup_with_public_key (ltr, &pkey);
256} 225}
257 226
258 227
@@ -336,12 +305,11 @@ GNUNET_GNS_lookup_with_tld (struct GNUNET_GNS_Handle *handle,
336 } 305 }
337 GNUNET_free (dot_tld); 306 GNUNET_free (dot_tld);
338 } 307 }
339 /* FIXME: this call is still shitty slow to do the longest
340 suffix if we have thousands of egos. We should modify
341 the IDENTITY API to do the longest suffix matching
342 inside of the identity service and not do an O(n) IPC! */
343 ltr->id_co = 308 ltr->id_co =
344 GNUNET_IDENTITY_connect (ltr->gns_handle->cfg, &identity_zone_cb, ltr); 309 GNUNET_IDENTITY_ego_lookup_by_suffix (ltr->gns_handle->cfg,
310 ltr->name,
311 &identity_zone_cb,
312 ltr);
345 if (NULL == ltr->id_co) 313 if (NULL == ltr->id_co)
346 { 314 {
347 GNUNET_free (ltr->name); 315 GNUNET_free (ltr->name);
@@ -365,7 +333,7 @@ GNUNET_GNS_lookup_with_tld_cancel (struct GNUNET_GNS_LookupWithTldRequest *ltr)
365 333
366 if (NULL != ltr->id_co) 334 if (NULL != ltr->id_co)
367 { 335 {
368 GNUNET_IDENTITY_disconnect (ltr->id_co); 336 GNUNET_IDENTITY_ego_lookup_by_suffix_cancel (ltr->id_co);
369 ltr->id_co = NULL; 337 ltr->id_co = NULL;
370 } 338 }
371 if (NULL != ltr->lr) 339 if (NULL != ltr->lr)
diff --git a/src/identity/Makefile.am b/src/identity/Makefile.am
index 6e587dc86..476d981bb 100644
--- a/src/identity/Makefile.am
+++ b/src/identity/Makefile.am
@@ -43,6 +43,7 @@ libgnunet_plugin_rest_identity_la_LDFLAGS = \
43libgnunetidentity_la_SOURCES = \ 43libgnunetidentity_la_SOURCES = \
44 identity_api.c \ 44 identity_api.c \
45 identity_api_lookup.c \ 45 identity_api_lookup.c \
46 identity_api_suffix_lookup.c \
46 identity.h 47 identity.h
47libgnunetidentity_la_LIBADD = \ 48libgnunetidentity_la_LIBADD = \
48 $(top_builddir)/src/util/libgnunetutil.la \ 49 $(top_builddir)/src/util/libgnunetutil.la \
diff --git a/src/identity/gnunet-service-identity.c b/src/identity/gnunet-service-identity.c
index a675a01f0..3e92a04cd 100644
--- a/src/identity/gnunet-service-identity.c
+++ b/src/identity/gnunet-service-identity.c
@@ -378,6 +378,73 @@ handle_lookup_message (void *cls,
378 378
379 379
380/** 380/**
381 * Handler for LOOKUP message from client, sends information
382 * about ONE identity to the client immediately.
383 *
384 * @param cls unused
385 * @param message the message received
386 * @return #GNUNET_SYSERR if message was ill-formed
387 */
388static int
389check_lookup_by_suffix_message (void *cls,
390 const struct LookupMessage *message)
391{
392 GNUNET_MQ_check_zero_termination (message);
393 return GNUNET_OK;
394}
395
396
397/**
398 * Handler for LOOKUP_BY_SUFFIX message from client, sends information
399 * about ONE identity to the client immediately.
400 *
401 * @param cls a `struct GNUNET_SERVICE_Client *`
402 * @param message the message received
403 */
404static void
405handle_lookup_by_suffix_message (void *cls,
406 const struct LookupMessage *message)
407{
408 struct GNUNET_SERVICE_Client *client = cls;
409 const char *name;
410 struct GNUNET_MQ_Envelope *env;
411 struct Ego *lprefix;
412
413 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
414 "Received LOOKUP_BY_SUFFIX message from client\n");
415 name = (const char *) &message[1];
416 lprefix = NULL;
417 for (struct Ego *ego = ego_head; NULL != ego; ego = ego->next)
418 {
419
420 if ((strlen (ego->identifier) <= strlen (name)) &&
421 (0 == strcmp (ego->identifier,
422 &name[strlen (name) - strlen (ego->identifier)])) &&
423 ((strlen (name) == strlen (ego->identifier)) ||
424 ('.' == name[strlen (name) -
425 strlen (ego->identifier) - 1])) &&
426 ((NULL == lprefix) ||
427 (strlen (ego->identifier) > strlen (lprefix->identifier))))
428 {
429 /* found better match, update! */
430 lprefix = ego;
431 }
432 }
433 if (NULL != lprefix)
434 {
435 env = create_update_message (lprefix);
436 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
437 GNUNET_SERVICE_client_continue (client);
438 return;
439 }
440 send_result_code (client,
441 0,
442 "ego not found");
443 GNUNET_SERVICE_client_continue (client);
444}
445
446
447/**
381 * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT message 448 * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT message
382 * 449 *
383 * @param cls client sending the message 450 * @param cls client sending the message
@@ -1118,6 +1185,10 @@ GNUNET_SERVICE_MAIN
1118 GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP, 1185 GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP,
1119 struct LookupMessage, 1186 struct LookupMessage,
1120 NULL), 1187 NULL),
1188 GNUNET_MQ_hd_var_size (lookup_by_suffix_message,
1189 GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP_BY_SUFFIX,
1190 struct LookupMessage,
1191 NULL),
1121 GNUNET_MQ_hd_var_size (get_default_message, 1192 GNUNET_MQ_hd_var_size (get_default_message,
1122 GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT, 1193 GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT,
1123 struct GetDefaultMessage, 1194 struct GetDefaultMessage,
diff --git a/src/identity/identity.h b/src/identity/identity.h
index 96550bdf2..6ef16e39d 100644
--- a/src/identity/identity.h
+++ b/src/identity/identity.h
@@ -62,7 +62,8 @@ struct ResultCodeMessage
62struct LookupMessage 62struct LookupMessage
63{ 63{
64 /** 64 /**
65 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP 65 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP or
66 * #GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP_BY_SUFFIX
66 */ 67 */
67 struct GNUNET_MessageHeader header; 68 struct GNUNET_MessageHeader header;
68 69
diff --git a/src/include/gnunet_identity_service.h b/src/include/gnunet_identity_service.h
index b2472da43..52ed1e908 100644
--- a/src/include/gnunet_identity_service.h
+++ b/src/include/gnunet_identity_service.h
@@ -328,6 +328,24 @@ GNUNET_IDENTITY_ego_lookup (const struct GNUNET_CONFIGURATION_Handle *cfg,
328void 328void
329GNUNET_IDENTITY_ego_lookup_cancel (struct GNUNET_IDENTITY_EgoLookup *el); 329GNUNET_IDENTITY_ego_lookup_cancel (struct GNUNET_IDENTITY_EgoLookup *el);
330 330
331/**
332 * Function called with the result.
333 *
334 * @param cls closure
335 * @param ego NULL on error / ego not found
336 * @param ego_name NULL on error, name of the ego otherwise
337 */
338typedef void (*GNUNET_IDENTITY_EgoSuffixCallback) (
339 void *cls,
340 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
341 const char *ego_name);
342
343
344/**
345 * Handle for suffix lookup.
346 */
347struct GNUNET_IDENTITY_EgoSuffixLookup;
348
331 349
332/** 350/**
333 * Obtain the ego with the maximum suffix match between the 351 * Obtain the ego with the maximum suffix match between the
@@ -335,20 +353,26 @@ GNUNET_IDENTITY_ego_lookup_cancel (struct GNUNET_IDENTITY_EgoLookup *el);
335 * a @a suffix "a.b.c" and egos with names "d.a.b.c", "b.c" and "c", 353 * a @a suffix "a.b.c" and egos with names "d.a.b.c", "b.c" and "c",
336 * we return the ego for "b.c". 354 * we return the ego for "b.c".
337 * 355 *
338 * @param id identity service to query 356 * @param cfg configuration to use
339 * @param suffix for which domain name suffix is an identity wanted 357 * @param suffix for which domain name suffix is an identity wanted
340 * @param cb function to call with the result (will only be called once) 358 * @param cb function to call with the result (will only be called once)
341 * @param cb_cls closure for @a cb 359 * @param cb_cls closure for @a cb
342 * @return handle to abort the operation 360 * @return handle to abort the operation
343 */ 361 */
344struct GNUNET_IDENTITY_EgoLookup * 362struct GNUNET_IDENTITY_EgoSuffixLookup *
345GNUNET_IDENTITY_ego_lookup_by_suffix (struct GNUNET_IDENTITY_Handle *id, 363GNUNET_IDENTITY_ego_lookup_by_suffix (const struct GNUNET_CONFIGURATION_Handle *cfg,
346 const char *suffix, 364 const char *suffix,
347 GNUNET_IDENTITY_EgoCallback cb, 365 GNUNET_IDENTITY_EgoSuffixCallback cb,
348 void *cb_cls); 366 void *cb_cls);
349 367
350 368
351 369/**
370 * Abort ego suffix lookup attempt.
371 *
372 * @param el handle for lookup to abort
373 */
374void
375GNUNET_IDENTITY_ego_lookup_by_suffix_cancel (struct GNUNET_IDENTITY_EgoSuffixLookup *el);
352 376
353#if 0 /* keep Emacsens' auto-indent happy */ 377#if 0 /* keep Emacsens' auto-indent happy */
354{ 378{
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index d93e12bfb..45bfa4f1b 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -1948,6 +1948,15 @@ extern "C" {
1948 */ 1948 */
1949#define GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP 632 1949#define GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP 632
1950 1950
1951/**
1952 * First message send from identity client to service to lookup a
1953 * single ego matching the given suffix (longest match). The service
1954 * will respond with a #GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE message if
1955 * the ego exists, or a #GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE if
1956 * not.
1957 */
1958#define GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP_BY_SUFFIX 633
1959
1951 1960
1952/******************************************************************************* 1961/*******************************************************************************
1953 * REVOCATION message types 1962 * REVOCATION message types