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