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