add changelog
[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
184
185 #endif
186
187
188 /**
189  * Function that can be used by the transport service to transmit
190  * a message using the plugin.   Note that in the case of a
191  * peer disconnecting, the continuation MUST be called
192  * prior to the disconnect notification itself.  This function
193  * will be called with this peer's HELLO message to initiate
194  * a fresh connection to another peer.
195  *
196  * @param cls closure
197  * @param session which session must be used
198  * @param msgbuf the message to transmit
199  * @param msgbuf_size number of bytes in @a msgbuf
200  * @param priority how important is the message (most plugins will
201  *                 ignore message priority and just FIFO)
202  * @param to how long to wait at most for the transmission (does not
203  *                require plugins to discard the message after the timeout,
204  *                just advisory for the desired delay; most plugins will ignore
205  *                this as well)
206  * @param cont continuation to call once the message has
207  *        been transmitted (or if the transport is ready
208  *        for the next transmission call; or if the
209  *        peer disconnected...); can be NULL
210  * @param cont_cls closure for @a cont
211  * @return number of bytes used (on the physical network, with overheads);
212  *         -1 on hard errors (i.e. address invalid); 0 is a legal value
213  *         and does NOT mean that the message was not transmitted (DV)
214  */
215 static ssize_t
216 template_plugin_send (void *cls,
217                       struct GNUNET_ATS_Session *session,
218                       const char *msgbuf,
219                       size_t msgbuf_size,
220                       unsigned int priority,
221                       struct GNUNET_TIME_Relative to,
222                       GNUNET_TRANSPORT_TransmitContinuation cont,
223                       void *cont_cls)
224 {
225   /*  struct Plugin *plugin = cls; */
226   ssize_t bytes_sent = 0;
227
228   return bytes_sent;
229 }
230
231
232 /**
233  * Function that can be used to force the plugin to disconnect
234  * from the given peer and cancel all previous transmissions
235  * (and their continuationc).
236  *
237  * @param cls closure
238  * @param target peer from which to disconnect
239  */
240 static void
241 template_plugin_disconnect_peer (void *cls,
242                                  const struct GNUNET_PeerIdentity *target)
243 {
244   // struct Plugin *plugin = cls;
245   // FIXME
246 }
247
248
249 /**
250  * Function that can be used to force the plugin to disconnect
251  * from the given peer and cancel all previous transmissions
252  * (and their continuationc).
253  *
254  * @param cls closure
255  * @param session session from which to disconnect
256  * @return #GNUNET_OK on success
257  */
258 static int
259 template_plugin_disconnect_session (void *cls,
260                                     struct GNUNET_ATS_Session *session)
261 {
262   // struct Plugin *plugin = cls;
263   // FIXME
264   return GNUNET_SYSERR;
265 }
266
267
268 /**
269  * Function that is called to get the keepalive factor.
270  * GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to
271  * calculate the interval between keepalive packets.
272  *
273  * @param cls closure with the `struct Plugin`
274  * @return keepalive factor
275  */
276 static unsigned int
277 template_plugin_query_keepalive_factor (void *cls)
278 {
279   return 3;
280 }
281
282
283 /**
284  * Function obtain the network type for a session
285  *
286  * @param cls closure ('struct Plugin*')
287  * @param session the session
288  * @return the network type in HBO or #GNUNET_SYSERR
289  */
290 static enum GNUNET_NetworkType
291 template_plugin_get_network (void *cls,
292                              struct GNUNET_ATS_Session *session)
293 {
294   GNUNET_assert (NULL != session);
295   return GNUNET_NT_UNSPECIFIED; /* Change to correct network type */
296 }
297
298
299 /**
300  * Function obtain the network type for an address.
301  *
302  * @param cls closure (`struct Plugin *`)
303  * @param address the address
304  * @return the network type
305  */
306 static enum GNUNET_NetworkType
307 template_plugin_get_network_for_address (void *cls,
308                                          const struct
309                                          GNUNET_HELLO_Address *address)
310 {
311   return GNUNET_NT_WAN; /* FOR NOW */
312 }
313
314
315 /**
316  * Convert the transports address to a nice, human-readable
317  * format.
318  *
319  * @param cls closure
320  * @param type name of the transport that generated the address
321  * @param addr one of the addresses of the host, NULL for the last address
322  *        the specific address format depends on the transport
323  * @param addrlen length of the address
324  * @param numeric should (IP) addresses be displayed in numeric form?
325  * @param timeout after how long should we give up?
326  * @param asc function to call on each string
327  * @param asc_cls closure for @a asc
328  */
329 static void
330 template_plugin_address_pretty_printer (void *cls, const char *type,
331                                         const void *addr, size_t addrlen,
332                                         int numeric,
333                                         struct GNUNET_TIME_Relative timeout,
334                                         GNUNET_TRANSPORT_AddressStringCallback
335                                         asc, void *asc_cls)
336 {
337   asc (asc_cls, "converted address", GNUNET_OK);  /* return address */
338   asc (asc_cls, NULL, GNUNET_OK);  /* done */
339 }
340
341
342 /**
343  * Another peer has suggested an address for this
344  * peer and transport plugin.  Check that this could be a valid
345  * address.  If so, consider adding it to the list
346  * of addresses.
347  *
348  * @param cls closure
349  * @param addr pointer to the address
350  * @param addrlen length of addr
351  * @return #GNUNET_OK if this is a plausible address for this peer
352  *         and transport
353  */
354 static int
355 template_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
356 {
357   /* struct Plugin *plugin = cls; */
358
359   /* check if the address is belonging to the plugin*/
360   return GNUNET_OK;
361 }
362
363
364 /**
365  * Function called for a quick conversion of the binary address to
366  * a numeric address.  Note that the caller must not free the
367  * address and that the next call to this function is allowed
368  * to override the address again.
369  *
370  * @param cls closure
371  * @param addr binary address
372  * @param addrlen length of the address
373  * @return string representing the same address
374  */
375 static const char *
376 template_plugin_address_to_string (void *cls, const void *addr, size_t addrlen)
377 {
378   /*
379    * Print address in format template.options.address
380    */
381
382   if (0 == addrlen)
383   {
384     return TRANSPORT_SESSION_INBOUND_STRING;
385   }
386
387   GNUNET_break (0);
388   return NULL;
389 }
390
391
392 /**
393  * Function called to convert a string address to
394  * a binary address.
395  *
396  * @param cls closure ('struct Plugin*')
397  * @param addr string address
398  * @param addrlen length of the @a addr
399  * @param buf location to store the buffer
400  * @param added location to store the number of bytes in the buffer.
401  *        If the function returns #GNUNET_SYSERR, its contents are undefined.
402  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
403  */
404 static int
405 template_plugin_string_to_address (void *cls,
406                                    const char *addr,
407                                    uint16_t addrlen,
408                                    void **buf, size_t *added)
409 {
410   /*
411    * Parse string in format template.options.address
412    */
413   GNUNET_break (0);
414   return GNUNET_SYSERR;
415 }
416
417
418 /**
419  * Create a new session to transmit data to the target
420  * This session will used to send data to this peer and the plugin will
421  * notify us by calling the env->session_end function
422  *
423  * @param cls closure
424  * @param address pointer to the GNUNET_HELLO_Address
425  * @return the session if the address is valid, NULL otherwise
426  */
427 static struct GNUNET_ATS_Session *
428 template_plugin_get_session (void *cls,
429                              const struct GNUNET_HELLO_Address *address)
430 {
431   GNUNET_break (0);
432   return NULL;
433 }
434
435
436 static void
437 template_plugin_update_session_timeout (void *cls,
438                                         const struct GNUNET_PeerIdentity *peer,
439                                         struct GNUNET_ATS_Session *session)
440 {
441 }
442
443
444 #if 0
445 /**
446  * Return information about the given session to the
447  * monitor callback.
448  *
449  * @param cls the `struct Plugin` with the monitor callback (`sic`)
450  * @param peer peer we send information about
451  * @param value our `struct GNUNET_ATS_Session` to send information about
452  * @return #GNUNET_OK (continue to iterate)
453  */
454 static int
455 send_session_info_iter (void *cls,
456                         const struct GNUNET_PeerIdentity *peer,
457                         void *value)
458 {
459   struct Plugin *plugin = cls;
460   struct GNUNET_ATS_Session *session = value;
461
462   notify_session_monitor (plugin,
463                           session,
464                           GNUNET_TRANSPORT_SS_UP);
465   return GNUNET_OK;
466 }
467
468
469 #endif
470
471
472 /**
473  * Begin monitoring sessions of a plugin.  There can only
474  * be one active monitor per plugin (i.e. if there are
475  * multiple monitors, the transport service needs to
476  * multiplex the generated events over all of them).
477  *
478  * @param cls closure of the plugin
479  * @param sic callback to invoke, NULL to disable monitor;
480  *            plugin will being by iterating over all active
481  *            sessions immediately and then enter monitor mode
482  * @param sic_cls closure for @a sic
483  */
484 static void
485 template_plugin_setup_monitor (void *cls,
486                                GNUNET_TRANSPORT_SessionInfoCallback sic,
487                                void *sic_cls)
488 {
489   struct Plugin *plugin = cls;
490
491   plugin->sic = sic;
492   plugin->sic_cls = sic_cls;
493   if (NULL != sic)
494   {
495 #if 0
496     GNUNET_CONTAINER_multipeermap_iterate (NULL /* FIXME */,
497                                            &send_session_info_iter,
498                                            plugin);
499 #endif
500     /* signal end of first iteration */
501     sic (sic_cls, NULL, NULL);
502   }
503 }
504
505
506 /**
507  * Entry point for the plugin.
508  */
509 void *
510 libgnunet_plugin_transport_template_init (void *cls)
511 {
512   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
513   struct GNUNET_TRANSPORT_PluginFunctions *api;
514   struct Plugin *plugin;
515
516   if (NULL == env->receive)
517   {
518     /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
519        initialze the plugin or the API */
520     api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
521     api->cls = NULL;
522     api->address_to_string = &template_plugin_address_to_string;
523     api->string_to_address = &template_plugin_string_to_address;
524     api->address_pretty_printer = &template_plugin_address_pretty_printer;
525     return api;
526   }
527
528   plugin = GNUNET_new (struct Plugin);
529   plugin->env = env;
530   api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
531   api->cls = plugin;
532   api->send = &template_plugin_send;
533   api->disconnect_peer = &template_plugin_disconnect_peer;
534   api->disconnect_session = &template_plugin_disconnect_session;
535   api->query_keepalive_factor = &template_plugin_query_keepalive_factor;
536   api->address_pretty_printer = &template_plugin_address_pretty_printer;
537   api->check_address = &template_plugin_address_suggested;
538   api->address_to_string = &template_plugin_address_to_string;
539   api->string_to_address = &template_plugin_string_to_address;
540   api->get_session = &template_plugin_get_session;
541   api->get_network = &template_plugin_get_network;
542   api->get_network_for_address = &template_plugin_get_network_for_address;
543   api->update_session_timeout = &template_plugin_update_session_timeout;
544   api->setup_monitor = &template_plugin_setup_monitor;
545   LOG (GNUNET_ERROR_TYPE_INFO, "Template plugin successfully loaded\n");
546   return api;
547 }
548
549
550 /**
551  * Exit point from the plugin.
552  */
553 void *
554 libgnunet_plugin_transport_template_done (void *cls)
555 {
556   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
557   struct Plugin *plugin = api->cls;
558
559   GNUNET_free (plugin);
560   GNUNET_free (api);
561   return NULL;
562 }
563
564
565 /* end of plugin_transport_template.c */