cleaning up set handlers, eliminating 2nd level demultiplexing and improving use...
[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
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., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, 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 GNUNET_ATS_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 GNUNET_ATS_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 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
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 GNUNET_ATS_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 GNUNET_ATS_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 GNUNET_ATS_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 GNUNET_ATS_Session *session)
292 {
293   GNUNET_assert (NULL != session);
294   return GNUNET_ATS_NET_UNSPECIFIED; /* Change to correct network type */
295 }
296
297
298 /**
299  * Function obtain the network type for an address.
300  *
301  * @param cls closure (`struct Plugin *`)
302  * @param address the address
303  * @return the network type
304  */
305 static enum GNUNET_ATS_Network_Type
306 template_plugin_get_network_for_address (void *cls,
307                                          const struct GNUNET_HELLO_Address *address)
308 {
309   return GNUNET_ATS_NET_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
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 #endif
468
469
470 /**
471  * Begin monitoring sessions of a plugin.  There can only
472  * be one active monitor per plugin (i.e. if there are
473  * multiple monitors, the transport service needs to
474  * multiplex the generated events over all of them).
475  *
476  * @param cls closure of the plugin
477  * @param sic callback to invoke, NULL to disable monitor;
478  *            plugin will being by iterating over all active
479  *            sessions immediately and then enter monitor mode
480  * @param sic_cls closure for @a sic
481  */
482 static void
483 template_plugin_setup_monitor (void *cls,
484                                GNUNET_TRANSPORT_SessionInfoCallback sic,
485                                void *sic_cls)
486 {
487   struct Plugin *plugin = cls;
488
489   plugin->sic = sic;
490   plugin->sic_cls = sic_cls;
491   if (NULL != sic)
492   {
493 #if 0
494     GNUNET_CONTAINER_multipeermap_iterate (NULL /* FIXME */,
495                                            &send_session_info_iter,
496                                            plugin);
497 #endif
498     /* signal end of first iteration */
499     sic (sic_cls, NULL, NULL);
500   }
501 }
502
503
504 /**
505  * Entry point for the plugin.
506  */
507 void *
508 libgnunet_plugin_transport_template_init (void *cls)
509 {
510   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
511   struct GNUNET_TRANSPORT_PluginFunctions *api;
512   struct Plugin *plugin;
513
514   if (NULL == env->receive)
515   {
516     /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
517        initialze the plugin or the API */
518     api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
519     api->cls = NULL;
520     api->address_to_string = &template_plugin_address_to_string;
521     api->string_to_address = &template_plugin_string_to_address;
522     api->address_pretty_printer = &template_plugin_address_pretty_printer;
523     return api;
524   }
525
526   plugin = GNUNET_new (struct Plugin);
527   plugin->env = env;
528   api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
529   api->cls = plugin;
530   api->send = &template_plugin_send;
531   api->disconnect_peer = &template_plugin_disconnect_peer;
532   api->disconnect_session = &template_plugin_disconnect_session;
533   api->query_keepalive_factor = &template_plugin_query_keepalive_factor;
534   api->address_pretty_printer = &template_plugin_address_pretty_printer;
535   api->check_address = &template_plugin_address_suggested;
536   api->address_to_string = &template_plugin_address_to_string;
537   api->string_to_address = &template_plugin_string_to_address;
538   api->get_session = &template_plugin_get_session;
539   api->get_network = &template_plugin_get_network;
540   api->get_network_for_address = &template_plugin_get_network_for_address;
541   api->update_session_timeout = &template_plugin_update_session_timeout;
542   api->setup_monitor = &template_plugin_setup_monitor;
543   LOG (GNUNET_ERROR_TYPE_INFO, "Template plugin successfully loaded\n");
544   return api;
545 }
546
547
548 /**
549  * Exit point from the plugin.
550  */
551 void *
552 libgnunet_plugin_transport_template_done (void *cls)
553 {
554   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
555   struct Plugin *plugin = api->cls;
556
557   GNUNET_free (plugin);
558   GNUNET_free (api);
559   return NULL;
560 }
561
562 /* end of plugin_transport_template.c */