adding a GNUNET_memcmp_priv for constant-time comparing of data; fixes #6152 (modulo...
[oweals/gnunet.git] / src / nse / nse_api.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009, 2010, 2011, 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 /**
22  * @file nse/nse_api.c
23  * @brief api to get information from the network size estimation service
24  * @author Nathan Evans
25  */
26 #include "platform.h"
27 #include "gnunet_constants.h"
28 #include "gnunet_arm_service.h"
29 #include "gnunet_hello_lib.h"
30 #include "gnunet_protocols.h"
31 #include "gnunet_util_lib.h"
32 #include "gnunet_nse_service.h"
33 #include "nse.h"
34
35 #define LOG(kind, ...) GNUNET_log_from (kind, "nse-api", __VA_ARGS__)
36
37 /**
38  * Handle for talking with the NSE service.
39  */
40 struct GNUNET_NSE_Handle
41 {
42   /**
43    * Configuration to use.
44    */
45   const struct GNUNET_CONFIGURATION_Handle *cfg;
46
47   /**
48    * Message queue (if available).
49    */
50   struct GNUNET_MQ_Handle *mq;
51
52   /**
53    * Task doing exponential back-off trying to reconnect.
54    */
55   struct GNUNET_SCHEDULER_Task *reconnect_task;
56
57   /**
58    * Time for next connect retry.
59    */
60   struct GNUNET_TIME_Relative reconnect_delay;
61
62   /**
63    * Callback function to call when message is received.
64    */
65   GNUNET_NSE_Callback recv_cb;
66
67   /**
68    * Closure to pass to @e recv_cb callback.
69    */
70   void *recv_cb_cls;
71 };
72
73
74 /**
75  * Try again to connect to network size estimation service.
76  *
77  * @param cls closure with the `struct GNUNET_NSE_Handle *`
78  */
79 static void
80 reconnect (void *cls);
81
82
83 /**
84  * Generic error handler, called with the appropriate
85  * error code and the same closure specified at the creation of
86  * the message queue.
87  * Not every message queue implementation supports an error handler.
88  *
89  * @param cls closure with the `struct GNUNET_NSE_Handle *`
90  * @param error error code
91  */
92 static void
93 mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
94 {
95   struct GNUNET_NSE_Handle *h = cls;
96
97   (void) error;
98   GNUNET_MQ_destroy (h->mq);
99   h->mq = NULL;
100   h->reconnect_task =
101     GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h);
102   h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
103 }
104
105
106 /**
107  * Type of a function to call when we receive a message
108  * from the service.
109  *
110  * @param cls closure
111  * @param client_msg message received
112  */
113 static void
114 handle_estimate (void *cls, const struct GNUNET_NSE_ClientMessage *client_msg)
115 {
116   struct GNUNET_NSE_Handle *h = cls;
117
118   h->reconnect_delay = GNUNET_TIME_UNIT_ZERO;
119   h->recv_cb (h->recv_cb_cls,
120               GNUNET_TIME_absolute_ntoh (client_msg->timestamp),
121               GNUNET_ntoh_double (client_msg->size_estimate),
122               GNUNET_ntoh_double (client_msg->std_deviation));
123 }
124
125
126 /**
127  * Try again to connect to network size estimation service.
128  *
129  * @param cls the `struct GNUNET_NSE_Handle *`
130  */
131 static void
132 reconnect (void *cls)
133 {
134   struct GNUNET_NSE_Handle *h = cls;
135   struct GNUNET_MQ_MessageHandler handlers[] =
136   { GNUNET_MQ_hd_fixed_size (estimate,
137                              GNUNET_MESSAGE_TYPE_NSE_ESTIMATE,
138                              struct GNUNET_NSE_ClientMessage,
139                              h),
140     GNUNET_MQ_handler_end () };
141   struct GNUNET_MessageHeader *msg;
142   struct GNUNET_MQ_Envelope *env;
143
144   h->reconnect_task = NULL;
145   LOG (GNUNET_ERROR_TYPE_DEBUG,
146        "Connecting to network size estimation service.\n");
147   GNUNET_assert (NULL == h->mq);
148   h->mq = GNUNET_CLIENT_connect (h->cfg, "nse", handlers, &mq_error_handler, h);
149   if (NULL == h->mq)
150     return;
151   env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NSE_START);
152   GNUNET_MQ_send (h->mq, env);
153 }
154
155
156 /**
157  * Connect to the network size estimation service.
158  *
159  * @param cfg the configuration to use
160  * @param func funtion to call with network size estimate
161  * @param func_cls closure to pass to @a func
162  * @return handle to use
163  */
164 struct GNUNET_NSE_Handle *
165 GNUNET_NSE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
166                     GNUNET_NSE_Callback func,
167                     void *func_cls)
168 {
169   struct GNUNET_NSE_Handle *h;
170
171   GNUNET_assert (NULL != func);
172   h = GNUNET_new (struct GNUNET_NSE_Handle);
173   h->cfg = cfg;
174   h->recv_cb = func;
175   h->recv_cb_cls = func_cls;
176   h->reconnect_delay = GNUNET_TIME_UNIT_ZERO;
177   reconnect (h);
178   if (NULL == h->mq)
179   {
180     GNUNET_free (h);
181     return NULL;
182   }
183   return h;
184 }
185
186
187 /**
188  * Disconnect from network size estimation service
189  *
190  * @param h handle to destroy
191  */
192 void
193 GNUNET_NSE_disconnect (struct GNUNET_NSE_Handle *h)
194 {
195   if (NULL != h->reconnect_task)
196   {
197     GNUNET_SCHEDULER_cancel (h->reconnect_task);
198     h->reconnect_task = NULL;
199   }
200   if (NULL != h->mq)
201   {
202     GNUNET_MQ_destroy (h->mq);
203     h->mq = NULL;
204   }
205   GNUNET_free (h);
206 }
207
208
209 /* end of nse_api.c */