(no commit message)
[oweals/gnunet.git] / src / transport / plugin_transport.h
index 795d4ed25729037fa401597241d79bb21a5700ec..d3dc52f3249954e885c81ccbe94117ac830091d6 100644 (file)
@@ -1,10 +1,10 @@
 /*
      This file is part of GNUnet
-     (C) 2009 Christian Grothoff (and other contributing authors)
+     (C) 2009, 2010 Christian Grothoff (and other contributing authors)
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
  *        Note that the destructors of transport plugins will
  *        be given the value returned by the constructor
  *        and is expected to return a NULL pointer.
- *
- * TODO:
- * - consider moving DATA message (latency measurement)
- *   to service; avoids encapsulation overheads and
- *   would enable latency measurements for non-bidi
- *   transports.
- * -
- *
  * @author Christian Grothoff
  */
 #ifndef PLUGIN_TRANSPORT_H
 
 #include "gnunet_configuration_lib.h"
 #include "gnunet_scheduler_lib.h"
+#include "gnunet_statistics_service.h"
 #include "gnunet_transport_service.h"
 
 /**
- * Function called by the transport for each received message.
- * This function should also be called with "NULL" for the
- * message to signal that the other peer disconnected.
- *
+ * Opaque pointer that plugins can use to distinguish specific
+ * connections to a given peer.  Typically used by stateful plugins to
+ * allow the service to refer to specific streams instead of a more
+ * general notion of "some connection" to the given peer.  This is
+ * useful since sometimes (i.e. for inbound TCP connections) a
+ * connection may not have an address that can be used for meaningful
+ * distinction between sessions to the same peer.
+ */
+struct Session;
+
+/**
+ * Every 'struct Session' must begin with this header.
+ */
+struct SessionHeader
+{
+
+  /**
+   * Cached signature for PONG generation for the session.  Do not use
+   * in the plugin!
+   */
+  struct GNUNET_CRYPTO_RsaSignature pong_signature;
+
+  /**
+   * Expiration time for signature.  Do not use in the plugin!
+   */
+  struct GNUNET_TIME_Absolute pong_sig_expires;
+  
+};
+
+/**
+ * Function that will be called whenever the plugin internally
+ * cleans up a session pointer and hence the service needs to
+ * discard all of those sessions as well.  Plugins that do not
+ * use sessions can simply omit calling this function and always
+ * use NULL wherever a session pointer is needed.
+ * 
  * @param cls closure
- * @param latency estimated latency for communicating with the
- *        given peer; should be set to GNUNET_TIME_UNIT_FOREVER_REL
- *        until the transport has seen messages transmitted in
- *        BOTH directions (and hence been able to do an actual
- *        round-trip observation); a non-FOREVER latency is also used
- *        by the transport to know that communication in both directions
- *        using this one plugin actually works
- * @param peer (claimed) identity of the other peer
- * @param message the message, NULL if peer was disconnected
+ * @param peer which peer was the session for 
+ * @param session which session is being destoyed
  */
-typedef void (*GNUNET_TRANSPORT_PluginReceiveCallback) (void *cls,
-                                                        struct
-                                                        GNUNET_TIME_Relative
-                                                        latency,
-                                                        const struct
-                                                        GNUNET_PeerIdentity *
-                                                        peer,
-                                                        const struct
-                                                        GNUNET_MessageHeader *
-                                                        message);
+typedef void (*GNUNET_TRANSPORT_SessionEnd) (void *cls,
+                                            const struct GNUNET_PeerIdentity *peer,
+                                            struct Session *session);
 
 
 /**
- * Function that will be called if we receive a validation
- * of an address challenge that we transmitted to another
- * peer.  Note that the validation should only be considered
- * acceptable if the challenge matches AND if the sender
- * address is at least a plausible address for this peer
- * (otherwise we may be seeing a MiM attack).
+ * Function called by the transport for each received message.
+ * This function should also be called with "NULL" for the
+ * message to signal that the other peer disconnected.
  *
  * @param cls closure
- * @param name name of the transport that generated the address
- * @param peer who responded to our challenge
- * @param challenge the challenge number we presumably used
- * @param sender_addr string describing our sender address (as observed
- *         by the other peer in human-readable format)
+ * @param peer (claimed) identity of the other peer
+ * @param message the message, NULL if we only care about
+ *                learning about the delay until we should receive again -- FIXME!
+ * @param distance in overlay hops; use 1 unless DV (or 0 if message == NULL)
+ * @param session identifier used for this session (NULL for plugins
+ *                that do not offer bi-directional communication to the sender
+ *                using the same "connection")
+ * @param sender_address binary address of the sender (if we established the
+ *                connection or are otherwise sure of it; should be NULL
+ *                for inbound TCP/UDP connections since it it not clear
+ *                that we could establish ourselves a connection to that
+ *                IP address and get the same system)
+ * @param sender_address_len number of bytes in sender_address
+ * @return how long the plugin should wait until receiving more data
+ *         (plugins that do not support this, can ignore the return value)
  */
