GNUnet  0.11.x
transport_api_monitor_plugins.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 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 
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_arm_service.h"
29 #include "gnunet_hello_lib.h"
30 #include "gnunet_protocols.h"
32 #include "transport.h"
33 
34 
39 {
44 
49 
54 
58  void *cb_cls;
59 
65 
70 
75 };
76 
77 
83 {
87  uint64_t session_id;
88 
92  void *client_ctx;
93 };
94 
95 
101 static void
102 do_plugin_connect (void *cls);
103 
104 
113 static int
114 free_entry (void *cls,
115  uint32_t key,
116  void *value)
117 {
118  struct GNUNET_TRANSPORT_PluginMonitor *pm = cls;
120 
121  pm->cb (pm->cb_cls,
122  ps,
123  &ps->client_ctx,
124  NULL);
127  key,
128  ps));
129  GNUNET_break (NULL == ps->client_ctx);
130  GNUNET_free (ps);
131  return GNUNET_OK;
132 }
133 
134 
140 static void
142 {
143  GNUNET_MQ_destroy (pm->mq);
144  pm->mq = NULL;
146  &free_entry,
147  pm);
151  pm);
152 }
153 
154 
161 static uint32_t
162 wrap_id (uint64_t id)
163 {
164  return ((uint32_t) id) ^ ((uint32_t) (id >> 32));
165 }
166 
167 
171 struct SearchContext
172 {
177 
181  uint64_t session_id;
182 };
183 
184 
193 static int
194 locate_by_id (void *cls,
195  uint32_t key,
196  void *value)
197 {
198  struct SearchContext *sc = cls;
200 
201  if (sc->session_id == ps->session_id)
202  {
203  sc->ps = ps;
204  return GNUNET_SYSERR;
205  }
206  return GNUNET_OK;
207 }
208 
209 
217 static int
218 check_event (void *cls,
219  const struct TransportPluginMonitorMessage *tpmm)
220 {
221  const char *pname;
222  size_t pname_len;
223  size_t paddr_len;
224 
225  pname = (const char *) &tpmm[1];
226  pname_len = ntohs (tpmm->plugin_name_len);
227  paddr_len = ntohs (tpmm->plugin_address_len);
228  if ((pname_len
229  + paddr_len
230  + sizeof(struct TransportPluginMonitorMessage) != ntohs (
231  tpmm->header.size)) ||
232  ((0 != pname_len) &&
233  ('\0' != pname[pname_len - 1])))
234  {
235  GNUNET_break (0);
236  return GNUNET_SYSERR;
237  }
238  return GNUNET_OK;
239 }
240 
241 
248 static void
249 handle_event (void *cls,
250  const struct TransportPluginMonitorMessage *tpmm)
251 {
252  struct GNUNET_TRANSPORT_PluginMonitor *pm = cls;
254  const char *pname;
255  const void *paddr;
257  size_t pname_len;
258  size_t paddr_len;
259  struct GNUNET_TRANSPORT_SessionInfo info;
260  struct GNUNET_HELLO_Address addr;
261  struct SearchContext rv;
262 
263  pname = (const char *) &tpmm[1];
264  pname_len = ntohs (tpmm->plugin_name_len);
265  paddr_len = ntohs (tpmm->plugin_address_len);
266  paddr = &pname[pname_len];
267  ps = NULL;
268  ss = (enum GNUNET_TRANSPORT_SessionState) ntohs (tpmm->session_state);
269  if (GNUNET_TRANSPORT_SS_INIT == ss)
270  {
272  ps->session_id = tpmm->session_id;
274  wrap_id (tpmm->session_id),
275  ps,
277  }
278  else
279  {
280  rv.session_id = tpmm->session_id;
281  rv.ps = NULL;
283  wrap_id (
284  tpmm->session_id),
285  &locate_by_id,
286  &rv);
287  ps = rv.ps;
288  if (NULL == ps)
289  {
290  GNUNET_break (0);
292  return;
293  }
294  }
295  info.state = ss;
296  info.is_inbound = (int16_t) ntohs (tpmm->is_inbound);
297  info.num_msg_pending = ntohl (tpmm->msgs_pending);
298  info.num_bytes_pending = ntohl (tpmm->bytes_pending);
301  info.address = &addr;
302  addr.peer = tpmm->peer;
303  addr.address = (0 == paddr_len) ? NULL : paddr;
304  addr.address_length = paddr_len;
305  addr.transport_name = (0 == pname_len) ? NULL : pname;
307  pm->cb (pm->cb_cls,
308  ps,
309  &ps->client_ctx,
310  &info);
311 
312  if (GNUNET_TRANSPORT_SS_DONE == ss)
313  {
314  GNUNET_break (NULL == ps->client_ctx);
317  wrap_id (
318  tpmm->session_id),
319  ps));
320  GNUNET_free (ps);
321  }
322 }
323 
324 
331 static void
332 handle_sync (void *cls,
333  const struct GNUNET_MessageHeader *msg)
334 {
335  struct GNUNET_TRANSPORT_PluginMonitor *pm = cls;
336 
337  /* we are in sync, notify callback */
338  pm->cb (pm->cb_cls,
339  NULL,
340  NULL,
341  NULL);
342 }
343 
344 
354 static void
355 mq_error_handler (void *cls,
356  enum GNUNET_MQ_Error error)
357 {
358  struct GNUNET_TRANSPORT_PluginMonitor *pm = cls;
359 
361 }
362 
363 
369 static void
370 do_plugin_connect (void *cls)
371 {
372  struct GNUNET_TRANSPORT_PluginMonitor *pm = cls;
373  struct GNUNET_MQ_MessageHandler handlers[] = {
374  GNUNET_MQ_hd_var_size (event,
377  pm),
380  struct GNUNET_MessageHeader,
381  pm),
383  };
384  struct GNUNET_MessageHeader *msg;
385  struct GNUNET_MQ_Envelope *env;
386 
387  pm->reconnect_task = NULL;
388  pm->mq = GNUNET_CLIENT_connect (pm->cfg,
389  "transport",
390  handlers,
392  pm);
393  if (NULL == pm->mq)
394  return;
395  env = GNUNET_MQ_msg (msg,
397  GNUNET_MQ_send (pm->mq,
398  env);
399 }
400 
401 
414  void *cb_cls)
415 {
417 
419  pm->cb = cb;
420  pm->cb_cls = cb_cls;
421  pm->cfg = cfg;
422  do_plugin_connect (pm);
423  if (NULL == pm->mq)
424  {
425  GNUNET_free (pm);
426  return NULL;
427  }
429  return pm;
430 }
431 
432 
441 void
444 {
445  if (NULL != pm->mq)
446  {
447  GNUNET_MQ_destroy (pm->mq);
448  pm->mq = NULL;
449  }
450  if (NULL != pm->reconnect_task)
451  {
453  pm->reconnect_task = NULL;
454  }
456  &free_entry,
457  pm);
459  GNUNET_free (pm);
460 }
461 
462 
463 /* end of transport_api_monitor_plugins.c */
uint64_t session_id
Unique session identifier.
size_t address_length
Number of bytes in address.
Session is being torn down and about to disappear.
enum GNUNET_HELLO_AddressInfo local_info
Extended information about address.
uint32_t num_bytes_pending
Number of bytes pending transmission for this session.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:673
static int free_entry(void *cls, uint32_t key, void *value)
Free the session entry and notify the callback about its demise.
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
const void * address
Binary representation of the address (plugin-specific).
#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PLUGIN_EVENT
Monitoring event about the connection state of plugins, generated in response to a subscription initi...
struct GNUNET_SCHEDULER_Task * reconnect_task
Task ID for reconnect.
common internal definitions for transport service
struct GNUNET_MQ_Handle * GNUNET_CLIENT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *service_name, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *error_handler_cls)
Create a message queue to connect to a GNUnet service.
Definition: client.c:1057
static void handle_event(void *cls, const struct TransportPluginMonitorMessage *tpmm)
Function called with responses from the service.
GNUNET_MQ_Error
Error codes for the queue.
int16_t is_inbound
GNUNET_YES if this is an inbound connection, GNUNET_NO if this is an outbound connection, GNUNET_SYSERR if connections of this plugin are so fundamentally bidirectional that they have no &#39;initiator&#39; Value given in NBO.
Definition: transport.h:629
int GNUNET_CONTAINER_multihashmap32_iterate(struct GNUNET_CONTAINER_MultiHashMap32 *map, GNUNET_CONTAINER_MulitHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map.
int is_inbound
GNUNET_YES if this is an inbound connection, GNUNET_NO if this is an outbound connection, GNUNET_SYSERR if connections of this plugin are so fundamentally bidirectional that they have no &#39;initiator&#39;
struct GNUNET_PeerIdentity peer
Which peer is this connection for?
Definition: transport.h:654
enum GNUNET_TRANSPORT_SessionState state
New state of the session.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_MQ_Handle * mq
Connection to the service.
Abstract representation of a plugin&#39;s session.
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
Handle for a plugin session state monitor.
GNUNET_TRANSPORT_SessionMonitorCallback cb
Callback to call.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_new(type)
Allocate a struct or union of the given type.
int GNUNET_CONTAINER_multihashmap32_get_multiple(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, GNUNET_CONTAINER_MulitHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map that match a particular key.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
const struct GNUNET_HELLO_Address * address
Address used by the session.
int GNUNET_CONTAINER_multihashmap32_put(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
uint32_t num_msg_pending
Number of messages pending transmission for this session.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_TIME_Absolute receive_delay
Until when does this plugin refuse to receive to manage staying within the inbound quota...
static int locate_by_id(void *cls, uint32_t key, void *value)
Locate a session entry.
Information about a plugin&#39;s session.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1253
int GNUNET_CONTAINER_multihashmap32_remove(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, const void *value)
Remove the given key-value pair from the map.
static char * value
Value of the record to add/remove.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
uint16_t plugin_name_len
Length of the plugin name in bytes, including 0-termination.
Definition: transport.h:664
uint16_t plugin_address_len
Length of the plugin address in bytes.
Definition: transport.h:669
const char * transport_name
Name of the transport plugin enabling the communication using this address.
struct GNUNET_TRANSPORT_PluginSession * ps
Result.
uint32_t msgs_pending
Number of messages waiting transmission.
Definition: transport.h:634
struct GNUNET_TIME_Absolute session_timeout
At what time will this session timeout (unless activity happens)?
struct GNUNET_TRANSPORT_PluginMonitor * GNUNET_TRANSPORT_monitor_plugins(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_TRANSPORT_SessionMonitorCallback cb, void *cb_cls)
Install a plugin session state monitor callback.
Internal representation of the hash map.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PLUGIN_START
Request to start monitoring the connection state of plugins.
Message handler for a specific message type.
struct GNUNET_CONTAINER_MultiHashMap32 * GNUNET_CONTAINER_multihashmap32_create(unsigned int len)
Create a 32-bit key multi hash map.
struct GNUNET_TIME_AbsoluteNBO timeout
When will this transport plugin session time out?
Definition: transport.h:644
void GNUNET_CONTAINER_multihashmap32_destroy(struct GNUNET_CONTAINER_MultiHashMap32 *map)
Destroy a 32-bit key hash map.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PLUGIN_SYNC
Monitoring event notifying client that the initial iteration is now completed and we are in sync with...
static void mq_error_handler(void *cls, enum GNUNET_MQ_Error error)
Generic error handler, called with the appropriate error code and the same closure specified at the c...
static uint32_t wrap_id(uint64_t id)
Convert 64-bit session ID to 32-bit index for hash map.
struct GNUNET_HashCode key
The key used in the DHT.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
struct GNUNET_TIME_Relative backoff
Backoff for reconnect.
Transport-level connection status update.
Definition: transport.h:609
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static struct GNUNET_FS_SearchContext * sc
Definition: gnunet-search.c:37
uint32_t bytes_pending
Number of bytes waiting for transmission.
Definition: transport.h:639
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
struct GNUNET_PeerIdentity peer
For which peer is this an address?
Allow multiple values with the same key.
Handle to a message queue.
Definition: mq.c:85
void(* GNUNET_TRANSPORT_SessionMonitorCallback)(void *cls, struct GNUNET_TRANSPORT_PluginSession *session, void **session_ctx, const struct GNUNET_TRANSPORT_SessionInfo *info)
Function called by the plugin with information about the current sessions managed by the plugin (for ...
uint64_t session_id
Unique identifier for the session.
Definition: transport.h:659
No additional information.
Context information to be used while searching for operation contexts.
Definition: testbed_api.c:225
uint16_t session_state
An enum GNUNET_TRANSPORT_SessionState in NBO.
Definition: transport.h:619
configuration data
Definition: configuration.c:85
struct GNUNET_TIME_AbsoluteNBO delay
Until how long is this plugin currently blocked from reading?
Definition: transport.h:649
void * client_ctx
Location for the client to store "data".
An address for communicating with a peer.
uint64_t session_id
ID to locate.
static int check_event(void *cls, const struct TransportPluginMonitorMessage *tpmm)
Function called with responses from the service.
The session was created (first call for each session object).
Entry in list of pending tasks.
Definition: scheduler.c:134
void GNUNET_TRANSPORT_monitor_plugins_cancel(struct GNUNET_TRANSPORT_PluginMonitor *pm)
Cancel monitoring the plugin session state.
Header for all communications.
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:824
#define GNUNET_YES
Definition: gnunet_common.h:77
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:353
static void do_plugin_connect(void *cls)
Task run to re-establish the connection.
GNUNET_TRANSPORT_SessionState
Possible states of a session in a plugin.
static void handle_sync(void *cls, const struct GNUNET_MessageHeader *msg)
Function called with sync responses from the service.
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
static struct GNUNET_TRANSPORT_PluginMonitor * pm
Handle if we are monitoring plugin session activity.
struct GNUNET_CONTAINER_MultiHashMap32 * sessions
Map of session_ids (reduced to 32-bits) to struct GNUNET_TRANSPORT_PluginSession objects.
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PLUGIN_EVENT.
Definition: transport.h:614
static void reconnect_plugin_ctx(struct GNUNET_TRANSPORT_PluginMonitor *pm)
Cut the existing connection and reconnect.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:966