2 This file is part of GNUnet
3 Copyright (C) 2002-2014 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU 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.
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.
17 * @file transport/plugin_transport_template.c
18 * @brief template for a new transport service
19 * @author Christian Grothoff
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"
29 #define LOG(kind,...) GNUNET_log_from (kind, "transport-template",__VA_ARGS__)
32 * After how long do we expire an address that we
33 * learned from another peer if it is not reconfirmed
36 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
38 #define PLUGIN_NAME "template"
41 * Encapsulation of all of the state of the plugin.
47 * Session handle for connections.
49 struct GNUNET_ATS_Session
52 * To whom are we talking to (set to our identity
53 * if we are still waiting for the welcome message)
55 struct GNUNET_PeerIdentity sender;
58 * Stored in a linked list (or a peer map, or ...)
60 struct GNUNET_ATS_Session *next;
63 * Pointer to the global plugin struct.
65 struct Plugin *plugin;
68 * The client (used to identify this connection)
73 * Continuation function to call once the transmission buffer
74 * has again space available. NULL if there is no
75 * continuation to call.
77 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
80 * Closure for @e transmit_cont.
82 void *transmit_cont_cls;
85 * At what time did we reset @e last_received last?
87 struct GNUNET_TIME_Absolute last_quota_update;
90 * How many bytes have we received since the @e last_quota_update
93 uint64_t last_received;
96 * Number of bytes per ms that this peer is allowed
103 GNUNET_NETWORK_STRUCT_BEGIN
105 struct TemplateAddress
108 * Address options in NBO
110 uint32_t options GNUNET_PACKED;
112 /* Add address here */
115 GNUNET_NETWORK_STRUCT_END
118 * Encapsulation of all of the state of the plugin.
125 struct GNUNET_TRANSPORT_PluginEnvironment *env;
128 * List of open sessions (or peer map, or...)
130 struct GNUNET_ATS_Session *sessions;
133 * Function to call about session status changes.
135 GNUNET_TRANSPORT_SessionInfoCallback sic;
138 * Closure for @e sic.
143 * Options in HBO to be used with addresses
151 * If a session monitor is attached, notify it about the new
154 * @param plugin our plugin
155 * @param session session that changed state
156 * @param state new state of the session
159 notify_session_monitor (struct Plugin *plugin,
160 struct GNUNET_ATS_Session *session,
161 enum GNUNET_TRANSPORT_SessionState state)
163 struct GNUNET_TRANSPORT_SessionInfo info;
165 if (NULL == plugin->sic)
167 memset (&info, 0, sizeof (info));
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,
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.
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
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)
210 template_plugin_send (void *cls,
211 struct GNUNET_ATS_Session *session,
214 unsigned int priority,
215 struct GNUNET_TIME_Relative to,
216 GNUNET_TRANSPORT_TransmitContinuation cont,
219 /* struct Plugin *plugin = cls; */
220 ssize_t bytes_sent = 0;
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).
232 * @param target peer from which to disconnect
235 template_plugin_disconnect_peer (void *cls,
236 const struct GNUNET_PeerIdentity *target)
238 // struct Plugin *plugin = cls;
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).
249 * @param session session from which to disconnect
250 * @return #GNUNET_OK on success
253 template_plugin_disconnect_session (void *cls,
254 struct GNUNET_ATS_Session *session)
256 // struct Plugin *plugin = cls;
258 return GNUNET_SYSERR;
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.
267 * @param cls closure with the `struct Plugin`
268 * @return keepalive factor
271 template_plugin_query_keepalive_factor (void *cls)
278 * Function obtain the network type for a session
280 * @param cls closure ('struct Plugin*')
281 * @param session the session
282 * @return the network type in HBO or #GNUNET_SYSERR
284 static enum GNUNET_ATS_Network_Type
285 template_plugin_get_network (void *cls,
286 struct GNUNET_ATS_Session *session)
288 GNUNET_assert (NULL != session);
289 return GNUNET_ATS_NET_UNSPECIFIED; /* Change to correct network type */
294 * Function obtain the network type for an address.
296 * @param cls closure (`struct Plugin *`)
297 * @param address the address
298 * @return the network type
300 static enum GNUNET_ATS_Network_Type
301 template_plugin_get_network_for_address (void *cls,
302 const struct GNUNET_HELLO_Address *address)
304 return GNUNET_ATS_NET_WAN; /* FOR NOW */
309 * Convert the transports address to a nice, human-readable
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
323 template_plugin_address_pretty_printer (void *cls, const char *type,
324 const void *addr, size_t addrlen,
326 struct GNUNET_TIME_Relative timeout,
327 GNUNET_TRANSPORT_AddressStringCallback
330 asc (asc_cls, "converted address", GNUNET_OK); /* return address */
331 asc (asc_cls, NULL, GNUNET_OK); /* done */
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
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
349 template_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
351 /* struct Plugin *plugin = cls; */
353 /* check if the address is belonging to the plugin*/
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.
365 * @param addr binary address
366 * @param addrlen length of the address
367 * @return string representing the same address
370 template_plugin_address_to_string (void *cls, const void *addr, size_t addrlen)
373 * Print address in format template.options.address
378 return TRANSPORT_SESSION_INBOUND_STRING;
387 * Function called to convert a string address to
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
399 template_plugin_string_to_address (void *cls,
402 void **buf, size_t *added)
405 * Parse string in format template.options.address
408 return GNUNET_SYSERR;
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
418 * @param address pointer to the GNUNET_HELLO_Address
419 * @return the session if the address is valid, NULL otherwise
421 static struct GNUNET_ATS_Session *
422 template_plugin_get_session (void *cls,
423 const struct GNUNET_HELLO_Address *address)
431 template_plugin_update_session_timeout (void *cls,
432 const struct GNUNET_PeerIdentity *peer,
433 struct GNUNET_ATS_Session *session)
441 * Return information about the given session to the
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)
450 send_session_info_iter (void *cls,
451 const struct GNUNET_PeerIdentity *peer,
454 struct Plugin *plugin = cls;
455 struct GNUNET_ATS_Session *session = value;
457 notify_session_monitor (plugin,
459 GNUNET_TRANSPORT_SS_UP);
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).
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
478 template_plugin_setup_monitor (void *cls,
479 GNUNET_TRANSPORT_SessionInfoCallback sic,
482 struct Plugin *plugin = cls;
485 plugin->sic_cls = sic_cls;
489 GNUNET_CONTAINER_multipeermap_iterate (NULL /* FIXME */,
490 &send_session_info_iter,
493 /* signal end of first iteration */
494 sic (sic_cls, NULL, NULL);
500 * Entry point for the plugin.
503 libgnunet_plugin_transport_template_init (void *cls)
505 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
506 struct GNUNET_TRANSPORT_PluginFunctions *api;
507 struct Plugin *plugin;
509 if (NULL == env->receive)
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);
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;
521 plugin = GNUNET_new (struct Plugin);
523 api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
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");
544 * Exit point from the plugin.
547 libgnunet_plugin_transport_template_done (void *cls)
549 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
550 struct Plugin *plugin = api->cls;
552 GNUNET_free (plugin);
557 /* end of plugin_transport_template.c */