-typedef void (*GNUNET_TRANSPORT_ValidationNotification) (void *cls,
-                                                         const char *name,
-                                                         const struct
-                                                         GNUNET_PeerIdentity *
-                                                         peer,
-                                                         uint32_t challenge,
-                                                         const char
-                                                         *sender_addr);
-
+typedef struct GNUNET_TIME_Relative (*GNUNET_TRANSPORT_PluginReceiveCallback) (void *cls,
+                                                                              const struct
+                                                                              GNUNET_PeerIdentity *
+                                                                              peer,
+                                                                              const struct
+                                                                              GNUNET_MessageHeader *
+                                                                              message,
+                                                                              uint32_t distance,
+                                                                              struct Session *session,
+                                                                              const char *sender_address,
+                                                                              uint16_t sender_address_len);
 
 
 /**
@@ -111,25 +131,31 @@ typedef void (*GNUNET_TRANSPORT_ValidationNotification) (void *cls,
 typedef void (*GNUNET_TRANSPORT_AddressNotification) (void *cls,
                                                       const char *name,
                                                       const void *addr,
-                                                      size_t addrlen,
+                                                      uint16_t addrlen,
                                                       struct
                                                       GNUNET_TIME_Relative
                                                       expires);
 
 
 /**
- * Function that will be called for each address obtained from the HELLO.
- *
+ * Function that will be called whenever the plugin receives data over
+ * the network and wants to determine how long it should wait until
+ * the next time it reads from the given peer.  Note that some plugins
+ * (such as UDP) may not be able to wait (for a particular peer), so
+ * the waiting part is optional.  Plugins that can wait should call
+ * this function, sleep the given amount of time, and call it again
+ * (with zero bytes read) UNTIL it returns zero and only then read.
+ * 
  * @param cls closure
- * @param name name of the transport that generated the address
- * @param addr one of the addresses of the host, NULL for the last address
- *        the specific address format depends on the transport
- * @param addrlen length of the address
+ * @param peer which peer did we read data from 
+ * @param amount_recved number of bytes read (can be zero)
+ * @return how long to wait until reading more from this peer
+ *         (to enforce inbound quotas)
  */
-typedef void (*GNUNET_TRANSPORT_AddressCallback) (void *cls,
-                                                  const char *name,
-                                                  const void *addr,
-                                                  size_t addrlen);
+typedef struct GNUNET_TIME_Relative (*GNUNET_TRANSPORT_TrafficReport) (void *cls,
+                                                                      const struct 
+                                                                      GNUNET_PeerIdentity *peer,
+                                                                      size_t amount_recved);
 
 
 /**
@@ -149,16 +175,6 @@ struct GNUNET_TRANSPORT_PluginEnvironment
    */
   struct GNUNET_SCHEDULER_Handle *sched;
 
-  /**
-   * Our public key.
-   */
-  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *my_public_key;
-
-  /**
-   * Our private key.
-   */
-  struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
-
   /**
    * Identity of this peer.
    */
@@ -169,6 +185,11 @@ struct GNUNET_TRANSPORT_PluginEnvironment
    */
   void *cls;
 
+  /**
+   * Handle for reporting statistics.
+   */
+  struct GNUNET_STATISTICS_Handle *stats;
+
   /**
    * Function that should be called by the transport plugin
    * whenever a message is received.
@@ -183,18 +204,16 @@ struct GNUNET_TRANSPORT_PluginEnvironment
   GNUNET_TRANSPORT_AddressNotification notify_address;
 
   /**
-   * Function that must be called by each plugin to notify the
-   * transport service about a successful validation of an
-   * address of another peer (or at least likely successful
-   * validation).
+   * Inform service about traffic received, get information
+   * about when we might be willing to receive more.
    */
