remove 'illegal' (non-reentrant) log logic from signal handler
[oweals/gnunet.git] / src / regex / regex_api_announce.c
1 /*
2      This file is part of GNUnet
3      Copyright (C) 2012, 2013, 2016 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 regex/regex_api_announce.c
22  * @brief access regex service to advertise capabilities via regex
23  * @author Maximilian Szengel
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_protocols.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_regex_service.h"
30 #include "regex_ipc.h"
31
32 #define LOG(kind, ...) GNUNET_log_from (kind, "regex-api", __VA_ARGS__)
33
34 /**
35  * Handle to store cached data about a regex announce.
36  */
37 struct GNUNET_REGEX_Announcement
38 {
39   /**
40    * Connection to the regex service.
41    */
42   struct GNUNET_MQ_Handle *mq;
43
44   /**
45    * Our configuration.
46    */
47   const struct GNUNET_CONFIGURATION_Handle *cfg;
48
49   /**
50    * Message we're sending to the service.
51    */
52   char *regex;
53
54   /**
55    * Frequency of announcements.
56    */
57   struct GNUNET_TIME_Relative refresh_delay;
58
59   /**
60    * Number of characters per edge.
61    */
62   uint16_t compression;
63 };
64
65
66 /**
67  * (Re)connect to the REGEX service with the given announcement @a a.
68  *
69  * @param a REGEX to announce.
70  */
71 static void
72 announce_reconnect (struct GNUNET_REGEX_Announcement *a);
73
74
75 /**
76  * We got a disconnect after asking regex to do the announcement.
77  * Retry.
78  *
79  * @param cls the `struct GNUNET_REGEX_Announcement` to retry
80  * @param error error code
81  */
82 static void
83 announce_mq_error_handler (void *cls,
84                            enum GNUNET_MQ_Error error)
85 {
86   struct GNUNET_REGEX_Announcement *a = cls;
87
88   GNUNET_MQ_destroy (a->mq);
89   a->mq = NULL;
90   announce_reconnect (a);
91 }
92
93
94 /**
95  * (Re)connect to the REGEX service with the given announcement @a a.
96  *
97  * @param a REGEX to announce.
98  */
99 static void
100 announce_reconnect (struct GNUNET_REGEX_Announcement *a)
101 {
102   struct GNUNET_MQ_Envelope *env;
103   struct AnnounceMessage *am;
104   size_t slen;
105
106   a->mq = GNUNET_CLIENT_connect (a->cfg,
107                                  "regex",
108                                  NULL,
109                                  &announce_mq_error_handler,
110                                  a);
111   if (NULL == a->mq)
112     return;
113   slen = strlen (a->regex) + 1;
114   env = GNUNET_MQ_msg_extra (am,
115                              slen,
116                              GNUNET_MESSAGE_TYPE_REGEX_ANNOUNCE);
117   am->compression = htons (a->compression);
118   am->reserved = htons (0);
119   am->refresh_delay = GNUNET_TIME_relative_hton (a->refresh_delay);
120   GNUNET_memcpy (&am[1],
121                  a->regex,
122                  slen);
123   GNUNET_MQ_send (a->mq,
124                   env);
125 }
126
127
128 /**
129  * Announce the given peer under the given regular expression.
130  *
131  * @param cfg configuration to use
132  * @param regex Regular expression to announce.
133  * @param refresh_delay after what delay should the announcement be repeated?
134  * @param compression How many characters per edge can we squeeze?
135  * @return Handle to reuse o free cached resources.
136  *         Must be freed by calling #GNUNET_REGEX_announce_cancel().
137  */
138 struct GNUNET_REGEX_Announcement *
139 GNUNET_REGEX_announce (const struct GNUNET_CONFIGURATION_Handle *cfg,
140                        const char *regex,
141                        struct GNUNET_TIME_Relative refresh_delay,
142                        uint16_t compression)
143 {
144   struct GNUNET_REGEX_Announcement *a;
145   size_t slen;
146
147   slen = strlen (regex) + 1;
148   if (slen + sizeof(struct AnnounceMessage) >= GNUNET_MAX_MESSAGE_SIZE)
149   {
150     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
151                 _ ("Regex `%s' is too long!\n"),
152                 regex);
153     GNUNET_break (0);
154     return NULL;
155   }
156   a = GNUNET_new (struct GNUNET_REGEX_Announcement);
157   a->cfg = cfg;
158   a->refresh_delay = refresh_delay;
159   a->compression = compression;
160   a->regex = GNUNET_strdup (regex);
161   announce_reconnect (a);
162   if (NULL == a->mq)
163   {
164     GNUNET_free (a->regex);
165     GNUNET_free (a);
166     return NULL;
167   }
168   return a;
169 }
170
171
172 /**
173  * Stop announcing the regex specified by the given handle.
174  *
175  * @param a handle returned by a previous #GNUNET_REGEX_announce() call.
176  */
177 void
178 GNUNET_REGEX_announce_cancel (struct GNUNET_REGEX_Announcement *a)
179 {
180   GNUNET_MQ_destroy (a->mq);
181   GNUNET_free (a->regex);
182   GNUNET_free (a);
183 }
184
185
186 /* end of regex_api_announce.c */