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 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.
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.
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/>.
20 * @file transport/plugin_transport_template.c
21 * @brief template for a new transport service
22 * @author Christian Grothoff
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"
32 #define LOG(kind,...) GNUNET_log_from (kind, "transport-template",__VA_ARGS__)
35 * After how long do we expire an address that we
36 * learned from another peer if it is not reconfirmed
39 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
41 #define PLUGIN_NAME "template"
44 * Encapsulation of all of the state of the plugin.
50 * Session handle for connections.
52 struct GNUNET_ATS_Session
55 * To whom are we talking to (set to our identity
56 * if we are still waiting for the welcome message)
58 struct GNUNET_PeerIdentity sender;
61 * Stored in a linked list (or a peer map, or ...)
63 struct GNUNET_ATS_Session *next;
66 * Pointer to the global plugin struct.
68 struct Plugin *plugin;
71 * The client (used to identify this connection)
76 * Continuation function to call once the transmission buffer
77 * has again space available. NULL if there is no
78 * continuation to call.
80 GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
83 * Closure for @e transmit_cont.
85 void *transmit_cont_cls;
88 * At what time did we reset @e last_received last?
90 struct GNUNET_TIME_Absolute last_quota_update;
93 * How many bytes have we received since the @e last_quota_update
96 uint64_t last_received;
99 * Number of bytes per ms that this peer is allowed
106 GNUNET_NETWORK_STRUCT_BEGIN
108 struct TemplateAddress
111 * Address options in NBO
113 uint32_t options GNUNET_PACKED;
115 /* Add address here */
118 GNUNET_NETWORK_STRUCT_END
121 * Encapsulation of all of the state of the plugin.
128 struct GNUNET_TRANSPORT_PluginEnvironment *env;
131 * List of open sessions (or peer map, or...)
133 struct GNUNET_ATS_Session *sessions;
136 * Function to call about session status changes.
138 GNUNET_TRANSPORT_SessionInfoCallback sic;
141 * Closure for @e sic.
146 * Options in HBO to be used with addresses
154 * If a session monitor is attached, notify it about the new
157 * @param plugin our plugin
158 * @param session session that changed state
159 * @param state new state of the session
162 notify_session_monitor (struct Plugin *plugin,
163 struct GNUNET_ATS_Session *session,
164 enum GNUNET_TRANSPORT_SessionState state)
166 struct GNUNET_TRANSPORT_SessionInfo info;
168 if (NULL == plugin->sic)
170 memset (&info, 0, sizeof (info));
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,
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.
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
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)
213 template_plugin_send (void *cls,
214 struct GNUNET_ATS_Session *session,
217 unsigned int priority,
218 struct GNUNET_TIME_Relative to,
219 GNUNET_TRANSPORT_TransmitContinuation cont,
222 /* struct Plugin *plugin = cls; */
223 ssize_t bytes_sent = 0;
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).
235 * @param target peer from which to disconnect
238 template_plugin_disconnect_peer (void *cls,
239 const struct GNUNET_PeerIdentity *target)
241 // struct Plugin *plugin = cls;
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).
252 * @param session session from which to disconnect
253 * @return #GNUNET_OK on success
256 template_plugin_disconnect_session (void *cls,
257 struct GNUNET_ATS_Session *session)
259 // struct Plugin *plugin = cls;
261 return GNUNET_SYSERR;
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.
270 * @param cls closure with the `struct Plugin`
271 * @return keepalive factor
274 template_plugin_query_keepalive_factor (void *cls)
281 * Function obtain the network type for a session
283 * @param cls closure ('struct Plugin*')
284 * @param session the session
285 * @return the network type in HBO or #GNUNET_SYSERR
287 static enum GNUNET_NetworkType
288 template_plugin_get_network (void *cls,
289 struct GNUNET_ATS_Session *session)
291 GNUNET_assert (NULL != session);
292 return GNUNET_NT_UNSPECIFIED; /* Change to correct network type */
297 * Function obtain the network type for an address.
299 * @param cls closure (`struct Plugin *`)
300 * @param address the address
301 * @return the network type
303 static enum GNUNET_NetworkType
304 template_plugin_get_network_for_address (void *cls,
305 const struct GNUNET_HELLO_Address *address)
307 return GNUNET_NT_WAN; /* FOR NOW */
312 * Convert the transports address to a nice, human-readable
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
326 template_plugin_address_pretty_printer (void *cls, const char *type,
327 const void *addr, size_t addrlen,
329 struct GNUNET_TIME_Relative timeout,
330 GNUNET_TRANSPORT_AddressStringCallback
333 asc (asc_cls, "converted address", GNUNET_OK); /* return address */
334 asc (asc_cls, NULL, GNUNET_OK); /* done */
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
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
352 template_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
354 /* struct Plugin *plugin = cls; */
356 /* check if the address is belonging to the plugin*/
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.
368 * @param addr binary address
369 * @param addrlen length of the address
370 * @return string representing the same address
373 template_plugin_address_to_string (void *cls, const void *addr, size_t addrlen)
376 * Print address in format template.options.address
381 return TRANSPORT_SESSION_INBOUND_STRING;
390 * Function called to convert a string address to
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
402 template_plugin_string_to_address (void *cls,
405 void **buf, size_t *added)
408 * Parse string in format template.options.address
411 return GNUNET_SYSERR;
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
421 * @param address pointer to the GNUNET_HELLO_Address
422 * @return the session if the address is valid, NULL otherwise
424 static struct GNUNET_ATS_Session *
425 template_plugin_get_session (void *cls,
426 const struct GNUNET_HELLO_Address *address)
434 template_plugin_update_session_timeout (void *cls,
435 const struct GNUNET_PeerIdentity *peer,
436 struct GNUNET_ATS_Session *session)
444 * Return information about the given session to the
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)
453 send_session_info_iter (void *cls,
454 const struct GNUNET_PeerIdentity *peer,
457 struct Plugin *plugin = cls;
458 struct GNUNET_ATS_Session *session = value;
460 notify_session_monitor (plugin,
462 GNUNET_TRANSPORT_SS_UP);
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).
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
481 template_plugin_setup_monitor (void *cls,
482 GNUNET_TRANSPORT_SessionInfoCallback sic,
485 struct Plugin *plugin = cls;
488 plugin->sic_cls = sic_cls;
492 GNUNET_CONTAINER_multipeermap_iterate (NULL /* FIXME */,
493 &send_session_info_iter,
496 /* signal end of first iteration */
497 sic (sic_cls, NULL, NULL);
503 * Entry point for the plugin.
506 libgnunet_plugin_transport_template_init (void *cls)
508 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
509 struct GNUNET_TRANSPORT_PluginFunctions *api;
510 struct Plugin *plugin;
512 if (NULL == env->receive)
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);
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;
524 plugin = GNUNET_new (struct Plugin);
526 api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
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");
547 * Exit point from the plugin.
550 libgnunet_plugin_transport_template_done (void *cls)
552 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
553 struct Plugin *plugin = api->cls;
555 GNUNET_free (plugin);
560 /* end of plugin_transport_template.c */