-  GNUNET_TRANSPORT_ValidationNotification notify_validation;
+  GNUNET_TRANSPORT_TrafficReport traffic_report;
 
   /**
-   * What is the default quota (in terms of incoming bytes per
-   * ms) for new connections?
+   * Function that must be called by the plugin when a non-NULL
+   * session handle stops being valid (is destroyed).
    */
-  uint32_t default_quota_in;
+  GNUNET_TRANSPORT_SessionEnd session_end;
 
   /**
    * What is the maximum number of connections that this transport
@@ -206,30 +225,6 @@ struct GNUNET_TRANSPORT_PluginEnvironment
 };
 
 
-/**
- * Function that can be used by the transport service to validate
- * the address of another peer.  Even if
- * we already have a connection to this peer, this function is
- * required to establish a new one.
- *
- * @param cls closure
- * @param target who should receive this message
- * @param challenge challenge code to use
- * @param timeout how long should we try to transmit these?
- * @param addrlen length of the address
- * @param addr the address
- * @return GNUNET_OK on success, GNUNET_SYSERR if the address
- *         format is invalid
- */
-typedef int
-  (*GNUNET_TRANSPORT_ValidationFunction) (void *cls,
-                                          const struct
-                                          GNUNET_PeerIdentity * target,
-                                          uint32_t challenge,
-                                          struct GNUNET_TIME_Relative
-                                          timeout, const void *addr,
-                                          size_t addrlen);
-
 /**
  * Function called by the GNUNET_TRANSPORT_TransmitFunction
  * upon "completion".
@@ -257,24 +252,45 @@ typedef void
  *
  * @param cls closure
  * @param target who should receive this message
- * @param priority how important is the message?
- * @param msg the message to transmit
- * @param timeout how long to wait at most for the transmission
+ * @param msgbuf the message to transmit
+ * @param msgbuf_size number of bytes in 'msgbuf'
+ * @param priority how important is the message (most plugins will
+ *                 ignore message priority and just FIFO)
+ * @param timeout how long to wait at most for the transmission (does not
+ *                require plugins to discard the message after the timeout,
+ *                just advisory for the desired delay; most plugins will ignore
+ *                this as well)
+ * @param session which session must be used (or NULL for "any")
+ * @param addr the address to use (can be NULL if the plugin
+ *                is "on its own" (i.e. re-use existing TCP connection))
+ * @param addrlen length of the address in bytes
+ * @param force_address GNUNET_YES if the plugin MUST use the given address,
+ *                GNUNET_NO means the plugin may use any other address and
+ *                GNUNET_SYSERR means that only reliable existing
+ *                bi-directional connections should be used (regardless
+ *                of address)
  * @param cont continuation to call once the message has
  *        been transmitted (or if the transport is ready
  *        for the next transmission call; or if the
  *        peer disconnected...); can be NULL
  * @param cont_cls closure for cont
+ * @return number of bytes used (on the physical network, with overheads);
+ *         -1 on hard errors (i.e. address invalid); 0 is a legal value
+ *         and does NOT mean that the message was not transmitted (DV)
  */
-typedef void
+typedef ssize_t
   (*GNUNET_TRANSPORT_TransmitFunction) (void *cls,
                                         const struct GNUNET_PeerIdentity *
                                         target,
-                                        unsigned int priority,
-                                        const struct GNUNET_MessageHeader *
-                                        msg,
+                                        const char *msgbuf,
+                                        size_t msgbuf_size,
+                                        uint32_t priority,
                                         struct GNUNET_TIME_Relative timeout,
-                                        GNUNET_TRANSPORT_TransmitContinuation
+                                       struct Session *session,
+                                        const void *addr,
+                                       size_t addrlen,
+                                       int force_address,
+                                       GNUNET_TRANSPORT_TransmitContinuation
                                         cont, void *cont_cls);
 
 
