global reindent, now with uncrustify hook enabled
[oweals/gnunet.git] / src / transport / plugin_transport_template.c
1 /*
2      This file is part of GNUnet
3      Copyright (C) 2002-2014 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 transport/plugin_transport_template.c
23  * @brief template for a new transport service
24  * @author Christian Grothoff
25  */
26
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_statistics_service.h"
31 #include "gnunet_transport_service.h"
32 #include "gnunet_transport_plugin.h"
33
34 #define LOG(kind, ...) GNUNET_log_from (kind, "transport-template", __VA_ARGS__)
35
36 /**
37  * After how long do we expire an address that we
38  * learned from another peer if it is not reconfirmed
39  * by anyone?
40  */
41 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply ( \
42     GNUNET_TIME_UNIT_HOURS, 6)
43
44 #define PLUGIN_NAME "template"
45
46 /**
47  * Encapsulation of all of the state of the plugin.
48  */
49 struct Plugin;
50
51
52 /**
53  * Session handle for connections.
54  */
55 struct GNUNET_ATS_Session
56 {
57   /**
58    * To whom are we talking to (set to our identity
59    * if we are still waiting for the welcome message)
60    */
61   struct GNUNET_PeerIdentity sender;
62
63   /**
64    * Stored in a linked list (or a peer map, or ...)
65    */
66   struct GNUNET_ATS_Session *next;
67
68   /**
69    * Pointer to the global plugin struct.
70    */
71   struct Plugin *plugin;
72
73   /**
74    * The client (used to identify this connection)
75    */
76   /* void *client; */
77
78   /**
79    * Continuation function to call once the transmission buffer
80    * has again space available.  NULL if there is no
81    * continuation to call.
82    */
83   GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
84
85   /**
86    * Closure for @e transmit_cont.
87    */
88   void *transmit_cont_cls;
89
90   /**
91    * At what time did we reset @e last_received last?
92    */
93   struct GNUNET_TIME_Absolute last_quota_update;
94
95   /**
96    * How many bytes have we received since the @e last_quota_update
97    * timestamp?
98    */
99   uint64_t last_received;
100
101   /**
102    * Number of bytes per ms that this peer is allowed
103    * to send to us.
104    */
105   uint32_t quota;
106 };
107
108 GNUNET_NETWORK_STRUCT_BEGIN
109
110 struct TemplateAddress
111 {
112   /**
113    * Address options in NBO
114    */
115   uint32_t options GNUNET_PACKED;
116
117   /* Add address here */
118 };
119
120 GNUNET_NETWORK_STRUCT_END
121
122 /**
123  * Encapsulation of all of the state of the plugin.
124  */
125 struct Plugin
126 {
127   /**
128    * Our environment.
129    */
130   struct GNUNET_TRANSPORT_PluginEnvironment *env;
131
132   /**
133    * List of open sessions (or peer map, or...)
134    */
135   struct GNUNET_ATS_Session *sessions;
136
137   /**
138    * Function to call about session status changes.
139    */
140   GNUNET_TRANSPORT_SessionInfoCallback sic;
141
142   /**
143    * Closure for @e sic.
144    */
145   void *sic_cls;
146
147   /**
148    * Options in HBO to be used with addresses
149    */
150 };
151
152
153 #if 0
154 /**
155  * If a session monitor is attached, notify it about the new
156  * session state.
157  *
158  * @param plugin our plugin
159  * @param session session that changed state
160  * @param state new state of the session
161  */
162 static void
163 notify_session_monitor (struct Plugin *plugin,
164                         struct GNUNET_ATS_Session *session,
165                         enum GNUNET_TRANSPORT_SessionState state)
166 {
167   struct GNUNET_TRANSPORT_SessionInfo info;
168
169   if (NULL == plugin->sic)
170     return;
171   memset (&info, 0, sizeof(info));
172   info.state = state;
173   info.is_inbound = GNUNET_SYSERR; /* FIXME */
174   // info.num_msg_pending =
175   // info.num_bytes_pending =
176   // info.receive_delay =
177   // info.session_timeout = session->timeout;
178   // info.address = session->address;
179   plugin->sic (plugin->sic_cls,
180                session,
181                &info);
182 }
183 #endif
184
185
186 /**
187  * Function that can be used by the transport service to transmit
188  * a message using the plugin.   Note that in the case of a
189  * peer disconnecting, the continuation MUST be called
190  * prior to the disconnect notification itself.  This function
191  * will be called with this peer's HELLO message to initiate
192  * a fresh connection to another peer.
193  *
194  * @param cls closure
195  * @param session which session must be used
196  * @param msgbuf the message to transmit
197  * @param msgbuf_size number of bytes in @a msgbuf
198  * @param priority how important is the message (most plugins will
199  *                 ignore message priority and just FIFO)
200  * @param to how long to wait at most for the transmission (does not
201  *                require plugins to discard the message after the timeout,
202  *                just advisory for the desired delay; most plugins will ignore
203  *                this as well)
204  * @param cont continuation to call once the message has
205  *        been transmitted (or if the transport is ready
206  *        for the next transmission call; or if the
207  *        peer disconnected...); can be NULL
208  * @param cont_cls closure for @a cont
209  * @return number of bytes used (on the physical network, with overheads);
210  *         -1 on hard errors (i.e. address invalid); 0 is a legal value
211  *         and does NOT mean that the message was not transmitted (DV)
212  */
213 static ssize_t
214 template_plugin_send (void *cls,
215                       struct GNUNET_ATS_Session *session,
216                       const char *msgbuf,
217                       size_t msgbuf_size,
218                       unsigned int priority,
219                       struct GNUNET_TIME_Relative to,
220                       GNUNET_TRANSPORT_TransmitContinuation cont,
221                       void *cont_cls)
222 {
223   /*  struct Plugin *plugin = cls; */
224   ssize_t bytes_sent = 0;
225
226   return bytes_sent;
227 }
228
229
230 /**
231  * Function that can be used to force the plugin to disconnect
232  * from the given peer and cancel all previous transmissions
233  * (and their continuationc).
234  *
235  * @param cls closure
236  * @param target peer from which to disconnect
237  */
238 static void
239 template_plugin_disconnect_peer (void *cls,
240                                  const struct GNUNET_PeerIdentity *target)
241 {
242   // struct Plugin *plugin = cls;
243   // FIXME
244 }
245
246
247 /**
248  * Function that can be used to force the plugin to disconnect
249  * from the given peer and cancel all previous transmissions
250  * (and their continuationc).
251  *
252  * @param cls closure
253  * @param session session from which to disconnect
254  * @return #GNUNET_OK on success
255  */
256 static int
257 template_plugin_disconnect_session (void *cls,
258                                     struct GNUNET_ATS_Session *session)
259 {
260   // struct Plugin *plugin = cls;
261   // FIXME
262   return GNUNET_SYSERR;
263 }
264
265
266 /**
267  * Function that is called to get the keepalive factor.
268  * GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to
269  * calculate the interval between keepalive packets.
270  *
271  * @param cls closure with the `struct Plugin`
272  * @return keepalive factor
273  */
274 static unsigned int
275 template_plugin_query_keepalive_factor (void *cls)
276 {
277   return 3;
278 }
279
280
281 /**
282  * Function obtain the network type for a session
283  *
284  * @param cls closure ('struct Plugin*')
285  * @param session the session
286  * @return the network type in HBO or #GNUNET_SYSERR
287  */
288 static enum GNUNET_NetworkType
289 template_plugin_get_network (void *cls,
290                              struct GNUNET_ATS_Session *session)
291 {
292   GNUNET_assert (NULL != session);
293   return GNUNET_NT_UNSPECIFIED; /* Change to correct network type */
294 }
295
296
297 /**
298  * Function obtain the network type for an address.
299  *
300  * @param cls closure (`struct Plugin *`)
301  * @param address the address
302  * @return the network type
303  */
304 static enum GNUNET_NetworkType
305 template_plugin_get_network_for_address (void *cls,
306                                          const struct
307                                          GNUNET_HELLO_Address *address)
308 {
309   return GNUNET_NT_WAN; /* FOR NOW */
310 }
311
312
313 /**
314  * Convert the transports address to a nice, human-readable
315  * format.
316  *
317  * @param cls closure
318  * @param type name of the transport that generated the address
319  * @param addr one of the addresses of the host, NULL for the last address
320  *        the specific address format depends on the transport
321  * @param addrlen length of the address
322  * @param numeric should (IP) addresses be displayed in numeric form?
323  * @param timeout after how long should we give up?
324  * @param asc function to call on each string
325  * @param asc_cls closure for @a asc
326  */
327 static void
328 template_plugin_address_pretty_printer (void *cls, const char *type,
329                                         const void *addr, size_t addrlen,
330                                         int numeric,
331                                         struct GNUNET_TIME_Relative timeout,
332                                         GNUNET_TRANSPORT_AddressStringCallback
333                                         asc, void *asc_cls)
334 {
335   asc (asc_cls, "converted address", GNUNET_OK);  /* return address */
336   asc (asc_cls, NULL, GNUNET_OK);  /* done */
337 }
338
339
340
341 /**
342  * Another peer has suggested an address for this
343  * peer and transport plugin.  Check that this could be a valid
344  * address.  If so, consider adding it to the list
345  * of addresses.
346  *
347  * @param cls closure
348  * @param addr pointer to the address
349  * @param addrlen length of addr
350  * @return #GNUNET_OK if this is a plausible address for this peer
351  *         and transport
352  */
353 static int
354 template_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
355 {
356   /* struct Plugin *plugin = cls; */
357
358   /* check if the address is belonging to the plugin*/
359   return GNUNET_OK;
360 }
361
362
363 /**
364  * Function called for a quick conversion of the binary address to
365  * a numeric address.  Note that the caller must not free the
366  * address and that the next call to this function is allowed
367  * to override the address again.
368  *
369  * @param cls closure
370  * @param addr binary address
371  * @param addrlen length of the address
372  * @return string representing the same address
373  */
374 static const char *
375 template_plugin_address_to_string (void *cls, const void *addr, size_t addrlen)
376 {
377   /*
378    * Print address in format template.options.address
379    */
380
381   if (0 == addrlen)
382   {
383     return TRANSPORT_SESSION_INBOUND_STRING;
384   }
385
386   GNUNET_break (0);
387   return NULL;
388 }
389
390
391 /**
392  * Function called to convert a string address to
393  * a binary address.
394  *
395  * @param cls closure ('struct Plugin*')
396  * @param addr string address
397  * @param addrlen length of the @a addr
398  * @param buf location to store the buffer
399  * @param added location to store the number of bytes in the buffer.
400  *        If the function returns #GNUNET_SYSERR, its contents are undefined.
401  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
402  */
403 static int
404 template_plugin_string_to_address (void *cls,
405                                    const char *addr,
406                                    uint16_t addrlen,
407                                    void **buf, size_t *added)
408 {
409   /*
410    * Parse string in format template.options.address
411    */
412   GNUNET_break (0);
413   return GNUNET_SYSERR;
414 }
415
416
417 /**
418  * Create a new session to transmit data to the target
419  * This session will used to send data to this peer and the plugin will
420  * notify us by calling the env->session_end function
421  *
422  * @param cls closure
423  * @param address pointer to the GNUNET_HELLO_Address
424  * @return the session if the address is valid, NULL otherwise
425  */
426 static struct GNUNET_ATS_Session *
427 template_plugin_get_session (void *cls,
428                              const struct GNUNET_HELLO_Address *address)
429 {
430   GNUNET_break (0);
431   return NULL;
432 }
433
434
435 static void
436 template_plugin_update_session_timeout (void *cls,
437                                         const struct GNUNET_PeerIdentity *peer,
438                                         struct GNUNET_ATS_Session *session)
439 {
440 }
441
442
443 #if 0
444 /**
445  * Return information about the given session to the
446  * monitor callback.
447  *
448  * @param cls the `struct Plugin` with the monitor callback (`sic`)
449  * @param peer peer we send information about
450  * @param value our `struct GNUNET_ATS_Session` to send information about
451  * @return #GNUNET_OK (continue to iterate)
452  */
453 static int
454 send_session_info_iter (void *cls,
455                         const struct GNUNET_PeerIdentity *peer,
456                         void *value)
457 {
458   struct Plugin *plugin = cls;
459   struct GNUNET_ATS_Session *session = value;
460
461   notify_session_monitor (plugin,
462                           session,
463                           GNUNET_TRANSPORT_SS_UP);
464   return GNUNET_OK;
465 }
466 #endif
467
468
469 /**
470  * Begin monitoring sessions of a plugin.  There can only
471  * be one active monitor per plugin (i.e. if there are
472  * multiple monitors, the transport service needs to
473  * multiplex the generated events over all of them).
474  *
475  * @param cls closure of the plugin
476  * @param sic callback to invoke, NULL to disable monitor;
477  *            plugin will being by iterating over all active
478  *            sessions immediately and then enter monitor mode
479  * @param sic_cls closure for @a sic
480  */
481 static void
482 template_plugin_setup_monitor (void *cls,
483                                GNUNET_TRANSPORT_SessionInfoCallback sic,
484                                void *sic_cls)
485 {
486   struct Plugin *plugin = cls;
487
488   plugin->sic = sic;
489   plugin->sic_cls = sic_cls;
490   if (NULL != sic)
491   {
492 #if 0
493     GNUNET_CONTAINER_multipeermap_iterate (NULL /* FIXME */,
494                                            &send_session_info_iter,
495                                            plugin);
496 #endif
497     /* signal end of first iteration */
498     sic (sic_cls, NULL, NULL);
499   }
500 }
501
502
503 /**
504  * Entry point for the plugin.
505  */
506 void *
507 libgnunet_plugin_transport_template_init (void *cls)
508 {
509   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
510   struct GNUNET_TRANSPORT_PluginFunctions *api;
511   struct Plugin *plugin;
512
513   if (NULL == env->receive)
514   {
515     /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
516        initialze the plugin or the API */
517     api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
518     api->cls = NULL;
519     api->address_to_string = &template_plugin_address_to_string;
520     api->string_to_address = &template_plugin_string_to_address;
521     api->address_pretty_printer = &template_plugin_address_pretty_printer;
522     return api;
523   }
524
525   plugin = GNUNET_new (struct Plugin);
526   plugin->env = env;
527   api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
528   api->cls = plugin;
529   api->send = &template_plugin_send;
530   api->disconnect_peer = &template_plugin_disconnect_peer;
531   api->disconnect_session = &template_plugin_disconnect_session;
532   api->query_keepalive_factor = &template_plugin_query_keepalive_factor;
533   api->address_pretty_printer = &template_plugin_address_pretty_printer;
534   api->check_address = &template_plugin_address_suggested;
535   api->address_to_string = &template_plugin_address_to_string;
536   api->string_to_address = &template_plugin_string_to_address;
537   api->get_session = &template_plugin_get_session;
538   api->get_network = &template_plugin_get_network;
539   api->get_network_for_address = &template_plugin_get_network_for_address;
540   api->update_session_timeout = &template_plugin_update_session_timeout;
541   api->setup_monitor = &template_plugin_setup_monitor;
542   LOG (GNUNET_ERROR_TYPE_INFO, "Template plugin successfully loaded\n");
543   return api;
544 }
545
546
547 /**
548  * Exit point from the plugin.
549  */
550 void *
551 libgnunet_plugin_transport_template_done (void *cls)
552 {
553   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
554   struct Plugin *plugin = api->cls;
555
556   GNUNET_free (plugin);
557   GNUNET_free (api);
558   return NULL;
559 }
560
561 /* end of plugin_transport_template.c */