merge
[oweals/gnunet.git] / src / core / core_api_monitor_peers.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009-2014, 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 /**
20  * @file core/core_api_monitor_peers.c
21  * @brief implementation of the peer_iterate function
22  * @author Christian Grothoff
23  * @author Nathan Evans
24  */
25 #include "platform.h"
26 #include "gnunet_core_service.h"
27 #include "core.h"
28
29
30 /**
31  * Handle to a CORE monitoring operation.
32  */
33 struct GNUNET_CORE_MonitorHandle
34 {
35
36   /**
37    * Our configuration.
38    */
39   const struct GNUNET_CONFIGURATION_Handle *cfg;
40
41   /**
42    * Our connection to the service.
43    */
44   struct GNUNET_MQ_Handle *mq;
45
46   /**
47    * Function called with the peer.
48    */
49   GNUNET_CORE_MonitorCallback peer_cb;
50
51   /**
52    * Closure for @e peer_cb.
53    */
54   void *peer_cb_cls;
55
56 };
57
58
59 /**
60  * Protocol error, reconnect to CORE service and notify
61  * client.
62  *
63  * @param mh monitoring session to reconnect to CORE
64  */
65 static void
66 reconnect (struct GNUNET_CORE_MonitorHandle *mh);
67
68
69 /**
70  * Generic error handler, called with the appropriate error code and
71  * the same closure specified at the creation of the message queue.
72  * Not every message queue implementation supports an error handler.
73  *
74  * @param cls closure, a `struct GNUNET_CORE_MonitorHandle *`
75  * @param error error code
76  */
77 static void
78 handle_mq_error (void *cls,
79                  enum GNUNET_MQ_Error error)
80 {
81   struct GNUNET_CORE_MonitorHandle *mh = cls;
82
83   reconnect (mh);
84 }
85
86
87 /**
88  * Receive reply from CORE service with information about a peer.
89  *
90  * @param cls our `struct  GNUNET_CORE_MonitorHandle *`
91  * @param mon_message monitor message
92  */
93 static void
94 handle_receive_info (void *cls,
95                      const struct MonitorNotifyMessage *mon_message)
96 {
97   struct GNUNET_CORE_MonitorHandle *mh = cls;
98
99   mh->peer_cb (mh->peer_cb_cls,
100                &mon_message->peer,
101                (enum GNUNET_CORE_KxState) ntohl (mon_message->state),
102                GNUNET_TIME_absolute_ntoh (mon_message->timeout));
103 }
104
105
106 /**
107  * Protocol error, reconnect to CORE service and notify
108  * client.
109  *
110  * @param mh monitoring session to reconnect to CORE
111  */
112 static void
113 reconnect (struct GNUNET_CORE_MonitorHandle *mh)
114 {
115   struct GNUNET_MQ_MessageHandler handlers[] = {
116     GNUNET_MQ_hd_fixed_size (receive_info,
117                              GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY,
118                              struct MonitorNotifyMessage,
119                              mh),
120     GNUNET_MQ_handler_end ()
121   };
122   struct GNUNET_MQ_Envelope *env;
123   struct GNUNET_MessageHeader *msg;
124
125   if (NULL != mh->mq)
126     GNUNET_MQ_destroy (mh->mq);
127   /* FIXME: use backoff? */
128   mh->mq = GNUNET_CLIENT_connect (mh->cfg,
129                                   "core",
130                                   handlers,
131                                   &handle_mq_error,
132                                   mh);
133   if (NULL == mh->mq)
134     return;
135   /* notify callback about reconnect */
136   mh->peer_cb (mh->peer_cb_cls,
137                NULL,
138                GNUNET_CORE_KX_CORE_DISCONNECT,
139                GNUNET_TIME_UNIT_FOREVER_ABS);
140   env = GNUNET_MQ_msg (msg,
141                        GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS);
142   GNUNET_MQ_send (mh->mq,
143                   env);
144 }
145
146
147 /**
148  * Monitor connectivity and KX status of all peers known to CORE.
149  * Calls @a peer_cb with the current status for each connected peer,
150  * and then once with NULL to indicate that all peers that are
151  * currently active have been handled.  After that, the iteration
152  * continues until it is cancelled.  Normal users of the CORE API are
153  * not expected to use this function.  It is different in that it
154  * truly lists all connections (including those where the KX is in
155  * progress), not just those relevant to the application.  This
156  * function is used by special applications for diagnostics.
157  *
158  * @param cfg configuration handle
159  * @param peer_cb function to call with the peer information
160  * @param peer_cb_cls closure for @a peer_cb
161  * @return NULL on error
162  */
163 struct GNUNET_CORE_MonitorHandle *
164 GNUNET_CORE_monitor_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
165                            GNUNET_CORE_MonitorCallback peer_cb,
166                            void *peer_cb_cls)
167 {
168   struct GNUNET_CORE_MonitorHandle *mh;
169
170   GNUNET_assert (NULL != peer_cb);
171   mh = GNUNET_new (struct GNUNET_CORE_MonitorHandle);
172   mh->cfg = cfg;
173   mh->peer_cb = peer_cb;
174   mh->peer_cb_cls = peer_cb_cls;
175   reconnect (mh);
176   if (NULL == mh->mq)
177   {
178     GNUNET_free (mh);
179     return NULL;
180   }
181   return mh;
182 }
183
184
185 /**
186  * Stop monitoring CORE activity.
187  *
188  * @param mh monitor to stop
189  */
190 void
191 GNUNET_CORE_monitor_stop (struct GNUNET_CORE_MonitorHandle *mh)
192 {
193   if (NULL != mh->mq)
194   {
195     GNUNET_MQ_destroy (mh->mq);
196     mh->mq = NULL;
197   }
198   GNUNET_free (mh);
199 }
200
201
202 /* end of core_api_monitor_peers.c */