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