GNUnet  0.10.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 
43 
48 
53 
57  void *cb_cls;
58 
64 
69 
74 };
75 
76 
85  uint64_t session_id;
86 
90  void *client_ctx;
91 };
92 
93 
94 
100 static void
101 do_plugin_connect(void *cls);
102 
103 
112 static int
113 free_entry(void *cls,
114  uint32_t key,
115  void *value)
116 {
117  struct GNUNET_TRANSPORT_PluginMonitor *pm = cls;
119 
120  pm->cb(pm->cb_cls,
121  ps,
122  &ps->client_ctx,
123  NULL);
126  key,
127  ps));
128  GNUNET_break(NULL == ps->client_ctx);
129  GNUNET_free(ps);
130  return GNUNET_OK;
131 }
132 
133 
139 static void
141 {
142  GNUNET_MQ_destroy(pm->mq);
143  pm->mq = NULL;
145  &free_entry,
146  pm);
150  pm);
151 }
152 
153 
160 static uint32_t
161 wrap_id(uint64_t id)
162 {
163  return ((uint32_t)id) ^ ((uint32_t)(id >> 32));
164 }
165 
166 
170 struct SearchContext {
175 
179  uint64_t session_id;
180 };
181 
182 
191 static int
192 locate_by_id(void *cls,
193  uint32_t key,
194  void *value)
195 {
196  struct SearchContext *sc = cls;
198 
199  if (sc->session_id == ps->session_id)
200  {
201  sc->ps = ps;
202  return GNUNET_SYSERR;
203  }
204  return GNUNET_OK;
205 }
206 
207 
215 static int
216 check_event(void *cls,
217  const struct TransportPluginMonitorMessage *tpmm)
218 {
219  const char *pname;
220  size_t pname_len;
221  size_t paddr_len;
222 
223  pname = (const char *)&tpmm[1];
224  pname_len = ntohs(tpmm->plugin_name_len);
225  paddr_len = ntohs(tpmm->plugin_address_len);
226  if ((pname_len +
227  paddr_len +
228  sizeof(struct TransportPluginMonitorMessage) != ntohs(tpmm->header.size)) ||
229  ((0 != pname_len) &&
230  ('\0' != pname[pname_len - 1])))
231  {
232  GNUNET_break(0);
233  return GNUNET_SYSERR;
234  }
235  return GNUNET_OK;
236 }
237 
238 
245 static void
246 handle_event(void *cls,
247  const struct TransportPluginMonitorMessage *tpmm)
248 {
249  struct GNUNET_TRANSPORT_PluginMonitor *pm = cls;
251  const char *pname;
252  const void *paddr;
254  size_t pname_len;
255  size_t paddr_len;
256  struct GNUNET_TRANSPORT_SessionInfo info;
257  struct GNUNET_HELLO_Address addr;
258  struct SearchContext rv;
259 
260  pname = (const char *)&tpmm[1];
261  pname_len = ntohs(tpmm->plugin_name_len);
262  paddr_len = ntohs(tpmm->plugin_address_len);
263  paddr = &pname[pname_len];
264  ps = NULL;
265  ss = (enum GNUNET_TRANSPORT_SessionState)ntohs(tpmm->session_state);
266  if (GNUNET_TRANSPORT_SS_INIT == ss)
267  {
269  ps->session_id = tpmm->session_id;
271  wrap_id(tpmm->session_id),
272  ps,
274  }
275  else
276  {
277  rv.session_id = tpmm->session_id;
278  rv.ps = NULL;
280  wrap_id(tpmm->session_id),
281  &locate_by_id,
282  &rv);
283  ps = rv.ps;
284  if (NULL == ps)
285  {
286  GNUNET_break(0);
288  return;
289  }
290  }
291  info.state = ss;
292  info.is_inbound = (int16_t)ntohs(tpmm->is_inbound);
293  info.num_msg_pending = ntohl(tpmm->msgs_pending);
294  info.num_bytes_pending = ntohl(tpmm->bytes_pending);
297  info.address = &addr;
298  addr.peer = tpmm->peer;
299  addr.address = (0 == paddr_len) ? NULL : paddr;
300  addr.address_length = paddr_len;
301  addr.transport_name = (0 == pname_len) ? NULL : pname;
303  pm->cb(pm->cb_cls,
304  ps,
305  &ps->client_ctx,
306  &info);
307 
308  if (GNUNET_TRANSPORT_SS_DONE == ss)
309  {
310  GNUNET_break(NULL == ps->client_ctx);
313  wrap_id(tpmm->session_id),
314  ps));
315  GNUNET_free(ps);
316  }
317 }
318 
319 
326 static void
327 handle_sync(void *cls,
328  const struct GNUNET_MessageHeader *msg)
329 {
330  struct GNUNET_TRANSPORT_PluginMonitor *pm = cls;
331 
332  /* we are in sync, notify callback */
333  pm->cb(pm->cb_cls,
334  NULL,
335  NULL,
336  NULL);
337 }
338 
339 
349 static void
351  enum GNUNET_MQ_Error error)
352 {
353  struct GNUNET_TRANSPORT_PluginMonitor *pm = cls;
354 
356 }
357 
358 
364 static void
366 {
367  struct GNUNET_TRANSPORT_PluginMonitor *pm = cls;
368  struct GNUNET_MQ_MessageHandler handlers[] = {
369  GNUNET_MQ_hd_var_size(event,
372  pm),
375  struct GNUNET_MessageHeader,
376  pm),
378  };
379  struct GNUNET_MessageHeader *msg;
380  struct GNUNET_MQ_Envelope *env;
381 
382  pm->reconnect_task = NULL;
383  pm->mq = GNUNET_CLIENT_connect(pm->cfg,
384  "transport",
385  handlers,
387  pm);
388  if (NULL == pm->mq)
389  return;
390  env = GNUNET_MQ_msg(msg,
392  GNUNET_MQ_send(pm->mq,
393  env);
394 }
395 
396 
409  void *cb_cls)
410 {
412 
414  pm->cb = cb;
415  pm->cb_cls = cb_cls;
416  pm->cfg = cfg;
417  do_plugin_connect(pm);
418  if (NULL == pm->mq)
419  {
420  GNUNET_free(pm);
421  return NULL;
422  }
424  return pm;
425 }
426 
427 
436 void
438 {
439  if (NULL != pm->mq)
440  {
441  GNUNET_MQ_destroy(pm->mq);
442  pm->mq = NULL;
443  }
444  if (NULL != pm->reconnect_task)
445  {
447  pm->reconnect_task = NULL;
448  }
450  &free_entry,
451  pm);
453  GNUNET_free(pm);
454 }
455 
456 
457 /* 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:671
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:900
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:612
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:637
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:1237
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:647
uint16_t plugin_address_len
Length of the plugin address in bytes.
Definition: transport.h:652
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:617
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:627
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:593
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:622
#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:84
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:642
No additional information.
Context information to be used while searching for operation contexts.
Definition: testbed_api.c:220
uint16_t session_state
An enum GNUNET_TRANSPORT_SessionState in NBO.
Definition: transport.h:602
configuration data
Definition: configuration.c:83
struct GNUNET_TIME_AbsoluteNBO delay
Until how long is this plugin currently blocked from reading?
Definition: transport.h:632
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:131
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:821
#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:351
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:597
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:956