aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <grothoff@gnunet.org>2021-07-24 22:05:46 +0200
committerChristian Grothoff <grothoff@gnunet.org>2021-07-24 22:06:04 +0200
commit31eae6bbe16302d2593b806ef3d2ac2ca9c2d8de (patch)
treeeba886ebfd704f83f13ce1b50976e3bdca6b2449
parentebd034f8139ee90336fd8e7e2f24f9c9d39c5e25 (diff)
downloadgnunet-31eae6bbe16302d2593b806ef3d2ac2ca9c2d8de.tar.gz
gnunet-31eae6bbe16302d2593b806ef3d2ac2ca9c2d8de.zip
early draft for libgnunetpq event notification support
-rw-r--r--src/include/gnunet_common.h11
-rw-r--r--src/include/gnunet_pq_lib.h168
-rw-r--r--src/include/gnunet_strings_lib.h55
-rw-r--r--src/json/json_helper.c28
-rw-r--r--src/pq/Makefile.am2
-rw-r--r--src/pq/pq.h20
-rw-r--r--src/pq/pq_connect.c2
-rw-r--r--src/pq/pq_event.c396
-rw-r--r--src/util/strings.c467
9 files changed, 714 insertions, 435 deletions
diff --git a/src/include/gnunet_common.h b/src/include/gnunet_common.h
index 1126deaf4..df1ccff26 100644
--- a/src/include/gnunet_common.h
+++ b/src/include/gnunet_common.h
@@ -435,11 +435,12 @@ enum GNUNET_ErrorType
435 * @param date when was the message logged? 435 * @param date when was the message logged?
436 * @param message what is the message 436 * @param message what is the message
437 */ 437 */
438typedef void (*GNUNET_Logger) (void *cls, 438typedef void
439 enum GNUNET_ErrorType kind, 439(*GNUNET_Logger) (void *cls,
440 const char *component, 440 enum GNUNET_ErrorType kind,
441 const char *date, 441 const char *component,
442 const char *message); 442 const char *date,
443 const char *message);
443 444
444 445
445/** 446/**
diff --git a/src/include/gnunet_pq_lib.h b/src/include/gnunet_pq_lib.h
index 2cecb9885..1f2915165 100644
--- a/src/include/gnunet_pq_lib.h
+++ b/src/include/gnunet_pq_lib.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2016, 2017, 2020 GNUnet e.V. 3 Copyright (C) 2016, 2017, 2020, 2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -853,6 +853,170 @@ GNUNET_PQ_reconnect (struct GNUNET_PQ_Context *db);
853 853
854 854
855/** 855/**
856 * Function called whenever the socket needed for
857 * notifications from postgres changes.
858 *
859 * @param cls closure
860 * @param fd socket to listen on, -1 for none
861 */
862typedef void
863(*GNUNET_PQ_SocketCallback)(void *cls,
864 int fd);
865
866
867/**
868 * Obtain the file descriptor to poll on for notifications.
869 * Useful if the GNUnet scheduler is NOT to be used for
870 * such notifications.
871 *
872 * @param db database handle
873 * @param sc function to call with the socket
874 * @param sc_cls closure for @a sc
875 */
876void
877GNUNET_PQ_event_set_socket_callback (struct GNUNET_PQ_Context *db,
878 GNUNET_PQ_SocketCallback sc,
879 void *sc_cls);
880
881
882/**
883 * Poll for database events now. Used if the event FD
884 * is ready and the application wants to trigger applicable
885 * events.
886 * Useful if the GNUnet scheduler is NOT to be used for
887 * such notifications.
888 *
889 * @param db database handle
890 */
891void
892GNUNET_PQ_event_do_poll (struct GNUNET_PQ_Context *db);
893
894
895/**
896 * Run poll event loop using the GNUnet scheduler.
897 *
898 * @param db database handle
899 */
900void
901GNUNET_PQ_event_scheduler_start (struct GNUNET_PQ_Context *db);
902
903
904/**
905 * Stop running poll event loop using the GNUnet scheduler.
906 *
907 * @param db database handle
908 */
909void
910GNUNET_PQ_event_scheduler_stop (struct GNUNET_PQ_Context *db);
911
912
913/**
914 * Handle for an active LISTENer to the database.
915 */
916struct GNUNET_PQ_EventHandler;
917
918/**
919 * Function called on events received from Postgres.
920 *
921 * @param cls closure
922 * @param extra additional event data provided
923 * @param extra_size number of bytes in @a extra
924 */
925typedef void
926(*GNUNET_PQ_EventCallback)(void *cls,
927 const void *extra,
928 size_t extra_size);
929
930GNUNET_NETWORK_STRUCT_BEGIN
931
932
933/**
934 * Header of a structure that describes an
935 * event channel we may subscribe to or notify on.
936 */
937struct GNUNET_PQ_EventHeaderP
938{
939 /**
940 * The length of the struct (in bytes, including the length field itself),
941 * in big-endian format.
942 */
943 uint16_t size GNUNET_PACKED;
944
945 /**
946 * The type of the message (GNUNET_PQ_EVENT_TYPE_XXXX), in big-endian format.
947 */
948 uint16_t type GNUNET_PACKED;
949
950};
951
952GNUNET_NETWORK_STRUCT_END
953
954
955/**
956 * Handle for an active LISTENer to the database.
957 */
958struct GNUNET_PQ_EventHandler;
959
960/**
961 * Register callback to be invoked on events of type @a es.
962 *
963 * Unlike many other calls, this function is thread-safe
964 * and may be called from threads that are different
965 * from the one that setup @a db. However, the @a cb
966 * will always be called from the thread that runs
967 * #GNUNET_PQ_event_do_poll() or the GNUnet scheduler.
968 *
969 * @param db database context to use
970 * @param es specification of the event to listen for
971 * @param cb function to call when the event happens, possibly
972 * multiple times (until #GNUNET_PQ_event_listen_cancel() is invoked)
973 * @param cb_cls closure for @a cb
974 * @return handle useful to cancel the listener
975 */
976struct GNUNET_PQ_EventHandler *
977GNUNET_PQ_event_listen (struct GNUNET_PQ_Context *db,
978 const struct GNUNET_PQ_EventHeaderP *es,
979 GNUNET_PQ_EventCallback cb,
980 void *cb_cls);
981
982
983/**
984 * Stop notifications.
985 *
986 * Unlike many other calls, this function is thread-safe
987 * and may be called from threads that are different
988 * from the one that setup @a db. However, the @a cb
989 * will always be called from the thread that runs
990 * #GNUNET_PQ_event_do_poll() or the GNUnet scheduler.
991 *
992 * @param eh handle to unregister.
993 */
994void
995GNUNET_PQ_event_listen_cancel (struct GNUNET_PQ_EventHandler *eh);
996
997
998/**
999 * Notify all that listen on @a es of an event.
1000 *
1001 * Unlike many other calls, this function is thread-safe
1002 * and may be called from threads that are different
1003 * from the one that setup @a db. However, the @a cb
1004 * will always be called from the thread that runs
1005 * #GNUNET_PQ_event_do_poll() or the GNUnet scheduler.
1006 *
1007 * @param db database context to use
1008 * @param es specification of the event to generate
1009 * @param extra additional event data provided
1010 * @param extra_size number of bytes in @a extra
1011 */
1012void
1013GNUNET_PQ_event_notify (struct GNUNET_PQ_Context *db,
1014 const struct GNUNET_PQ_EventHeaderP *es,
1015 const void *extra,
1016 size_t extra_size);
1017
1018
1019/**
856 * Within the @a db context, run all the SQL files 1020 * Within the @a db context, run all the SQL files
857 * from the @a load_path from 0000-9999.sql (as long 1021 * from the @a load_path from 0000-9999.sql (as long
858 * as the files exist contiguously). 1022 * as the files exist contiguously).
@@ -861,7 +1025,7 @@ GNUNET_PQ_reconnect (struct GNUNET_PQ_Context *db);
861 * @param load_path where to find the XXXX.sql files 1025 * @param load_path where to find the XXXX.sql files
862 * @return #GNUNET_OK on success 1026 * @return #GNUNET_OK on success
863 */ 1027 */
864int 1028enum GNUNET_GenericReturnValue
865GNUNET_PQ_run_sql (struct GNUNET_PQ_Context *db, 1029GNUNET_PQ_run_sql (struct GNUNET_PQ_Context *db,
866 const char *load_path); 1030 const char *load_path);
867 1031
diff --git a/src/include/gnunet_strings_lib.h b/src/include/gnunet_strings_lib.h
index 955a3afca..977c2ead7 100644
--- a/src/include/gnunet_strings_lib.h
+++ b/src/include/gnunet_strings_lib.h
@@ -327,7 +327,7 @@ GNUNET_STRINGS_data_to_string_alloc (const void *buf,
327 * @param out_size size of the output buffer @a out 327 * @param out_size size of the output buffer @a out
328 * @return #GNUNET_OK on success, #GNUNET_SYSERR if result has the wrong encoding 328 * @return #GNUNET_OK on success, #GNUNET_SYSERR if result has the wrong encoding
329 */ 329 */
330int 330enum GNUNET_GenericReturnValue
331GNUNET_STRINGS_string_to_data (const char *enc, 331GNUNET_STRINGS_string_to_data (const char *enc,
332 size_t enclen, 332 size_t enclen,
333 void *out, 333 void *out,
@@ -335,6 +335,24 @@ GNUNET_STRINGS_string_to_data (const char *enc,
335 335
336 336
337/** 337/**
338 * Convert CrockfordBase32 encoding back to data.
339 * @a out_size will be determined from @a enc and
340 * @a out will be allocated to be large enough.
341 *
342 * @param enc the encoding
343 * @param enclen number of characters in @a enc (without 0-terminator, which can be missing)
344 * @param[out] out location where to allocate and store the decoded data
345 * @param[out] out_size set to the size of the output buffer @a out
346 * @return #GNUNET_OK on success, #GNUNET_SYSERR if result has the wrong encoding
347 */
348enum GNUNET_GenericReturnValue
349GNUNET_STRINGS_string_to_data_alloc (const char *enc,
350 size_t enclen,
351 void **out,
352 size_t *out_size);
353
354
355/**
338 * Encode into Base64. 356 * Encode into Base64.
339 * 357 *
340 * @param data the data to encode 358 * @param data the data to encode
@@ -359,7 +377,10 @@ GNUNET_STRINGS_base64_encode (const void *in,
359 * @return the size of the output 377 * @return the size of the output
360 */ 378 */
361size_t 379size_t
362GNUNET_STRINGS_urlencode (const char *data, size_t len, char **out); 380GNUNET_STRINGS_urlencode (const char *data,
381 size_t len,
382 char **out);
383
363 384
364/** 385/**
365 * Encode into Base64url. RFC7515 386 * Encode into Base64url. RFC7515
@@ -371,7 +392,9 @@ GNUNET_STRINGS_urlencode (const char *data, size_t len, char **out);
371 * @return the size of the output 392 * @return the size of the output
372 */ 393 */
373size_t 394size_t
374GNUNET_STRINGS_base64url_encode (const void *in, size_t len, char **output); 395GNUNET_STRINGS_base64url_encode (const void *in,
396 size_t len,
397 char **output);
375 398
376 399
377/** 400/**
@@ -399,7 +422,9 @@ GNUNET_STRINGS_base64_decode (const char *data,
399 * @return the size of the output 422 * @return the size of the output
400 */ 423 */
401size_t 424size_t
402GNUNET_STRINGS_base64url_decode (const char *data, size_t len, void **out); 425GNUNET_STRINGS_base64url_decode (const char *data,
426 size_t len,
427 void **out);
403 428
404/** 429/**
405 * url/percent encode (RFC3986). 430 * url/percent encode (RFC3986).
@@ -411,7 +436,9 @@ GNUNET_STRINGS_base64url_decode (const char *data, size_t len, void **out);
411 * @return the size of the output 436 * @return the size of the output
412 */ 437 */
413size_t 438size_t
414GNUNET_STRINGS_urldecode (const char *data, size_t len, char **out); 439GNUNET_STRINGS_urldecode (const char *data,
440 size_t len,
441 char **out);
415 442
416 443
417/** 444/**
@@ -442,7 +469,7 @@ GNUNET_STRINGS_pp2s (const struct GNUNET_PeerIdentity *pids,
442 * an URI, '* scheme_part' and '*path_part' will remain unchanged 469 * an URI, '* scheme_part' and '*path_part' will remain unchanged
443 * (if they weren't NULL). 470 * (if they weren't NULL).
444 */ 471 */
445int 472enum GNUNET_GenericReturnValue
446GNUNET_STRINGS_parse_uri (const char *path, 473GNUNET_STRINGS_parse_uri (const char *path,
447 char **scheme_part, 474 char **scheme_part,
448 const char **path_part); 475 const char **path_part);
@@ -462,7 +489,7 @@ GNUNET_STRINGS_parse_uri (const char *path,
462 * GNUNET_free (). Can be NULL. 489 * GNUNET_free (). Can be NULL.
463 * @return #GNUNET_YES if 'filename' is absolute, #GNUNET_NO otherwise. 490 * @return #GNUNET_YES if 'filename' is absolute, #GNUNET_NO otherwise.
464 */ 491 */
465int 492enum GNUNET_GenericReturnValue
466GNUNET_STRINGS_path_is_absolute (const char *filename, 493GNUNET_STRINGS_path_is_absolute (const char *filename,
467 int can_be_uri, 494 int can_be_uri,
468 int *r_is_uri, 495 int *r_is_uri,
@@ -505,7 +532,7 @@ enum GNUNET_STRINGS_FilenameCheck
505 * @return #GNUNET_YES if all checks pass, #GNUNET_NO if at least one of them 532 * @return #GNUNET_YES if all checks pass, #GNUNET_NO if at least one of them
506 * fails, #GNUNET_SYSERR when a check can't be performed 533 * fails, #GNUNET_SYSERR when a check can't be performed
507 */ 534 */
508int 535enum GNUNET_GenericReturnValue
509GNUNET_STRINGS_check_filename (const char *filename, 536GNUNET_STRINGS_check_filename (const char *filename,
510 enum GNUNET_STRINGS_FilenameCheck checks); 537 enum GNUNET_STRINGS_FilenameCheck checks);
511 538
@@ -521,7 +548,7 @@ GNUNET_STRINGS_check_filename (const char *filename,
521 * @return #GNUNET_OK if conversion succeeded. #GNUNET_SYSERR otherwise, in which 548 * @return #GNUNET_OK if conversion succeeded. #GNUNET_SYSERR otherwise, in which
522 * case the contents of r_buf are undefined. 549 * case the contents of r_buf are undefined.
523 */ 550 */
524int 551enum GNUNET_GenericReturnValue
525GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr, 552GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr,
526 uint16_t addrlen, 553 uint16_t addrlen,
527 struct sockaddr_in6 *r_buf); 554 struct sockaddr_in6 *r_buf);
@@ -537,7 +564,7 @@ GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr,
537 * @return #GNUNET_OK if conversion succeeded. #GNUNET_SYSERR otherwise, in which case 564 * @return #GNUNET_OK if conversion succeeded. #GNUNET_SYSERR otherwise, in which case
538 * the contents of r_buf are undefined. 565 * the contents of r_buf are undefined.
539 */ 566 */
540int 567enum GNUNET_GenericReturnValue
541GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr, 568GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr,
542 uint16_t addrlen, 569 uint16_t addrlen,
543 struct sockaddr_in *r_buf); 570 struct sockaddr_in *r_buf);
@@ -569,7 +596,7 @@ GNUNET_STRINGS_parse_socket_addr (const char *addr,
569 * @return #GNUNET_OK if conversion succeeded. #GNUNET_SYSERR otherwise, in which 596 * @return #GNUNET_OK if conversion succeeded. #GNUNET_SYSERR otherwise, in which
570 * case the contents of r_buf are undefined. 597 * case the contents of r_buf are undefined.
571 */ 598 */
572int 599enum GNUNET_GenericReturnValue
573GNUNET_STRINGS_to_address_ip (const char *addr, 600GNUNET_STRINGS_to_address_ip (const char *addr,
574 uint16_t addrlen, 601 uint16_t addrlen,
575 struct sockaddr_storage *r_buf); 602 struct sockaddr_storage *r_buf);
@@ -587,7 +614,7 @@ GNUNET_STRINGS_to_address_ip (const char *addr,
587 * @param u8argv a location to store new argv in 614 * @param u8argv a location to store new argv in
588 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure 615 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
589 */ 616 */
590int 617enum GNUNET_GenericReturnValue
591GNUNET_STRINGS_get_utf8_args (int argc, 618GNUNET_STRINGS_get_utf8_args (int argc,
592 char *const *argv, 619 char *const *argv,
593 int *u8argc, 620 int *u8argc,
@@ -610,7 +637,9 @@ GNUNET_STRINGS_get_utf8_args (int argc,
610 * null byte 637 * null byte
611 */ 638 */
612size_t 639size_t
613GNUNET_strlcpy (char *dst, const char *src, size_t n); 640GNUNET_strlcpy (char *dst,
641 const char *src,
642 size_t n);
614 643
615 644
616/* ***************** IPv4/IPv6 parsing ****************** */ 645/* ***************** IPv4/IPv6 parsing ****************** */
diff --git a/src/json/json_helper.c b/src/json/json_helper.c
index 03db9ec80..55435ea19 100644
--- a/src/json/json_helper.c
+++ b/src/json/json_helper.c
@@ -116,7 +116,6 @@ parse_variable_data (void *cls,
116 const char *str; 116 const char *str;
117 size_t size; 117 size_t size;
118 void *data; 118 void *data;
119 int res;
120 119
121 str = json_string_value (root); 120 str = json_string_value (root);
122 if (NULL == str) 121 if (NULL == str)
@@ -124,30 +123,13 @@ parse_variable_data (void *cls,
124 GNUNET_break_op (0); 123 GNUNET_break_op (0);
125 return GNUNET_SYSERR; 124 return GNUNET_SYSERR;
126 } 125 }
127 size = (strlen (str) * 5) / 8; 126 if (GNUNET_OK !=
128 if (size >= GNUNET_MAX_MALLOC_CHECKED) 127 GNUNET_STRINGS_string_to_data_alloc (str,
129 { 128 strlen (str),
130 GNUNET_break_op (0); 129 &data,
131 return GNUNET_SYSERR; 130 &size))
132 }
133 data = GNUNET_malloc (size);
134 res = GNUNET_STRINGS_string_to_data (str,
135 strlen (str),
136 data,
137 size);
138 if ( (0 < size) &&
139 (GNUNET_OK != res) )
140 {
141 size--;
142 res = GNUNET_STRINGS_string_to_data (str,
143 strlen (str),
144 data,
145 size);
146 }
147 if (GNUNET_OK != res)
148 { 131 {
149 GNUNET_break_op (0); 132 GNUNET_break_op (0);
150 GNUNET_free (data);
151 return GNUNET_SYSERR; 133 return GNUNET_SYSERR;
152 } 134 }
153 *(void **) spec->ptr = data; 135 *(void **) spec->ptr = data;
diff --git a/src/pq/Makefile.am b/src/pq/Makefile.am
index fcc30f6ff..0febac4ac 100644
--- a/src/pq/Makefile.am
+++ b/src/pq/Makefile.am
@@ -14,6 +14,7 @@ libgnunetpq_la_SOURCES = \
14 pq.h \ 14 pq.h \
15 pq_connect.c \ 15 pq_connect.c \
16 pq_eval.c \ 16 pq_eval.c \
17 pq_event.c \
17 pq_exec.c \ 18 pq_exec.c \
18 pq_prepare.c \ 19 pq_prepare.c \
19 pq_query_helper.c \ 20 pq_query_helper.c \
@@ -23,6 +24,7 @@ libgnunetpq_la_LIBADD = -lpq \
23libgnunetpq_la_LDFLAGS = \ 24libgnunetpq_la_LDFLAGS = \
24 $(POSTGRESQL_LDFLAGS) \ 25 $(POSTGRESQL_LDFLAGS) \
25 $(GN_LIB_LDFLAGS) \ 26 $(GN_LIB_LDFLAGS) \
27 -lpthread \
26 -version-info 1:0:0 28 -version-info 1:0:0
27 29
28if ENABLE_TEST_RUN 30if ENABLE_TEST_RUN
diff --git a/src/pq/pq.h b/src/pq/pq.h
index 91a890bcb..3c89626a9 100644
--- a/src/pq/pq.h
+++ b/src/pq/pq.h
@@ -57,6 +57,26 @@ struct GNUNET_PQ_Context
57 * Path to load SQL files from. 57 * Path to load SQL files from.
58 */ 58 */
59 char *load_path; 59 char *load_path;
60
61 /**
62 * Function to call on Postgres FDs.
63 */
64 GNUNET_PQ_SocketCallback sc;
65
66 /**
67 * Closure for @e sc.
68 */
69 void *sc_cls;
70
71 /**
72 * Map managing event subscriptions.
73 */
74 struct GNUNET_CONTAINER_MultiShortmap *channel_map;
75
76 /**
77 * Lock to access @e channel_map.
78 */
79 pthread_mutex_t notify_lock;
60}; 80};
61 81
62#endif 82#endif
diff --git a/src/pq/pq_connect.c b/src/pq/pq_connect.c
index cd52c2728..00664dcd0 100644
--- a/src/pq/pq_connect.c
+++ b/src/pq/pq_connect.c
@@ -209,7 +209,7 @@ apply_patch (struct GNUNET_PQ_Context *db,
209 * @param load_path where to find the XXXX.sql files 209 * @param load_path where to find the XXXX.sql files
210 * @return #GNUNET_OK on success 210 * @return #GNUNET_OK on success
211 */ 211 */
212int 212enum GNUNET_GenericReturnValue
213GNUNET_PQ_run_sql (struct GNUNET_PQ_Context *db, 213GNUNET_PQ_run_sql (struct GNUNET_PQ_Context *db,
214 const char *load_path) 214 const char *load_path)
215{ 215{
diff --git a/src/pq/pq_event.c b/src/pq/pq_event.c
new file mode 100644
index 000000000..ecb942230
--- /dev/null
+++ b/src/pq/pq_event.c
@@ -0,0 +1,396 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 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 * @file pq/pq_event.c
22 * @brief event notifications via Postgres
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "pq.h"
27#include <pthread.h>
28
29
30/**
31 * Handle for an active LISTENer to the database.
32 */
33struct GNUNET_PQ_EventHandler
34{
35 /**
36 * Channel name.
37 */
38 struct GNUNET_ShortHashCode sh;
39
40 /**
41 * Function to call on events.
42 */
43 GNUNET_PQ_EventCallback cb;
44
45 /**
46 * Closure for @e cb.
47 */
48 void *cb_cls;
49
50 /**
51 * Database context this event handler is with.
52 */
53 struct GNUNET_PQ_Context *db;
54};
55
56
57
58
59/**
60 * Convert @a es to a short hash.
61 *
62 * @param es spec to hash to an identifier
63 * @param[out] sh short hash to set
64 */
65static void
66es_to_sh (const struct GNUNET_PQ_EventHeaderP *es,
67 struct GNUNET_ShortHashCode *sh)
68{
69 struct GNUNET_HashCode h_channel;
70
71 GNUNET_CRYPTO_hash (es,
72 ntohs (es->size),
73 &h_channel);
74 GNUNET_static_assert (sizeof (*sh) <= sizeof (h_channel));
75 memcpy (sh,
76 &h_channel,
77 sizeof (*sh));
78}
79
80
81/**
82 * Convert @a sh to a Postgres identifier.
83 *
84 * @param sh short hash to convert to an identifier
85 * @param[out] identifier by default, Postgres supports
86 * NAMEDATALEN=64 character identifiers
87 * @return end position of the identifier
88 */
89static char *
90sh_to_channel (struct GNUNET_ShortHashCode *sh,
91 char identifier[64])
92{
93 char *end;
94
95 end = GNUNET_STRINGS_data_to_string (sh,
96 sizeof (*sh),
97 identifier,
98 63);
99 GNUNET_assert (NULL != end);
100 *end = '\0';
101 return end;
102}
103
104
105/**
106 * Convert @a es to a Postgres identifier.
107 *
108 * @param es spec to hash to an identifier
109 * @param[out] identifier by default, Postgres supports
110 * NAMEDATALEN=64 character identifiers
111 * @return end position of the identifier
112 */
113static char *
114es_to_channel (const struct GNUNET_PQ_EventHeaderP *es,
115 char identifier[64])
116{
117 struct GNUNET_ShortHashCode sh;
118
119 es_to_sh (es,
120 &sh);
121 return sh_to_channel (&sh,
122 identifier);
123}
124
125
126/**
127 * Closure for #do_notify().
128 */
129struct NotifyContext
130{
131 /**
132 * Extra argument of the notification, or NULL.
133 */
134 void *extra;
135
136 /**
137 * Number of bytes in @e extra.
138 */
139 size_t extra_size;
140};
141
142
143/**
144 * Function called on every event handler that
145 * needs to be triggered.
146 *
147 * @param cls a `struct NotifyContext`
148 * @param sh channel name
149 * @param value a `struct GNUNET_PQ_EventHandler`
150 * @return #GNUNET_OK continue to iterate
151 */
152static int
153do_notify (void *cls,
154 const struct GNUNET_ShortHashCode *sh,
155 void *value)
156{
157 struct NotifyContext *ctx = cls;
158 struct GNUNET_PQ_EventHandler *eh = value;
159
160 eh->cb (eh->cb_cls,
161 ctx->extra,
162 ctx->extra_size);
163 return GNUNET_OK;
164}
165
166
167void
168GNUNET_PQ_event_set_socket_callback (struct GNUNET_PQ_Context *db,
169 GNUNET_PQ_SocketCallback sc,
170 void *sc_cls)
171{
172 int fd;
173
174 db->sc = sc;
175 db->sc_cls = sc_cls;
176 if (NULL == sc)
177 return;
178 GNUNET_assert (0 ==
179 pthread_mutex_lock (&db->notify_lock));
180 fd = PQsocket (db->conn);
181 if ( (-1 != fd) &&
182 (0 != GNUNET_CONTAINER_multishortmap_size (db->channel_map)) )
183 sc (sc_cls,
184 fd);
185 GNUNET_assert (0 ==
186 pthread_mutex_unlock (&db->notify_lock));
187}
188
189
190void
191GNUNET_PQ_event_do_poll (struct GNUNET_PQ_Context *db)
192{
193 PGnotify *n;
194
195 GNUNET_assert (0 ==
196 pthread_mutex_lock (&db->notify_lock));
197 while (NULL != (n = PQnotifies (db->conn)))
198 {
199 struct GNUNET_ShortHashCode sh;
200 struct NotifyContext ctx = {
201 .extra = NULL
202 };
203
204 if (GNUNET_OK !=
205 GNUNET_STRINGS_string_to_data (n->relname,
206 strlen (n->relname),
207 &sh,
208 sizeof (sh)))
209 {
210 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
211 "Ignoring notification for unsupported channel identifier `%s'\n",
212 n->relname);
213 continue;
214 }
215 if ( (NULL != n->extra) &&
216 (GNUNET_OK !=
217 GNUNET_STRINGS_string_to_data_alloc (n->extra,
218 strlen (n->extra),
219 &ctx.extra,
220 &ctx.extra_size)))
221 {
222 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
223 "Ignoring notification for unsupported extra data `%s' on channel `%s'\n",
224 n->extra,
225 n->relname);
226 continue;
227 }
228 GNUNET_CONTAINER_multishortmap_iterate (db->channel_map,
229 &do_notify,
230 &ctx);
231 GNUNET_free (ctx.extra);
232 }
233 GNUNET_assert (0 ==
234 pthread_mutex_unlock (&db->notify_lock));
235}
236
237
238void
239GNUNET_PQ_event_scheduler_start (struct GNUNET_PQ_Context *db)
240{
241 GNUNET_break (0); // FIXME: not implemented
242}
243
244
245void
246GNUNET_PQ_event_scheduler_stop (struct GNUNET_PQ_Context *db)
247{
248 GNUNET_break (0); // FIXME: not implemented
249}
250
251
252static void
253manage_subscribe (struct GNUNET_PQ_Context *db,
254 const char *cmd,
255 struct GNUNET_PQ_EventHandler *eh)
256{
257 char sql[16 + 64];
258 char *end;
259 PGresult *result;
260
261 end = stpcpy (sql,
262 cmd);
263 end = sh_to_channel (&eh->sh,
264 end);
265 result = PQexec (db->conn,
266 sql);
267 if (PGRES_COMMAND_OK != PQresultStatus (result))
268 {
269 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
270 "pq",
271 "Failed to execute `%s': %s/%s/%s/%s/%s",
272 sql,
273 PQresultErrorField (result,
274 PG_DIAG_MESSAGE_PRIMARY),
275 PQresultErrorField (result,
276 PG_DIAG_MESSAGE_DETAIL),
277 PQresultErrorMessage (result),
278 PQresStatus (PQresultStatus (result)),
279 PQerrorMessage (db->conn));
280 }
281 PQclear (result);
282}
283
284
285struct GNUNET_PQ_EventHandler *
286GNUNET_PQ_event_listen (struct GNUNET_PQ_Context *db,
287 const struct GNUNET_PQ_EventHeaderP *es,
288 GNUNET_PQ_EventCallback cb,
289 void *cb_cls)
290{
291 struct GNUNET_PQ_EventHandler *eh;
292 bool was_zero;
293
294 eh = GNUNET_new (struct GNUNET_PQ_EventHandler);
295 eh->db = db;
296 es_to_sh (es,
297 &eh->sh);
298 eh->cb = cb;
299 eh->cb_cls = cb_cls;
300 GNUNET_assert (0 ==
301 pthread_mutex_lock (&db->notify_lock));
302 was_zero = (0 == GNUNET_CONTAINER_multishortmap_size (db->channel_map));
303 GNUNET_assert (GNUNET_OK ==
304 GNUNET_CONTAINER_multishortmap_put (db->channel_map,
305 &eh->sh,
306 eh,
307 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
308 if ( (NULL != db->sc) &&
309 was_zero)
310 {
311 int fd = PQsocket (db->conn);
312
313 if (-1 != fd)
314 db->sc (db->sc_cls,
315 fd);
316 }
317 manage_subscribe (db,
318 "LISTEN ",
319 eh);
320 GNUNET_assert (0 ==
321 pthread_mutex_unlock (&db->notify_lock));
322 return eh;
323}
324
325
326void
327GNUNET_PQ_event_listen_cancel (struct GNUNET_PQ_EventHandler *eh)
328{
329 struct GNUNET_PQ_Context *db = eh->db;
330
331 GNUNET_assert (0 ==
332 pthread_mutex_lock (&db->notify_lock));
333 GNUNET_assert (GNUNET_OK ==
334 GNUNET_CONTAINER_multishortmap_remove (db->channel_map,
335 &eh->sh,
336 eh));
337
338 manage_subscribe (db,
339 "UNLISTEN ",
340 eh);
341 if ( (NULL != db->sc) &&
342 (0 == GNUNET_CONTAINER_multishortmap_size (db->channel_map)) )
343 {
344 db->sc (db->sc_cls,
345 -1);
346 }
347 GNUNET_assert (0 ==
348 pthread_mutex_unlock (&db->notify_lock));
349}
350
351
352void
353GNUNET_PQ_event_notify (struct GNUNET_PQ_Context *db,
354 const struct GNUNET_PQ_EventHeaderP *es,
355 const void *extra,
356 size_t extra_size)
357{
358 char sql[16 + 64 + extra_size * 8 / 5 + 8];
359 char *end;
360 PGresult *result;
361
362 end = stpcpy (sql,
363 "NOTIFY ");
364 end = es_to_channel (es,
365 end);
366 end = stpcpy (end,
367 "'");
368 end = GNUNET_STRINGS_data_to_string (extra,
369 extra_size,
370 end,
371 sizeof (sql) - (end - sql) - 1);
372 GNUNET_assert (NULL != end);
373 *end = '\0';
374 end = stpcpy (end,
375 "'");
376 result = PQexec (db->conn,
377 sql);
378 if (PGRES_COMMAND_OK != PQresultStatus (result))
379 {
380 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
381 "pq",
382 "Failed to execute `%s': %s/%s/%s/%s/%s",
383 sql,
384 PQresultErrorField (result,
385 PG_DIAG_MESSAGE_PRIMARY),
386 PQresultErrorField (result,
387 PG_DIAG_MESSAGE_DETAIL),
388 PQresultErrorMessage (result),
389 PQresStatus (PQresultStatus (result)),
390 PQerrorMessage (db->conn));
391 }
392 PQclear (result);
393}
394
395/* end of pq_event.c */
396
diff --git a/src/util/strings.c b/src/util/strings.c
index b62d5f547..24335e444 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -41,27 +41,6 @@
41 GNUNET_log_from_strerror (kind, "util-strings", syscall) 41 GNUNET_log_from_strerror (kind, "util-strings", syscall)
42 42
43 43
44/**
45 * Fill a buffer of the given size with
46 * count 0-terminated strings (given as varargs).
47 * If "buffer" is NULL, only compute the amount of
48 * space required (sum of "strlen(arg)+1").
49 *
50 * Unlike using "snprintf" with "%s", this function
51 * will add 0-terminators after each string. The
52 * #GNUNET_string_buffer_tokenize() function can be
53 * used to parse the buffer back into individual
54 * strings.
55 *
56 * @param buffer the buffer to fill with strings, can
57 * be NULL in which case only the necessary
58 * amount of space will be calculated
59 * @param size number of bytes available in buffer
60 * @param count number of strings that follow
61 * @param ... count 0-terminated strings to copy to buffer
62 * @return number of bytes written to the buffer
63 * (or number of bytes that would have been written)
64 */
65size_t 44size_t
66GNUNET_STRINGS_buffer_fill (char *buffer, 45GNUNET_STRINGS_buffer_fill (char *buffer,
67 size_t size, 46 size_t size,
@@ -90,13 +69,6 @@ GNUNET_STRINGS_buffer_fill (char *buffer,
90} 69}
91 70
92 71
93/**
94 * Convert a peer path to a human-readable string.
95 *
96 * @param pids array of PIDs to convert to a string
97 * @param num_pids length of the @a pids array
98 * @return string representing the array of @a pids
99 */
100char * 72char *
101GNUNET_STRINGS_pp2s (const struct GNUNET_PeerIdentity *pids, 73GNUNET_STRINGS_pp2s (const struct GNUNET_PeerIdentity *pids,
102 unsigned int num_pids) 74 unsigned int num_pids)
@@ -120,19 +92,6 @@ GNUNET_STRINGS_pp2s (const struct GNUNET_PeerIdentity *pids,
120} 92}
121 93
122 94
123/**
124 * Given a buffer of a given size, find "count"
125 * 0-terminated strings in the buffer and assign
126 * the count (varargs) of type "const char**" to the
127 * locations of the respective strings in the
128 * buffer.
129 *
130 * @param buffer the buffer to parse
131 * @param size size of the buffer
132 * @param count number of strings to locate
133 * @return offset of the character after the last 0-termination
134 * in the buffer, or 0 on error.
135 */
136unsigned int 95unsigned int
137GNUNET_STRINGS_buffer_tokenize (const char *buffer, 96GNUNET_STRINGS_buffer_tokenize (const char *buffer,
138 size_t size, 97 size_t size,
@@ -167,12 +126,6 @@ GNUNET_STRINGS_buffer_tokenize (const char *buffer,
167} 126}
168 127
169 128
170/**
171 * Convert a given filesize into a fancy human-readable format.
172 *
173 * @param size number of bytes
174 * @return fancy representation of the size (possibly rounded) for humans
175 */
176char * 129char *
177GNUNET_STRINGS_byte_size_fancy (unsigned long long size) 130GNUNET_STRINGS_byte_size_fancy (unsigned long long size)
178{ 131{
@@ -205,20 +158,10 @@ GNUNET_STRINGS_byte_size_fancy (unsigned long long size)
205} 158}
206 159
207 160
208/**
209 * Like strlcpy but portable. The given string @a src is copied until its null
210 * byte or until @a n - 1 bytes have been read. The destination buffer is
211 * guaranteed to be null-terminated.
212 *
213 * @param dst destination of the copy (must be @a n bytes long)
214 * @param src source of the copy (at most @a n - 1 bytes will be read)
215 * @param n the length of the string to copy, including its terminating null
216 * byte
217 * @return the length of the string that was copied, excluding the terminating
218 * null byte
219 */
220size_t 161size_t
221GNUNET_strlcpy (char *dst, const char *src, size_t n) 162GNUNET_strlcpy (char *dst,
163 const char *src,
164 size_t n)
222{ 165{
223 size_t slen; 166 size_t slen;
224 167
@@ -313,13 +256,6 @@ convert_with_table (const char *input,
313} 256}
314 257
315 258
316/**
317 * Convert a given fancy human-readable size to bytes.
318 *
319 * @param fancy_size human readable string (e.g. 1 MB)
320 * @param size set to the size in bytes
321 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
322 */
323int 259int
324GNUNET_STRINGS_fancy_size_to_bytes (const char *fancy_size, 260GNUNET_STRINGS_fancy_size_to_bytes (const char *fancy_size,
325 unsigned long long *size) 261 unsigned long long *size)
@@ -344,14 +280,6 @@ GNUNET_STRINGS_fancy_size_to_bytes (const char *fancy_size,
344} 280}
345 281
346 282
347/**
348 * Convert a given fancy human-readable time to our internal
349 * representation.
350 *
351 * @param fancy_time human readable string (e.g. 1 minute)
352 * @param rtime set to the relative time
353 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
354 */
355int 283int
356GNUNET_STRINGS_fancy_time_to_relative (const char *fancy_time, 284GNUNET_STRINGS_fancy_time_to_relative (const char *fancy_time,
357 struct GNUNET_TIME_Relative *rtime) 285 struct GNUNET_TIME_Relative *rtime)
@@ -394,15 +322,6 @@ GNUNET_STRINGS_fancy_time_to_relative (const char *fancy_time,
394} 322}
395 323
396 324
397/**
398 * Convert a given fancy human-readable time to our internal
399 * representation. The human-readable time is expected to be
400 * in local time, whereas the returned value will be in UTC.
401 *
402 * @param fancy_time human readable string (e.g. %Y-%m-%d %H:%M:%S)
403 * @param atime set to the absolute time
404 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
405 */
406int 325int
407GNUNET_STRINGS_fancy_time_to_absolute (const char *fancy_time, 326GNUNET_STRINGS_fancy_time_to_absolute (const char *fancy_time,
408 struct GNUNET_TIME_Absolute *atime) 327 struct GNUNET_TIME_Absolute *atime)
@@ -435,19 +354,6 @@ GNUNET_STRINGS_fancy_time_to_absolute (const char *fancy_time,
435} 354}
436 355
437 356
438/**
439 * Convert the len characters long character sequence
440 * given in input that is in the given input charset
441 * to a string in given output charset.
442 *
443 * @param input input string
444 * @param len number of bytes in @a input
445 * @param input_charset character set used for @a input
446 * @param output_charset desired character set for the return value
447 * @return the converted string (0-terminated),
448 * if conversion fails, a copy of the original
449 * string is returned.
450 */
451char * 357char *
452GNUNET_STRINGS_conv (const char *input, 358GNUNET_STRINGS_conv (const char *input,
453 size_t len, 359 size_t len,
@@ -510,18 +416,6 @@ fail:
510} 416}
511 417
512 418
513/**
514 * Convert the len characters long character sequence
515 * given in input that is in the given charset
516 * to UTF-8.
517 *
518 * @param input the input string (not necessarily 0-terminated)
519 * @param len the number of bytes in the @a input
520 * @param charset character set to convert from
521 * @return the converted string (0-terminated),
522 * if conversion fails, a copy of the original
523 * string is returned.
524 */
525char * 419char *
526GNUNET_STRINGS_to_utf8 (const char *input, 420GNUNET_STRINGS_to_utf8 (const char *input,
527 size_t len, 421 size_t len,
@@ -534,17 +428,6 @@ GNUNET_STRINGS_to_utf8 (const char *input,
534} 428}
535 429
536 430
537/**
538 * Convert the len bytes-long UTF-8 string
539 * given in input to the given charset.
540 *
541 * @param input the input string (not necessarily 0-terminated)
542 * @param len the number of bytes in the @a input
543 * @param charset character set to convert to
544 * @return the converted string (0-terminated),
545 * if conversion fails, a copy of the original
546 * string is returned.
547 */
548char * 431char *
549GNUNET_STRINGS_from_utf8 (const char *input, 432GNUNET_STRINGS_from_utf8 (const char *input,
550 size_t len, 433 size_t len,
@@ -557,15 +440,9 @@ GNUNET_STRINGS_from_utf8 (const char *input,
557} 440}
558 441
559 442
560/**
561 * Convert the utf-8 input string to lowercase.
562 * Output needs to be allocated appropriately.
563 *
564 * @param input input string
565 * @param output output buffer
566 */
567void 443void
568GNUNET_STRINGS_utf8_tolower (const char *input, char *output) 444GNUNET_STRINGS_utf8_tolower (const char *input,
445 char *output)
569{ 446{
570 uint8_t *tmp_in; 447 uint8_t *tmp_in;
571 size_t len; 448 size_t len;
@@ -582,15 +459,9 @@ GNUNET_STRINGS_utf8_tolower (const char *input, char *output)
582} 459}
583 460
584 461
585/**
586 * Convert the utf-8 input string to uppercase.
587 * Output needs to be allocated appropriately.
588 *
589 * @param input input string
590 * @param output output buffer
591 */
592void 462void
593GNUNET_STRINGS_utf8_toupper (const char *input, char *output) 463GNUNET_STRINGS_utf8_toupper (const char *input,
464 char *output)
594{ 465{
595 uint8_t *tmp_in; 466 uint8_t *tmp_in;
596 size_t len; 467 size_t len;
@@ -607,13 +478,6 @@ GNUNET_STRINGS_utf8_toupper (const char *input, char *output)
607} 478}
608 479
609 480
610/**
611 * Complete filename (a la shell) from abbrevition.
612 * @param fil the name of the file, may contain ~/ or
613 * be relative to the current directory
614 * @returns the full file name,
615 * NULL is returned on error
616 */
617char * 481char *
618GNUNET_STRINGS_filename_expand (const char *fil) 482GNUNET_STRINGS_filename_expand (const char *fil)
619{ 483{
@@ -689,15 +553,6 @@ GNUNET_STRINGS_filename_expand (const char *fil)
689} 553}
690 554
691 555
692/**
693 * Give relative time in human-readable fancy format.
694 * This is one of the very few calls in the entire API that is
695 * NOT reentrant!
696 *
697 * @param delta time in milli seconds
698 * @param do_round are we allowed to round a bit?
699 * @return time as human-readable string
700 */
701const char * 556const char *
702GNUNET_STRINGS_relative_time_to_string (struct GNUNET_TIME_Relative delta, 557GNUNET_STRINGS_relative_time_to_string (struct GNUNET_TIME_Relative delta,
703 int do_round) 558 int do_round)
@@ -745,15 +600,6 @@ GNUNET_STRINGS_relative_time_to_string (struct GNUNET_TIME_Relative delta,
745} 600}
746 601
747 602
748/**
749 * "asctime", except for GNUnet time. Converts a GNUnet internal
750 * absolute time (which is in UTC) to a string in local time.
751 * Note that the returned value will be overwritten if this function
752 * is called again.
753 *
754 * @param t the absolute time to convert
755 * @return timestamp in human-readable form in local time
756 */
757const char * 603const char *
758GNUNET_STRINGS_absolute_time_to_string (struct GNUNET_TIME_Absolute t) 604GNUNET_STRINGS_absolute_time_to_string (struct GNUNET_TIME_Absolute t)
759{ 605{
@@ -776,17 +622,6 @@ GNUNET_STRINGS_absolute_time_to_string (struct GNUNET_TIME_Absolute t)
776} 622}
777 623
778 624
779/**
780 * "man basename"
781 * Returns a pointer to a part of filename (allocates nothing)!
782 *
783 * @param filename filename to extract basename from
784 * @return short (base) name of the file (that is, everything following the
785 * last directory separator in filename. If filename ends with a
786 * directory separator, the result will be a zero-length string.
787 * If filename has no directory separators, the result is filename
788 * itself.
789 */
790const char * 625const char *
791GNUNET_STRINGS_get_short_name (const char *filename) 626GNUNET_STRINGS_get_short_name (const char *filename)
792{ 627{
@@ -856,18 +691,6 @@ getValue__ (unsigned char a)
856} 691}
857 692
858 693
859/**
860 * Convert binary data to ASCII encoding using Crockford Base32 encoding.
861 * Returns a pointer to the byte after the last byte in the string, that
862 * is where the 0-terminator was placed if there was room.
863 *
864 * @param data data to encode
865 * @param size size of data (in bytes)
866 * @param out buffer to fill
867 * @param out_size size of the buffer. Must be large enough to hold
868 * (size * 8 + 4) / 5 bytes
869 * @return pointer to the next byte in @a out or NULL on error.
870 */
871char * 694char *
872GNUNET_STRINGS_data_to_string (const void *data, 695GNUNET_STRINGS_data_to_string (const void *data,
873 size_t size, 696 size_t size,
@@ -923,16 +746,6 @@ GNUNET_STRINGS_data_to_string (const void *data,
923} 746}
924 747
925 748
926/**
927 * Return the base32crockford encoding of the given buffer.
928 *
929 * The returned string will be freshly allocated, and must be free'd
930 * with GNUNET_free().
931 *
932 * @param buffer with data
933 * @param size size of the buffer
934 * @return freshly allocated, null-terminated string
935 */
936char * 749char *
937GNUNET_STRINGS_data_to_string_alloc (const void *buf, size_t size) 750GNUNET_STRINGS_data_to_string_alloc (const void *buf, size_t size)
938{ 751{
@@ -958,17 +771,7 @@ GNUNET_STRINGS_data_to_string_alloc (const void *buf, size_t size)
958} 771}
959 772
960 773
961/** 774enum GNUNET_GenericReturnValue
962 * Convert Crockford Base32hex encoding back to data.
963 * @a out_size must match exactly the size of the data before it was encoded.
964 *
965 * @param enc the encoding
966 * @param enclen number of characters in @a enc (without 0-terminator, which can be missing)
967 * @param out location where to store the decoded data
968 * @param out_size size of the output buffer @a out
969 * @return #GNUNET_OK on success, #GNUNET_SYSERR if result has the wrong encoding
970 */
971int
972GNUNET_STRINGS_string_to_data (const char *enc, 775GNUNET_STRINGS_string_to_data (const char *enc,
973 size_t enclen, 776 size_t enclen,
974 void *out, 777 void *out,
@@ -1034,23 +837,49 @@ GNUNET_STRINGS_string_to_data (const char *enc,
1034} 837}
1035 838
1036 839
1037/** 840enum GNUNET_GenericReturnValue
1038 * Parse a path that might be an URI. 841GNUNET_STRINGS_string_to_data_alloc (const char *enc,
1039 * 842 size_t enclen,
1040 * @param path path to parse. Must be NULL-terminated. 843 void **out,
1041 * @param scheme_part a pointer to 'char *' where a pointer to a string that 844 size_t *out_size)
1042 * represents the URI scheme will be stored. Can be NULL. The string is 845{
1043 * allocated by the function, and should be freed by GNUNET_free() when 846 size_t size;
1044 * it is no longer needed. 847 void *data;
1045 * @param path_part a pointer to 'const char *' where a pointer to the path 848 int res;
1046 * part of the URI will be stored. Can be NULL. Points to the same block 849
1047 * of memory as 'path', and thus must not be freed. Might point to '\0', 850 size = (enclen * 5) / 8;
1048 * if path part is zero-length. 851 if (size >= GNUNET_MAX_MALLOC_CHECKED)
1049 * @return GNUNET_YES if it's an URI, GNUNET_NO otherwise. If 'path' is not 852 {
1050 * an URI, '* scheme_part' and '*path_part' will remain unchanged 853 GNUNET_break_op (0);
1051 * (if they weren't NULL). 854 return GNUNET_SYSERR;
1052 */ 855 }
1053int 856 data = GNUNET_malloc (size);
857 res = GNUNET_STRINGS_string_to_data (enc,
858 enclen,
859 data,
860 size);
861 if ( (0 < size) &&
862 (GNUNET_OK != res) )
863 {
864 size--;
865 res = GNUNET_STRINGS_string_to_data (enc,
866 enclen,
867 data,
868 size);
869 }
870 if (GNUNET_OK != res)
871 {
872 GNUNET_break_op (0);
873 GNUNET_free (data);
874 return GNUNET_SYSERR;
875 }
876 *out = data;
877 *out_size = size;
878 return GNUNET_OK;
879}
880
881
882enum GNUNET_GenericReturnValue
1054GNUNET_STRINGS_parse_uri (const char *path, 883GNUNET_STRINGS_parse_uri (const char *path,
1055 char **scheme_part, 884 char **scheme_part,
1056 const char **path_part) 885 const char **path_part)
@@ -1112,21 +941,7 @@ GNUNET_STRINGS_parse_uri (const char *path,
1112} 941}
1113 942
1114 943
1115/** 944enum GNUNET_GenericReturnValue
1116 * Check whether @a filename is absolute or not, and if it's an URI
1117 *
1118 * @param filename filename to check
1119 * @param can_be_uri #GNUNET_YES to check for being URI, #GNUNET_NO - to
1120 * assume it's not URI
1121 * @param r_is_uri a pointer to an int that is set to #GNUNET_YES if @a filename
1122 * is URI and to #GNUNET_NO otherwise. Can be NULL. If @a can_be_uri is
1123 * not #GNUNET_YES, `* r_is_uri` is set to #GNUNET_NO.
1124 * @param r_uri_scheme a pointer to a char * that is set to a pointer to URI scheme.
1125 * The string is allocated by the function, and should be freed with
1126 * GNUNET_free(). Can be NULL.
1127 * @return #GNUNET_YES if @a filename is absolute, #GNUNET_NO otherwise.
1128 */
1129int
1130GNUNET_STRINGS_path_is_absolute (const char *filename, 945GNUNET_STRINGS_path_is_absolute (const char *filename,
1131 int can_be_uri, 946 int can_be_uri,
1132 int *r_is_uri, 947 int *r_is_uri,
@@ -1168,15 +983,7 @@ GNUNET_STRINGS_path_is_absolute (const char *filename,
1168} 983}
1169 984
1170 985
1171/** 986enum GNUNET_GenericReturnValue
1172 * Perform @a checks on @a filename.
1173 *
1174 * @param filename file to check
1175 * @param checks checks to perform
1176 * @return #GNUNET_YES if all checks pass, #GNUNET_NO if at least one of them
1177 * fails, #GNUNET_SYSERR when a check can't be performed
1178 */
1179int
1180GNUNET_STRINGS_check_filename (const char *filename, 987GNUNET_STRINGS_check_filename (const char *filename,
1181 enum GNUNET_STRINGS_FilenameCheck checks) 988 enum GNUNET_STRINGS_FilenameCheck checks)
1182{ 989{
@@ -1209,19 +1016,7 @@ GNUNET_STRINGS_check_filename (const char *filename,
1209} 1016}
1210 1017
1211 1018
1212/** 1019enum GNUNET_GenericReturnValue
1213 * Tries to convert @a zt_addr string to an IPv6 address.
1214 * The string is expected to have the format "[ABCD::01]:80".
1215 *
1216 * @param zt_addr 0-terminated string. May be mangled by the function.
1217 * @param addrlen length of @a zt_addr (not counting 0-terminator).
1218 * @param r_buf a buffer to fill. Initially gets filled with zeroes,
1219 * then its sin6_port, sin6_family and sin6_addr are set appropriately.
1220 * @return #GNUNET_OK if conversion succeeded.
1221 * #GNUNET_SYSERR otherwise, in which
1222 * case the contents of @a r_buf are undefined.
1223 */
1224int
1225GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr, 1020GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr,
1226 uint16_t addrlen, 1021 uint16_t addrlen,
1227 struct sockaddr_in6 *r_buf) 1022 struct sockaddr_in6 *r_buf)
@@ -1284,18 +1079,7 @@ GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr,
1284} 1079}
1285 1080
1286 1081
1287/** 1082enum GNUNET_GenericReturnValue
1288 * Tries to convert 'zt_addr' string to an IPv4 address.
1289 * The string is expected to have the format "1.2.3.4:80".
1290 *
1291 * @param zt_addr 0-terminated string. May be mangled by the function.
1292 * @param addrlen length of @a zt_addr (not counting 0-terminator).
1293 * @param r_buf a buffer to fill.
1294 * @return #GNUNET_OK if conversion succeeded.
1295 * #GNUNET_SYSERR otherwise, in which case
1296 * the contents of @a r_buf are undefined.
1297 */
1298int
1299GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr, 1083GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr,
1300 uint16_t addrlen, 1084 uint16_t addrlen,
1301 struct sockaddr_in *r_buf) 1085 struct sockaddr_in *r_buf)
@@ -1333,18 +1117,7 @@ GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr,
1333} 1117}
1334 1118
1335 1119
1336/** 1120enum GNUNET_GenericReturnValue
1337 * Tries to convert @a addr string to an IP (v4 or v6) address.
1338 * Will automatically decide whether to treat 'addr' as v4 or v6 address.
1339 *
1340 * @param addr a string, may not be 0-terminated.
1341 * @param addrlen number of bytes in @a addr (if addr is 0-terminated,
1342 * 0-terminator should not be counted towards addrlen).
1343 * @param r_buf a buffer to fill.
1344 * @return #GNUNET_OK if conversion succeeded. #GNUNET_SYSERR otherwise, in which
1345 * case the contents of @a r_buf are undefined.
1346 */
1347int
1348GNUNET_STRINGS_to_address_ip (const char *addr, 1121GNUNET_STRINGS_to_address_ip (const char *addr,
1349 uint16_t addrlen, 1122 uint16_t addrlen,
1350 struct sockaddr_storage *r_buf) 1123 struct sockaddr_storage *r_buf)
@@ -1359,15 +1132,6 @@ GNUNET_STRINGS_to_address_ip (const char *addr,
1359} 1132}
1360 1133
1361 1134
1362/**
1363 * Parse an address given as a string into a
1364 * `struct sockaddr`.
1365 *
1366 * @param addr the address
1367 * @param[out] af set to the parsed address family (e.g. AF_INET)
1368 * @param[out] sa set to the parsed address
1369 * @return 0 on error, otherwise number of bytes in @a sa
1370 */
1371size_t 1135size_t
1372GNUNET_STRINGS_parse_socket_addr (const char *addr, 1136GNUNET_STRINGS_parse_socket_addr (const char *addr,
1373 uint8_t *af, 1137 uint8_t *af,
@@ -1441,21 +1205,7 @@ _make_continuous_arg_copy (int argc, char *const *argv)
1441} 1205}
1442 1206
1443 1207
1444/** 1208enum GNUNET_GenericReturnValue
1445 * Returns utf-8 encoded arguments.
1446 * Does nothing (returns a copy of argc and argv) on any platform
1447 * other than W32.
1448 * Returned argv has u8argv[u8argc] == NULL.
1449 * Returned argv is a single memory block, and can be freed with a single
1450 * GNUNET_free() call.
1451 *
1452 * @param argc argc (as given by main())
1453 * @param argv argv (as given by main())
1454 * @param u8argc a location to store new argc in (though it's th same as argc)
1455 * @param u8argv a location to store new argv in
1456 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
1457 */
1458int
1459GNUNET_STRINGS_get_utf8_args (int argc, 1209GNUNET_STRINGS_get_utf8_args (int argc,
1460 char *const *argv, 1210 char *const *argv,
1461 int *u8argc, 1211 int *u8argc,
@@ -1478,7 +1228,7 @@ GNUNET_STRINGS_get_utf8_args (int argc,
1478 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the 1228 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
1479 * @a port_policy is malformed 1229 * @a port_policy is malformed
1480 */ 1230 */
1481static int 1231static enum GNUNET_GenericReturnValue
1482parse_port_policy (const char *port_policy, 1232parse_port_policy (const char *port_policy,
1483 struct GNUNET_STRINGS_PortPolicy *pp) 1233 struct GNUNET_STRINGS_PortPolicy *pp)
1484{ 1234{
@@ -1523,18 +1273,6 @@ parse_port_policy (const char *port_policy,
1523} 1273}
1524 1274
1525 1275
1526/**
1527 * Parse an IPv4 network policy. The argument specifies a list of
1528 * subnets. The format is
1529 * <tt>(network[/netmask][:SPORT[-DPORT]];)*</tt> (no whitespace, must
1530 * be terminated with a semicolon). The network must be given in
1531 * dotted-decimal notation. The netmask can be given in CIDR notation
1532 * (/16) or in dotted-decimal (/255.255.0.0).
1533 *
1534 * @param routeListX a string specifying the IPv4 subnets
1535 * @return the converted list, terminated with all zeros;
1536 * NULL if the synatx is flawed
1537 */
1538struct GNUNET_STRINGS_IPv4NetworkPolicy * 1276struct GNUNET_STRINGS_IPv4NetworkPolicy *
1539GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX) 1277GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX)
1540{ 1278{
@@ -1716,17 +1454,6 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX)
1716} 1454}
1717 1455
1718 1456
1719/**
1720 * Parse an IPv6 network policy. The argument specifies a list of
1721 * subnets. The format is <tt>(network[/netmask[:SPORT[-DPORT]]];)*</tt>
1722 * (no whitespace, must be terminated with a semicolon). The network
1723 * must be given in colon-hex notation. The netmask must be given in
1724 * CIDR notation (/16) or can be omitted to specify a single host.
1725 * Note that the netmask is mandatory if ports are specified.
1726 *
1727 * @param routeListX a string specifying the policy
1728 * @return the converted list, 0-terminated, NULL if the synatx is flawed
1729 */
1730struct GNUNET_STRINGS_IPv6NetworkPolicy * 1457struct GNUNET_STRINGS_IPv6NetworkPolicy *
1731GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX) 1458GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX)
1732{ 1459{
@@ -1863,17 +1590,10 @@ static char *cvt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1863 "0123456789+/"; 1590 "0123456789+/";
1864 1591
1865 1592
1866/**
1867 * Encode into Base64.
1868 *
1869 * @param in the data to encode
1870 * @param len the length of the input
1871 * @param output where to write the output (*output should be NULL,
1872 * is allocated)
1873 * @return the size of the output
1874 */
1875size_t 1593size_t
1876GNUNET_STRINGS_base64_encode (const void *in, size_t len, char **output) 1594GNUNET_STRINGS_base64_encode (const void *in,
1595 size_t len,
1596 char **output)
1877{ 1597{
1878 const char *data = in; 1598 const char *data = in;
1879 size_t ret; 1599 size_t ret;
@@ -1919,17 +1639,10 @@ GNUNET_STRINGS_base64_encode (const void *in, size_t len, char **output)
1919} 1639}
1920 1640
1921 1641
1922/**
1923 * Encode into Base64url. RFC7515
1924 *
1925 * @param in the data to encode
1926 * @param len the length of the input
1927 * @param output where to write the output (*output should be NULL,
1928 * is allocated)
1929 * @return the size of the output
1930 */
1931size_t 1642size_t
1932GNUNET_STRINGS_base64url_encode (const void *in, size_t len, char **output) 1643GNUNET_STRINGS_base64url_encode (const void *in,
1644 size_t len,
1645 char **output)
1933{ 1646{
1934 char *enc; 1647 char *enc;
1935 size_t pos; 1648 size_t pos;
@@ -1965,17 +1678,10 @@ GNUNET_STRINGS_base64url_encode (const void *in, size_t len, char **output)
1965 : ((a) == '+') ? 62 : ((a) == '/') ? 63 : -1) 1678 : ((a) == '+') ? 62 : ((a) == '/') ? 63 : -1)
1966 1679
1967 1680
1968/**
1969 * Decode from Base64.
1970 *
1971 * @param data the data to encode
1972 * @param len the length of the input
1973 * @param output where to write the output (*output should be NULL,
1974 * is allocated)
1975 * @return the size of the output
1976 */
1977size_t 1681size_t
1978GNUNET_STRINGS_base64_decode (const char *data, size_t len, void **out) 1682GNUNET_STRINGS_base64_decode (const char *data,
1683 size_t len,
1684 void **out)
1979{ 1685{
1980 char *output; 1686 char *output;
1981 size_t ret = 0; 1687 size_t ret = 0;
@@ -2037,17 +1743,10 @@ END:
2037} 1743}
2038 1744
2039 1745
2040/**
2041 * Decode from Base64url. RFC7515
2042 *
2043 * @param data the data to decode
2044 * @param len the length of the input
2045 * @param output where to write the output (*output should be NULL,
2046 * is allocated)
2047 * @return the size of the output
2048 */
2049size_t 1746size_t
2050GNUNET_STRINGS_base64url_decode (const char *data, size_t len, void **out) 1747GNUNET_STRINGS_base64url_decode (const char *data,
1748 size_t len,
1749 void **out)
2051{ 1750{
2052 char *s; 1751 char *s;
2053 int padding; 1752 int padding;
@@ -2090,17 +1789,10 @@ GNUNET_STRINGS_base64url_decode (const char *data, size_t len, void **out)
2090} 1789}
2091 1790
2092 1791
2093/**
2094 * url/percent encode (RFC3986).
2095 *
2096 * @param data the data to encode
2097 * @param len the length of the input
2098 * @param output where to write the output (*output should be NULL,
2099 * is allocated)
2100 * @return the size of the output
2101 */
2102size_t 1792size_t
2103GNUNET_STRINGS_urldecode (const char *data, size_t len, char **out) 1793GNUNET_STRINGS_urldecode (const char *data,
1794 size_t len,
1795 char **out)
2104{ 1796{
2105 const char *rpos = data; 1797 const char *rpos = data;
2106 *out = GNUNET_malloc (len + 1); /* output should always fit into input */ 1798 *out = GNUNET_malloc (len + 1); /* output should always fit into input */
@@ -2134,17 +1826,10 @@ GNUNET_STRINGS_urldecode (const char *data, size_t len, char **out)
2134} 1826}
2135 1827
2136 1828
2137/**
2138 * url/percent encode (RFC3986).
2139 *
2140 * @param data the data to decode
2141 * @param len the length of the input
2142 * @param output where to write the output (*output should be NULL,
2143 * is allocated)
2144 * @return the size of the output
2145 */
2146size_t 1829size_t
2147GNUNET_STRINGS_urlencode (const char *data, size_t len, char **out) 1830GNUNET_STRINGS_urlencode (const char *data,
1831 size_t len,
1832 char **out)
2148{ 1833{
2149 struct GNUNET_Buffer buf = { 0 }; 1834 struct GNUNET_Buffer buf = { 0 };
2150 const uint8_t *i8 = (uint8_t *) data; 1835 const uint8_t *i8 = (uint8_t *) data;