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