error handling
[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      SPDX-License-Identifier: AGPL3.0-or-later
19  */
20
21 /**
22  * @file core/core_api_monitor_peers.c
23  * @brief implementation of the peer_iterate function
24  * @author Christian Grothoff
25  * @author Nathan Evans
26  */
27 #include "platform.h"
28 #include "gnunet_core_service.h"
29 #include "core.h"
30
31
32 /**
33  * Handle to a CORE monitoring operation.
34  */
35 struct GNUNET_CORE_MonitorHandle
36 {
37   /**
38    * Our configuration.
39    */
40   const struct GNUNET_CONFIGURATION_Handle *cfg;
41
42   /**
43    * Our connection to the service.
44    */
45   struct GNUNET_MQ_Handle *mq;
46
47   /**
48    * Function called with the peer.
49    */
50   GNUNET_CORE_MonitorCallback peer_cb;
51
52   /**
53    * Closure for @e peer_cb.
54    */
55   void *peer_cb_cls;
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, enum GNUNET_MQ_Error error)
79 {
80   struct GNUNET_CORE_MonitorHandle *mh = cls;
81
82   (void) error;
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, const struct MonitorNotifyMessage *mon_message)
95 {
96   struct GNUNET_CORE_MonitorHandle *mh = cls;
97
98   mh->peer_cb (mh->peer_cb_cls,
99                &mon_message->peer,
100                (enum GNUNET_CORE_KxState) ntohl (mon_message->state),
101                GNUNET_TIME_absolute_ntoh (mon_message->timeout));
102 }
103
104
105 /**
106  * Protocol error, reconnect to CORE service and notify
107  * client.
108  *
109  * @param mh monitoring session to reconnect to CORE
110  */
111 static void
112 reconnect (struct GNUNET_CORE_MonitorHandle *mh)
113 {
114   struct GNUNET_MQ_MessageHandler handlers[] =
115   { GNUNET_MQ_hd_fixed_size (receive_info,
116                              GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY,
117                              struct MonitorNotifyMessage,
118                              mh),
119     GNUNET_MQ_handler_end () };
120   struct GNUNET_MQ_Envelope *env;
121   struct GNUNET_MessageHeader *msg;
122
123   if (NULL != mh->mq)
124     GNUNET_MQ_destroy (mh->mq);
125   /* FIXME: use backoff? */
126   mh->mq =
127     GNUNET_CLIENT_connect (mh->cfg, "core", handlers, &handle_mq_error, mh);
128   if (NULL == mh->mq)
129     return;
130   /* notify callback about reconnect */
131   if (NULL != mh->peer_cb)
132     mh->peer_cb (mh->peer_cb_cls,
133                  NULL,
134                  GNUNET_CORE_KX_CORE_DISCONNECT,
135                  GNUNET_TIME_UNIT_FOREVER_ABS);
136   env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS);
137   GNUNET_MQ_send (mh->mq, env);
138 }
139
140
141 /**
142  * Monitor connectivity and KX status of all peers known to CORE.
143  * Calls @a peer_cb with the current status for each connected peer,
144  * and then once with NULL to indicate that all peers that are
145  * currently active have been handled.  After that, the iteration
146  * continues until it is cancelled.  Normal users of the CORE API are
147  * not expected to use this function.  It is different in that it
148  * truly lists all connections (including those where the KX is in
149  * progress), not just those relevant to the application.  This
150  * function is used by special applications for diagnostics.
151  *
152  * @param cfg configuration handle
153  * @param peer_cb function to call with the peer information
154  * @param peer_cb_cls closure for @a peer_cb
155  * @return NULL on error
156  */
157 struct GNUNET_CORE_MonitorHandle *
158 GNUNET_CORE_monitor_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
159                            GNUNET_CORE_MonitorCallback peer_cb,
160                            void *peer_cb_cls)
161 {
162   struct GNUNET_CORE_MonitorHandle *mh;
163
164   GNUNET_assert (NULL != peer_cb);
165   mh = GNUNET_new (struct GNUNET_CORE_MonitorHandle);
166   mh->cfg = cfg;
167   reconnect (mh);
168   mh->peer_cb = peer_cb;
169   mh->peer_cb_cls = peer_cb_cls;
170   if (NULL == mh->mq)
171   {
172     GNUNET_free (mh);
173     return NULL;
174   }
175   return mh;
176 }
177
178
179 /**
180  * Stop monitoring CORE activity.
181  *
182  * @param mh monitor to stop
183  */
184 void
185 GNUNET_CORE_monitor_stop (struct GNUNET_CORE_MonitorHandle *mh)
186 {
187   if (NULL != mh->mq)
188   {
189     GNUNET_MQ_destroy (mh->mq);
190     mh->mq = NULL;
191   }
192   GNUNET_free (mh);
193 }
194
195
196 /* end of core_api_monitor_peers.c */