@@ -339,34 +355,39 @@ typedef void
 
 
 /**
- * Set a quota for receiving data from the given peer; this is a
- * per-transport limit.  The transport should limit its read/select
- * calls to stay below the quota (in terms of incoming data).
+ * Another peer has suggested an address for this peer and transport
+ * plugin.  Check that this could be a valid address.  This function
+ * is not expected to 'validate' the address in the sense of trying to
+ * connect to it but simply to see if the binary format is technically
+ * legal for establishing a connection to this peer (and make sure that
+ * the address really corresponds to our network connection/settings
+ * and not some potential man-in-the-middle).
  *
- * @param cls closure
- * @param peer the peer for whom the quota is given
- * @param quota_in quota for receiving/sending data in bytes per ms
+ * @param addr pointer to the address
+ * @param addrlen length of addr
+ * @return GNUNET_OK if this is a plausible address for this peer
+ *         and transport, GNUNET_SYSERR if not
  */
-typedef void
-  (*GNUNET_TRANSPORT_SetQuota) (void *cls,
-                                const struct GNUNET_PeerIdentity * target,
-                                uint32_t quota_in);
+typedef int
+(*GNUNET_TRANSPORT_CheckAddress) (void *cls,
+                                 const void *addr, size_t addrlen);
 
 
 /**
- * Another peer has suggested an address for this
- * peer and transport plugin.  Check that this could be a valid
- * address.  If so, consider adding it to the list
- * of addresses.
+ * Function called for a quick conversion of the binary address to
+ * a numeric address.  Note that the caller must not free the 
+ * address and that the next call to this function is allowed
+ * to override the address again.
  *
- * @param addr pointer to the address
- * @param addrlen length of addr
- * @return GNUNET_OK if this is a plausible address for this peer
- *         and transport
+ * @param cls closure
+ * @param addr binary address
+ * @param addr_len length of the address
+ * @return string representing the same address 
  */
-typedef int
-  (*GNUNET_TRANSPORT_SuggestAddress) (void *cls,
-                                      const void *addr, size_t addrlen);
+typedef const char* (*GNUNET_TRANSPORT_AddressToString) (void *cls,
+                                                        const void *addr,
+                                                        size_t addrlen);
+
 
 /**
  * Each plugin is required to return a pointer to a struct of this
@@ -380,16 +401,9 @@ struct GNUNET_TRANSPORT_PluginFunctions
    */
   void *cls;
 
-  /**
-   * Function used to send a single message to a particular
-   * peer using the specified address.  Used to validate
-   * HELLOs.
-   */
-  GNUNET_TRANSPORT_ValidationFunction validate;
-
   /**
    * Function that the transport service will use to transmit data to
-   * another peer.  May be null for plugins that only support
+   * another peer.  May be NULL for plugins that only support
    * receiving data.  After this call, the plugin call the specified
    * continuation with success or error before notifying us about the
    * target having disconnected.
@@ -413,31 +427,22 @@ struct GNUNET_TRANSPORT_PluginFunctions
   GNUNET_TRANSPORT_AddressPrettyPrinter address_pretty_printer;
 
   /**
-   * Function that the transport service can use to try to enforce a
-   * quota for the number of bytes received via this transport.
-   * Transports that can not refuse incoming data (such as UDP)
-   * are free to ignore these calls.
+   * Function that will be called to check if a binary address
+   * for this plugin is well-formed and corresponds to an
+   * address for THIS peer (as per our configuration).  Naturally,
+   * if absolutely necessary, plugins can be a bit conservative in
+   * their answer, but in general plugins should make sure that the
+   * address does not redirect traffic to a 3rd party that might
+   * try to man-in-the-middle our traffic.
    */
-  GNUNET_TRANSPORT_SetQuota set_receive_quota;
+  GNUNET_TRANSPORT_CheckAddress check_address;
 
   /**
-   * Function that will be called if another peer suggested that
-   * we should use a particular address (since he is reaching
-   * us at that address) for this transport.
+   * Function that will be called to convert a binary address
+   * to a string (numeric conversion only).
    */
-  GNUNET_TRANSPORT_SuggestAddress address_suggested;
+  GNUNET_TRANSPORT_AddressToString address_to_string;
 
-  /**
-   * Relative cost of this transport compared to others.  This
-   * is supposed to be a static cost estimate which determines
-   * which plugins should not even be attempted if other,
-   * cheaper transports are already working.  The idea is that
-   * the costs have roughly this relationship:
-   * <pre>
-   * TCP < UDP < HTTP == HTTPS < SMTP
-   * </pre>
-   */
-  unsigned int cost_estimate;
 };