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