GNUnet debian-0.24.3-29-g453fda2cf
 
Loading...
Searching...
No Matches
gnunet-service-transport.c File Reference

main for gnunet-service-transport More...

Include dependency graph for gnunet-service-transport.c:

Go to the source code of this file.

Data Structures

struct  MessageUUIDP
 Unique identifier we attach to a message. More...
 
struct  AcknowledgementUUIDP
 Unique identifier to map an acknowledgement to a transmission. More...
 
struct  TransportBackchannelEncapsulationMessage
 Outer layer of an encapsulated backchannel message. More...
 
struct  EphemeralConfirmationPS
 Body by which a peer confirms that it is using an ephemeral key. More...
 
struct  TransportDVBoxPayloadP
 Plaintext of the variable-size payload that is encrypted within a struct TransportBackchannelEncapsulationMessage More...
 
struct  TransportReliabilityBoxMessage
 Outer layer of an encapsulated unfragmented application message sent over an unreliable channel. More...
 
struct  TransportCummulativeAckPayloadP
 Acknowledgement payload. More...
 
struct  TransportReliabilityAckMessage
 Confirmation that the receiver got a GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX. More...
 
struct  TransportFragmentBoxMessage
 Outer layer of an encapsulated fragmented application message. More...
 
struct  DvInitPS
 Content signed by the initiator during DV learning. More...
 
struct  DvHopPS
 Content signed by each peer during DV learning. More...
 
struct  DVPathEntryP
 An entry describing a peer on a path in a struct TransportDVLearnMessage message. More...
 
struct  TransportDVLearnMessage
 Internal message used by transport for distance vector learning. More...
 
struct  TransportDVBoxMessage
 Outer layer of an encapsulated message send over multiple hops. More...
 
struct  TransportValidationChallengeMessage
 Message send to another peer to validate that it can indeed receive messages at a particular address. More...
 
struct  TransportValidationPS
 Message signed by a peer to confirm that it can indeed receive messages at a particular address. More...
 
struct  TransportValidationResponseMessage
 Message send to a peer to respond to a #GNUNET_MESSAGE_TYPE_ADDRESS_VALIDATION_CHALLENGE. More...
 
struct  TransportGlobalNattedAddress
 
struct  TransportFlowControlMessage
 Message for Transport-to-Transport Flow control. More...
 
struct  LearnLaunchEntry
 When did we launch this DV learning activity? More...
 
struct  TransmissionHistoryEntry
 Information we keep per GOODPUT_AGING_SLOTS about historic (or current) transmission performance. More...
 
struct  PerformanceData
 Performance data for a transmission possibility. More...
 
struct  CommunicatorMessageContext
 Context from handle_incoming_msg(). More...
 
struct  RingBufferEntry
 Entry for the ring buffer caching messages send to core, when virtual link is available. More...
 
struct  CoreSentContext
 Closure for core_env_sent_cb. More...
 
struct  ReassemblyContext
 Information we keep for a message that we are reassembling. More...
 
struct  VirtualLink
 A virtual link is another reachable peer that is known to CORE. More...
 
struct  PendingAcknowledgement
 Data structure kept when we are waiting for an acknowledgement. More...
 
struct  DistanceVectorHop
 One possible hop towards a DV target. More...
 
struct  DistanceVector
 Entry in our dv_routes table, representing a (set of) distance vector routes to a particular peer. More...
 
struct  QueueEntry
 Entry identifying transmission in one of our struct Queue which still awaits an ACK. More...
 
struct  Queue
 Handle for a queue. More...
 
struct  Neighbour
 A neighbour that at least one communicator is connected to. More...
 
struct  IncomingRequest
 Another peer attempted to talk to us, we should try to establish a connection in the other direction. More...
 
struct  PeerRequest
 Information per peer and request. More...
 
struct  PendingMessage
 List containing all messages that are yet to be send. More...
 
struct  TransportCummulativeAckPayload
 Acknowledgement payload. More...
 
struct  AcknowledgementCummulator
 Data structure in which we track acknowledgements still to be sent to the. More...
 
struct  AddressListEntry
 One of the addresses of this peer. More...
 
struct  TransportClient
 Client connected to the transport service. More...
 
struct  ValidationState
 State we keep for validation activities. More...
 
struct  Backtalker
 A Backtalker is a peer sending us backchannel messages. More...
 
struct  PilsRequest
 DLL. More...
 
struct  MonitorEvent
 Details about what to notify monitors about. More...
 
struct  SignDvCls
 
struct  DVKeyState
 Structure of the key material used to encrypt backchannel messages. More...
 
struct  AddGlobalAddressesContext
 
struct  PilsAddressSignContext
 Helper context struct for HELLO update. More...
 
struct  SignedAddress
 Binary block we sign when we sign an address. More...
 
struct  FindByMessageUuidContext
 Closure for find_by_message_uuid. More...
 
struct  SignDhpCls
 
struct  NeighbourSelectionContext
 Closure for dv_neighbour_selection and dv_neighbour_transmission. More...
 
struct  DecapsDvBoxCls
 
struct  CheckKnownAddressContext
 Closure for check_known_address. More...
 
struct  SignTValidationCls
 
struct  CheckKnownChallengeContext
 Closure for check_known_challenge. More...
 
struct  PendingMessageScoreContext
 Context for select_best_pending_from_link(). More...
 
struct  QueueQualityContext
 Closure for check_connection_quality. More...
 
struct  SignDvInitCls
 
struct  TransportGlobalNattedAddressClosure
 
struct  UpdateHelloFromPidCtx
 

Macros

#define RING_BUFFER_SIZE   16
 Size of ring buffer to cache CORE and forwarded DVBox messages.
 
#define MAX_FC_RETRANSMIT_COUNT   1000
 Maximum number of FC retransmissions for a running retransmission task.
 
#define MAX_CUMMULATIVE_ACKS   64
 Maximum number of messages we acknowledge together in one cumulative ACK.
 
#define FC_NO_CHANGE_REPLY_PROBABILITY   8
 What is the 1:n chance that we send a Flow control response when receiving a flow control message that did not change anything for us? Basically, this is used in the case where both peers are stuck on flow control (no window changes), but one might continue sending flow control messages to the other peer as the first FC message when things stalled got lost, and then subsequently the other peer does usually not respond as nothing changed.
 
#define IN_PACKET_SIZE_WITHOUT_MTU   128
 What is the size we assume for a read operation in the absence of an MTU for the purpose of flow control?
 
#define GOODPUT_AGING_SLOTS   4
 Number of slots we keep of historic data for computation of goodput / message loss ratio.
 
#define DEFAULT_WINDOW_SIZE   (128 * 1024)
 How big is the flow control window size by default; limits per-neighbour RAM utilization.
 
#define MAX_INCOMING_REQUEST   16
 For how many incoming connections do we try to create a virtual link for (at the same time!).
 
#define MAX_DV_DISCOVERY_SELECTION   16
 Maximum number of peers we select for forwarding DVInit messages at the same time (excluding initiator).
 
#define RECV_WINDOW_SIZE   4
 Window size.
 
#define MIN_DV_PATH_LENGTH_FOR_INITIATOR   3
 Minimum number of hops we should forward DV learn messages even if they are NOT useful for us in hope of looping back to the initiator?
 
#define MAX_DV_HOPS_ALLOWED   16
 Maximum DV distance allowed ever.
 
#define MAX_DV_LEARN_PENDING   64
 Maximum number of DV learning activities we may have pending at the same time.
 
#define MAX_DV_PATHS_TO_TARGET   3
 Maximum number of DV paths we keep simultaneously to the same target.
 
#define PILS_FEED_ADDRESSES_DELAY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3)
 Delay between added/removed addresses and PILS feed call.
 
#define DELAY_WARN_THRESHOLD    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
 If a queue delays the next message by more than this number of seconds we log a warning.
 
#define DV_FORWARD_TIMEOUT    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
 If a DVBox could not be forwarded after this number of seconds we drop it.
 
#define DEFAULT_ACK_WAIT_DURATION    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
 Default value for how long we wait for reliability ack.
 
#define DV_QUALITY_RTT_THRESHOLD    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
 We only consider queues as "quality" connections when suppressing the generation of DV initiation messages if the latency of the queue is below this threshold.
 
#define DV_PATH_VALIDITY_TIMEOUT    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
 How long do we consider a DV path valid if we see no further updates on it? Note: the value chosen here might be too low!
 
#define BACKCHANNEL_INACTIVITY_TIMEOUT    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
 How long do we cache backchannel (struct Backtalker) information after a backchannel goes inactive?
 
#define DV_PATH_DISCOVERY_FREQUENCY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
 How long before paths expire would we like to (re)discover DV paths? Should be below DV_PATH_VALIDITY_TIMEOUT.
 
#define EPHEMERAL_VALIDITY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
 How long are ephemeral keys valid?
 
#define REASSEMBLY_EXPIRATION    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
 How long do we keep partially reassembled messages around before giving up?
 
#define FAST_VALIDATION_CHALLENGE_FREQ    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1)
 What is the fastest rate at which we send challenges if we keep learning an address (gossip, DHT, etc.)?
 
#define MAX_VALIDATION_CHALLENGE_FREQ    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_DAYS, 1)
 What is the slowest rate at which we send challenges?
 
#define ACK_CUMMULATOR_TIMEOUT    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
 How long until we forget about historic accumulators and thus reset the ACK counter? Should exceed the maximum time an active connection experiences without an ACK.
 
#define DV_LEARN_BASE_FREQUENCY   GNUNET_TIME_UNIT_MINUTES
 What is the non-randomized base frequency at which we would initiate DV learn messages?
 
#define DV_LEARN_QUALITY_THRESHOLD   100
 How many good connections (confirmed, bi-directional, not DV) do we need to have to suppress initiating DV learn messages?
 
#define MAX_ADDRESS_VALID_UNTIL    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MONTHS, 1)
 When do we forget an invalid address for sure?
 
#define ADDRESS_VALIDATION_LIFETIME    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
 How long do we consider an address valid if we just checked?
 
#define MIN_DELAY_ADDRESS_VALIDATION   GNUNET_TIME_UNIT_MILLISECONDS
 What is the maximum frequency at which we do address validation? A random value between 0 and this value is added when scheduling the validation_task (both to ensure we do not validate too often, and to randomize a bit).
 
#define VALIDATION_RTT_BUFFER_FACTOR   3
 How many network RTTs before an address validation expires should we begin trying to revalidate? (Note that the RTT used here is the one that we experienced during the last validation, not necessarily the latest RTT observed).
 
#define COMMUNICATOR_TOTAL_QUEUE_LIMIT   512
 How many messages can we have pending for a given communicator process before we start to throttle that communicator?
 
#define QUEUE_LENGTH_LIMIT   32
 How many messages can we have pending for a given queue (queue to a particular peer via a communicator) process before we start to throttle that queue?
 
#define QUEUE_ENTRY_TIMEOUT    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
 
#define RTT_DIFF    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
 Difference of the average RTT for the DistanceVector calculate by us and the target we are willing to accept for starting the burst.
 

Typedefs

typedef void(* DVMessageHandler) (void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
 Function to call to further operate on the now DV encapsulated message hdr, forwarding it via next_hop under respect of options.
 

Enumerations

enum  ClientType {
  CT_NONE = 0 , CT_CORE = 1 , CT_MONITOR = 2 , CT_COMMUNICATOR = 3 ,
  CT_APPLICATION = 4
}
 What type of client is the struct TransportClient about? More...
 
enum  RouteMessageOptions {
  RMO_NONE = 0 , RMO_DV_ALLOWED = 1 , RMO_UNCONFIRMED_ALLOWED = 2 , RMO_ANYTHING_GOES = (RMO_DV_ALLOWED | RMO_UNCONFIRMED_ALLOWED) ,
  RMO_REDUNDANT = 4
}
 Which transmission options are allowable for transmission? Interpreted bit-wise! More...
 
enum  PendingMessageType { PMT_CORE = 0 , PMT_FRAGMENT_BOX = 1 , PMT_RELIABILITY_BOX = 2 , PMT_DV_BOX = 3 }
 Types of different pending messages. More...
 

Functions

static unsigned int get_age ()
 Get an offset into the transmission history buffer for struct PerformanceData.
 
static void free_incoming_request (struct IncomingRequest *ir)
 Release ir data structure.
 
static void free_pending_acknowledgement (struct PendingAcknowledgement *pa)
 Release pa data structure.
 
static void free_fragment_tree (struct PendingMessage *root)
 Free fragment tree below root, excluding root itself.
 
static void free_pending_message (struct PendingMessage *pm)
 Release memory associated with pm and remove pm from associated data structures.
 
static void free_reassembly_context (struct ReassemblyContext *rc)
 Free rc.
 
static void reassembly_cleanup_task (void *cls)
 Task run to clean up reassembly context of a neighbour that have expired.
 
static int free_reassembly_cb (void *cls, uint32_t key, void *value)
 function called to free_reassembly_context().
 
static void free_virtual_link (struct VirtualLink *vl)
 Free virtual link.
 
static void free_validation_state (struct ValidationState *vs)
 Free validation state.
 
static struct Neighbourlookup_neighbour (const struct GNUNET_PeerIdentity *pid)
 Lookup neighbour for peer pid.
 
static struct VirtualLinklookup_virtual_link (const struct GNUNET_PeerIdentity *pid)
 Lookup virtual link for peer pid.
 
static void free_distance_vector_hop (struct DistanceVectorHop *dvh)
 Free a dvh.
 
static void check_link_down (void *cls)
 Task run to check whether the hops of the cls still are validated, or if we need to core about disconnection.
 
static void cores_send_disconnect_info (const struct GNUNET_PeerIdentity *pid)
 Send message to CORE clients that we lost a connection.
 
static void free_dv_route (struct DistanceVector *dv)
 Free entry in dv_routes.
 
static void notify_monitor (struct TransportClient *tc, const struct GNUNET_PeerIdentity *peer, const char *address, enum GNUNET_NetworkType nt, const struct MonitorEvent *me)
 Notify monitor tc about an event.
 
static void notify_monitors (const struct GNUNET_PeerIdentity *peer, const char *address, enum GNUNET_NetworkType nt, const struct MonitorEvent *me)
 Send information in me about a peer's status with respect to some address to all monitors that care.
 
static void * client_connect_cb (void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
 Called whenever a client connects.
 
static enum GNUNET_GenericReturnValue remove_global_addresses (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 
static void free_neighbour (struct Neighbour *neighbour, enum GNUNET_GenericReturnValue drop_link)
 Release memory used by neighbour.
 
static void core_send_connect_info (struct TransportClient *tc, const struct GNUNET_PeerIdentity *pid)
 Send message to CORE clients that we lost a connection.
 
static void cores_send_connect_info (const struct GNUNET_PeerIdentity *pid)
 Send message to CORE clients that we gained a connection.
 
static void transmit_on_queue (void *cls)
 We believe we are ready to transmit a message on a queue.
 
static unsigned int check_for_queue_with_higher_prio (struct Queue *queue, struct Queue *queue_head)
 Check if the communicator has another queue with higher prio ready for sending.
 
static void schedule_transmit_on_queue (struct GNUNET_TIME_Relative delay, struct Queue *queue, enum GNUNET_SCHEDULER_Priority p)
 Called whenever something changed that might effect when we try to do the next transmission on queue using transmit_on_queue().
 
static void free_queue (struct Queue *queue)
 Free queue.
 
static void free_address_list_entry (struct AddressListEntry *ale)
 Free ale.
 
static int stop_peer_request (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Stop the peer request in value.
 
static void do_shutdown (void *cls)
 Function called when the service shuts down.
 
static void client_disconnect_cb (void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
 Called whenever a client is disconnected.
 
static int notify_client_connect_info (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Iterator telling new CORE client about all existing connections to peers.
 
static void finish_cmc_handling_with_continue (struct CommunicatorMessageContext *cmc, unsigned int free_cmc)
 Send ACK to communicator (if requested) and free cmc.
 
static enum GNUNET_GenericReturnValue resume_communicators (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 
static void handle_client_start (void *cls, const struct StartMessage *start)
 Initialize a "CORE" client.
 
static int check_client_send (void *cls, const struct OutboundMessage *obm)
 Client asked for transmission to a peer.
 
static void client_send_response (struct PendingMessage *pm)
 Send a response to the pm that we have processed a "send" request.
 
static unsigned int pick_random_dv_hops (const struct DistanceVector *dv, enum RouteMessageOptions options, struct DistanceVectorHop **hops_array, unsigned int hops_array_length)
 Pick hops_array_length random DV paths satisfying options.
 
static int check_communicator_available (void *cls, const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
 Communicator started.
 
static void finish_cmc_handling (struct CommunicatorMessageContext *cmc)
 
static void handle_client_recv_ok (void *cls, const struct RecvOkMessage *rom)
 Client confirms that it is done handling message(s) to a particular peer.
 
static void handle_communicator_available (void *cls, const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
 Communicator started.
 
static int check_communicator_backchannel (void *cls, const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
 Communicator requests backchannel transmission.
 
static void sign_dv_cb (void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
 
static void sign_ephemeral (struct DistanceVector *dv)
 Sign ephemeral keys in our dv are current.
 
static void free_queue_entry (struct QueueEntry *qe, struct TransportClient *tc)
 
static void free_timedout_queue_entry (void *cls)
 
static void queue_send_msg (struct Queue *queue, struct PendingMessage *pm, const void *payload, size_t payload_size)
 Send the message payload on queue.
 
static struct GNUNET_TIME_Relative route_via_neighbour (const struct Neighbour *n, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
 Pick a queue of n under constraints options and schedule transmission of hdr.
 
static void dv_setup_key_state_from_km (const struct GNUNET_ShortHashCode *km, const struct GNUNET_ShortHashCode *iv, struct DVKeyState *key)
 Given the key material in km and the initialization vector iv, setup the key material for the backchannel in key.
 
static void dv_hmac (const struct DVKeyState *key, struct GNUNET_HashCode *hmac, const void *data, size_t data_size)
 Do HMAC calculation for backchannel messages over data using key material from key.
 
static void dv_encrypt (struct DVKeyState *key, const void *in, void *dst, size_t in_size)
 Perform backchannel encryption using symmetric secret in key to encrypt data from in to dst.
 
static enum GNUNET_GenericReturnValue dv_decrypt (struct DVKeyState *key, void *out, const void *ciph, size_t out_size)
 Perform backchannel encryption using symmetric secret in key to encrypt data from in to dst.
 
static void dv_key_clean (struct DVKeyState *key)
 Clean up key material in key.
 
static struct GNUNET_TIME_Relative encapsulate_for_dv (struct DistanceVector *dv, unsigned int num_dvhs, struct DistanceVectorHop **dvhs, const struct GNUNET_MessageHeader *hdr, DVMessageHandler use, void *use_cls, enum RouteMessageOptions options, enum GNUNET_GenericReturnValue without_fc)
 Pick a path of dv under constraints options and schedule transmission of hdr.
 
static void send_dv_to_neighbour (void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
 Wrapper around route_via_neighbour() that matches the DVMessageHandler structure.
 
static struct GNUNET_TIME_Relative route_control_message_without_fc (struct VirtualLink *vl, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
 We need to transmit hdr to target.
 
static void consider_sending_fc (void *cls)
 Something changed on the virtual link with respect to flow control.
 
static void task_consider_sending_fc (void *cls)
 Something changed on the virtual link with respect to flow control.
 
static char * get_address_without_port (const char *address)
 Get the IP address without the port number.
 
static enum GNUNET_GenericReturnValue add_global_addresses (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 
static struct GNUNET_TIME_Relative calculate_rtt (struct DistanceVector *dv)
 
static void check_vl_transmission (struct VirtualLink *vl)
 There is a message at the head of the pending messages for vl which may be ready for transmission.
 
static void handle_client_send (void *cls, const struct OutboundMessage *obm)
 Client asked for transmission to a peer.
 
static void handle_communicator_backchannel (void *cls, const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
 Communicator requests backchannel transmission.
 
static int check_add_address (void *cls, const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
 Address of our peer added.
 
static void store_pi (void *cls)
 Ask peerstore to store our address.
 
static void shc_cont (void *cls, int success)
 
static void pils_sign_hello_cb (void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
 Get HELLO signature and create message to store in PEERSTORE.
 
static void peerstore_store_own_cb (void *cls, int success)
 Function called when peerstore is done storing our address.
 
static void pils_sign_addr_cb (void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
 
void pils_sign_address (struct AddressListEntry *ale, struct GNUNET_TIME_Absolute mono_time)
 Build address record by signing raw information with private key of the peer identity.
 
static struct AddressListEntrycreate_address_entry (struct TransportClient *tc, struct GNUNET_TIME_Relative expiration, enum GNUNET_NetworkType nt, const char *address, uint32_t aid, size_t slen)
 
static void feed_addresses_to_pils (void *cls)
 
static void handle_add_address (void *cls, const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
 Address of our peer added.
 
static void handle_del_address (void *cls, const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
 Address of our peer deleted.
 
static void demultiplex_with_cmc (struct CommunicatorMessageContext *cmc)
 Given an inbound message msg from a communicator cmc, demultiplex it based on the type calling the right handler.
 
static void core_env_sent_cb (void *cls)
 Function called when we are done giving a message of a certain size to CORE and should thus decrement the number of bytes of RAM reserved for that peer's MQ.
 
static void finish_handling_raw_message (struct VirtualLink *vl, const struct GNUNET_MessageHeader *mh, struct CommunicatorMessageContext *cmc, unsigned int free_cmc)
 
static void handle_raw_message (void *cls, const struct GNUNET_MessageHeader *mh)
 Communicator gave us an unencapsulated message to pass as-is to CORE.
 
static int check_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
 Communicator gave us a fragment box.
 
static void destroy_ack_cummulator (void *cls)
 Clean up an idle cumulative acknowledgement data structure.
 
static void transmit_cummulative_ack_cb (void *cls)
 Do the transmission of a cumulative acknowledgement now.
 
static void cummulative_ack (const struct GNUNET_PeerIdentity *pid, const struct AcknowledgementUUIDP *ack_uuid, struct GNUNET_TIME_Absolute max_delay)
 Transmit an acknowledgement for ack_uuid to pid delaying transmission by at most ack_delay.
 
static int find_by_message_uuid (void *cls, uint32_t key, void *value)
 Iterator called to find a reassembly context by the message UUID in the multihashmap32.
 
static void handle_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
 Communicator gave us a fragment.
 
static int check_reliability_box (void *cls, const struct TransportReliabilityBoxMessage *rb)
 Communicator gave us a reliability box.
 
static void handle_reliability_box (void *cls, const struct TransportReliabilityBoxMessage *rb)
 Communicator gave us a reliability box.
 
static void update_pd_age (struct PerformanceData *pd, unsigned int age)
 Check if we have advanced to another age since the last time.
 
static void update_performance_data (struct PerformanceData *pd, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
 Update pd based on the latest rtt and the number of bytes that were confirmed to be successfully transmitted.
 
static void update_queue_performance (struct Queue *q, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
 We have successfully transmitted data via q, update metrics.
 
static void update_dvh_performance (struct DistanceVectorHop *dvh, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
 We have successfully transmitted data via dvh, update metrics.
 
static void completed_pending_message (struct PendingMessage *pm)
 We have completed transmission of pm, remove it from the transmission queues (and if it is a fragment, continue up the tree as necessary).
 
static void handle_acknowledged (struct PendingAcknowledgement *pa, struct GNUNET_TIME_Relative ack_delay)
 The pa was acknowledged, process the acknowledgement.
 
static int check_reliability_ack (void *cls, const struct TransportReliabilityAckMessage *ra)
 Communicator gave us a reliability ack.
 
static void handle_reliability_ack (void *cls, const struct TransportReliabilityAckMessage *ra)
 Communicator gave us a reliability ack.
 
static int check_backchannel_encapsulation (void *cls, const struct TransportBackchannelEncapsulationMessage *be)
 Communicator gave us a backchannel encapsulation.
 
static void handle_backchannel_encapsulation (void *cls, const struct TransportBackchannelEncapsulationMessage *be)
 Communicator gave us a backchannel encapsulation.
 
static void path_cleanup_cb (void *cls)
 Task called when we should check if any of the DV paths we have learned to a target are due for garbage collection.
 
static void send_msg_from_cache (struct VirtualLink *vl)
 
static void activate_core_visible_dv_path (struct DistanceVectorHop *hop)
 The hop is a validated path to the respective target peer and we should tell core about it – and schedule a job to revoke the state.
 
static int learn_dv_path (const struct GNUNET_PeerIdentity *path, unsigned int path_len, struct GNUNET_TIME_Relative network_latency, struct GNUNET_TIME_Absolute path_valid_until)
 We have learned a path through the network to some other peer, add it to our DV data structure (returning GNUNET_YES on success).
 
static int check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
 Communicator gave us a DV learn message.
 
static void sign_dhp_cp (void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
 
static void forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop, const struct TransportDVLearnMessage *msg, uint16_t bi_history, uint16_t nhops, const struct DVPathEntryP *hops, struct GNUNET_TIME_Absolute in_time)
 Build and forward a DV learn message to next_hop.
 
static int validate_dv_initiator_signature (struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time, const struct GNUNET_PeerIdentity *init, const struct GNUNET_CRYPTO_ChallengeNonceP *challenge, const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
 Check signature of type GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
 
static int dv_neighbour_selection (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Function called for each neighbour during handle_dv_learn.
 
static int dv_neighbour_transmission (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Function called for each neighbour during handle_dv_learn.
 
static unsigned int calculate_fork_degree (unsigned int hops_taken, unsigned int neighbour_count, unsigned int eligible_count)
 Computes the number of neighbours we should forward a DVInit message to given that it has so far taken hops_taken hops though the network and that the number of neighbours we have in total is neighbour_count, out of which eligible_count are not yet on the path.
 
static void neighbour_store_dvmono_cb (void *cls, int success)
 Function called when peerstore is done storing a DV monotonic time.
 
static struct GNUNET_TIME_Relative get_network_latency (const struct TransportDVLearnMessage *dvl)
 
static void handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
 Communicator gave us a DV learn message.
 
static int check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
 Communicator gave us a DV box.
 
static void forward_dv_box (struct Neighbour *next_hop, struct TransportDVBoxMessage *hdr, uint16_t total_hops, uint16_t num_hops, const struct GNUNET_PeerIdentity *hops, const void *enc_payload, uint16_t enc_payload_size)
 Create a DV Box message and queue it for transmission to next_hop.
 
static void free_backtalker (struct Backtalker *b)
 Free data structures associated with b.
 
static int free_backtalker_cb (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Callback to free backtalker records.
 
static void backtalker_timeout_cb (void *cls)
 Function called when it is time to clean up a backtalker.
 
static void backtalker_monotime_cb (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
 Function called with the monotonic time of a backtalker by PEERSTORE.
 
static void backtalker_monotime_store_cb (void *cls, int success)
 Function called by PEERSTORE when the store operation of a backtalker's monotonic time is complete.
 
static void update_backtalker_monotime (struct Backtalker *b)
 The backtalker b monotonic time changed.
 
static void decaps_dv_box_cb (void *cls, const struct GNUNET_ShortHashCode *km)
 
static void handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
 Communicator gave us a DV box.
 
static int check_incoming_msg (void *cls, const struct GNUNET_TRANSPORT_IncomingMessage *im)
 Client notified us about transmission from a peer.
 
static int check_known_address (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Test if the validation state in value matches the address from cls.
 
static void validation_start_cb (void *cls)
 Task run periodically to validate some address based on validation_heap.
 
static void update_next_challenge_time (struct ValidationState *vs, struct GNUNET_TIME_Absolute new_time)
 Set the time for next_challenge of vs to new_time.
 
static void start_address_validation (const struct GNUNET_PeerIdentity *pid, const char *address)
 Start address validation.
 
static struct Queuefind_queue (const struct GNUNET_PeerIdentity *pid, const char *address)
 Find the queue matching pid and address.
 
static void suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address)
 Signature of a function called with a communicator address of a peer pid that an application wants us to connect to.
 
static void hello_for_incoming_cb (void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
 
static void handle_hello_for_incoming (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
 Function called by PEERSTORE for each matching record.
 
static void hello_for_incoming_error_cb (void *cls)
 
static void hello_for_incoming_sync_cb (void *cls)
 
static void sign_t_validation_cb (void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
 
static void handle_validation_challenge (void *cls, const struct TransportValidationChallengeMessage *tvc)
 Communicator gave us a transport address validation challenge.
 
static int check_known_challenge (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Test if the validation state in value matches the challenge from cls.
 
static void peerstore_store_validation_cb (void *cls, int success)
 Function called when peerstore is done storing a validated address.
 
static void validation_transmit_on_queue (struct Queue *q, struct ValidationState *vs)
 The queue q (which matches the peer and address in vs) is ready for queueing.
 
static void revalidation_start_cb (void *cls)
 
static enum GNUNET_GenericReturnValue revalidate_map_it (void *cls, const struct GNUNET_HashCode *key, void *value)
 
static void handle_validation_response (void *cls, const struct TransportValidationResponseMessage *tvr)
 Communicator gave us a transport address validation response.
 
static void handle_incoming_msg (void *cls, const struct GNUNET_TRANSPORT_IncomingMessage *im)
 Incoming message.
 
static int check_flow_control (void *cls, const struct TransportFlowControlMessage *fc)
 Communicator gave us a transport address validation response.
 
static void iterate_address_start_burst (void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
 
static void check_for_burst_address (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
 
static void burst_timeout (void *cls)
 
static void start_burst (void *cls)
 
static void queue_burst (void *cls)
 
static void handle_flow_control (void *cls, const struct TransportFlowControlMessage *fc)
 Communicator gave us a transport address validation response.
 
static int check_add_queue_message (void *cls, const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
 New queue became available.
 
static void set_pending_message_uuid (struct PendingMessage *pm)
 If necessary, generates the UUID for a pm.
 
static struct PendingAcknowledgementprepare_pending_acknowledgement (struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
 Setup data structure waiting for acknowledgements.
 
static struct PendingMessagefragment_message (struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
 Fragment the given pm to the given mtu.
 
static struct PendingMessagereliability_box_message (struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
 Reliability-box the given pm.
 
static void reorder_root_pm (struct PendingMessage *pm, struct GNUNET_TIME_Absolute next_attempt)
 
static unsigned int check_next_attempt_tree (struct PendingMessage *pm, struct PendingMessage *root)
 
static void harmonize_flight_round (struct PendingMessage *pm)
 
static void update_pm_next_attempt (struct PendingMessage *pm, struct GNUNET_TIME_Absolute next_attempt)
 Change the value of the next_attempt field of pm to next_attempt and re-order pm in the transmission list as required by the new timestamp.
 
static void select_best_pending_from_link (struct PendingMessageScoreContext *sc, struct Queue *queue, struct VirtualLink *vl, struct DistanceVectorHop *dvh, size_t overhead)
 Select the best pending message from vl for transmission via queue.
 
static void extract_box_cb (void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
 Function to call to further operate on the now DV encapsulated message hdr, forwarding it via next_hop under respect of options.
 
static void handle_del_queue_message (void *cls, const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
 Queue to a peer went down.
 
static void handle_send_message_ack (void *cls, const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
 Message was transmitted.
 
static void handle_burst_finished (void *cls, const struct GNUNET_TRANSPORT_BurstFinished *bf)
 The burst finished.
 
static int notify_client_queues (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Iterator telling new MONITOR client about all existing queues to peers.
 
static void handle_monitor_start (void *cls, const struct GNUNET_TRANSPORT_MonitorStart *start)
 Initialize a monitor client.
 
static struct TransportClientlookup_communicator (const char *prefix)
 Find transport client providing communication service for the protocol prefix.
 
static int check_connection_quality (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Check whether any queue to the given neighbour is of a good "quality" and if so, increment the counter.
 
static void start_dv_learn (void *cls)
 Task run when we CONSIDER initiating a DV learn process.
 
static void sign_dv_init_cb (void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
 
static int check_validation_request_pending (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 A new queue has been created, check if any address validation requests have been waiting for it.
 
static void neighbour_dv_monotime_cb (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
 Function called with the monotonic time of a DV initiator by PEERSTORE.
 
static void iterate_address_and_compare_cb (void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
 
static enum GNUNET_GenericReturnValue contains_address (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 
static void check_for_global_natted_error_cb (void *cls)
 
static void check_for_global_natted_sync_cb (void *cls)
 
static void check_for_global_natted (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
 
static void handle_add_queue_message (void *cls, const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
 New queue became available.
 
static void handle_update_queue_message (void *cls, const struct GNUNET_TRANSPORT_UpdateQueueMessage *msg)
 Handle updates to queues.
 
static void handle_queue_create_ok (void *cls, const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
 Communicator tells us that our request to create a queue "worked", that is setting up the queue is now in process.
 
static void handle_queue_create_fail (void *cls, const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
 Communicator tells us that our request to create a queue failed.
 
static void handle_suggest_cancel (void *cls, const struct ExpressPreferenceMessage *msg)
 We have received a struct ExpressPreferenceMessage from an application client.
 
static void hello_for_client_cb (void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
 
static void handle_hello_for_client (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
 Function called by PEERSTORE for each matching record.
 
static void hello_for_client_error_cb (void *cls)
 
static void hello_for_client_sync_cb (void *cls)
 
static void handle_suggest (void *cls, const struct ExpressPreferenceMessage *msg)
 We have received a struct ExpressPreferenceMessage from an application client.
 
static int check_request_hello_validation (void *cls, const struct RequestHelloValidationMessage *m)
 Check GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION messages.
 
static void handle_request_hello_validation (void *cls, const struct RequestHelloValidationMessage *m)
 A client encountered an address of another peer.
 
static int free_neighbour_cb (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Free neighbour entry.
 
static int free_dv_routes_cb (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Free DV route entry.
 
static int free_validation_state_cb (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Free validation state.
 
static int free_pending_ack_cb (void *cls, const struct GNUNET_Uuid *key, void *value)
 Free pending acknowledgement.
 
static int free_ack_cummulator_cb (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Free acknowledgement cummulator.
 
static void shutdown_task (void *cls)
 
static void update_hello_from_pid_change_cb (void *cls, int success)
 
void print_address_list (void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
 
static void pils_pid_change_cb (void *cls, const struct GNUNET_HELLO_Parser *parser, const struct GNUNET_HashCode *hash)
 Callback called when pils service updates us with our new peer identity.
 
static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
 Initiate transport service.
 
 GNUNET_SERVICE_MAIN (GNUNET_OS_project_data_gnunet(), "transport", GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_fixed_size(suggest, GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST, struct ExpressPreferenceMessage, NULL), GNUNET_MQ_hd_fixed_size(suggest_cancel, GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST_CANCEL, struct ExpressPreferenceMessage, NULL), GNUNET_MQ_hd_var_size(request_hello_validation, GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION, struct RequestHelloValidationMessage, NULL), GNUNET_MQ_hd_fixed_size(client_start, GNUNET_MESSAGE_TYPE_TRANSPORT_START, struct StartMessage, NULL), GNUNET_MQ_hd_var_size(client_send, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, struct OutboundMessage, NULL), GNUNET_MQ_hd_fixed_size(client_recv_ok, GNUNET_MESSAGE_TYPE_TRANSPORT_RECV_OK, struct RecvOkMessage, NULL), GNUNET_MQ_hd_var_size(communicator_available, GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR, struct GNUNET_TRANSPORT_CommunicatorAvailableMessage, NULL), GNUNET_MQ_hd_var_size(communicator_backchannel, GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL, struct GNUNET_TRANSPORT_CommunicatorBackchannel, NULL), GNUNET_MQ_hd_var_size(add_address, GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS, struct GNUNET_TRANSPORT_AddAddressMessage, NULL), GNUNET_MQ_hd_fixed_size(del_address, GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS, struct GNUNET_TRANSPORT_DelAddressMessage, NULL), GNUNET_MQ_hd_var_size(incoming_msg, GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG, struct GNUNET_TRANSPORT_IncomingMessage, NULL), GNUNET_MQ_hd_fixed_size(queue_create_ok, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK, struct GNUNET_TRANSPORT_CreateQueueResponse, NULL), GNUNET_MQ_hd_fixed_size(queue_create_fail, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL, struct GNUNET_TRANSPORT_CreateQueueResponse, NULL), GNUNET_MQ_hd_var_size(add_queue_message, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP, struct GNUNET_TRANSPORT_AddQueueMessage, NULL), GNUNET_MQ_hd_fixed_size(update_queue_message, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_UPDATE, struct GNUNET_TRANSPORT_UpdateQueueMessage, NULL), GNUNET_MQ_hd_fixed_size(del_queue_message, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN, struct GNUNET_TRANSPORT_DelQueueMessage, NULL), GNUNET_MQ_hd_fixed_size(send_message_ack, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK, struct GNUNET_TRANSPORT_SendMessageToAck, NULL), GNUNET_MQ_hd_fixed_size(burst_finished, GNUNET_MESSAGE_TYPE_TRANSPORT_BURST_FINISHED, struct GNUNET_TRANSPORT_BurstFinished, NULL), GNUNET_MQ_hd_fixed_size(monitor_start, GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START, struct GNUNET_TRANSPORT_MonitorStart, NULL), GNUNET_MQ_handler_end())
 Define "main" method using service macro.
 

Variables

static struct RingBufferEntryring_buffer [RING_BUFFER_SIZE]
 Ring buffer for a CORE message we did not deliver to CORE, because of missing virtual link to sender.
 
static unsigned int ring_buffer_head
 Head of the ring buffer.
 
static unsigned int is_ring_buffer_full
 Is the ring buffer filled up to RING_BUFFER_SIZE.
 
static struct PendingMessagering_buffer_dv [RING_BUFFER_SIZE]
 Ring buffer for a forwarded DVBox message we did not deliver to the next hop, because of missing virtual link that hop.
 
static unsigned int ring_buffer_dv_head
 Head of the ring buffer.
 
static unsigned int is_ring_buffer_dv_full
 Is the ring buffer filled up to RING_BUFFER_SIZE.
 
static struct TransportClientclients_head
 Head of linked list of all clients to this service.
 
static struct TransportClientclients_tail
 Tail of linked list of all clients to this service.
 
static struct GNUNET_STATISTICS_HandleGST_stats
 Statistics handle.
 
static const struct GNUNET_CONFIGURATION_HandleGST_cfg
 Configuration handle.
 
static struct GNUNET_PeerIdentityGST_my_identity
 Our public key.
 
struct GNUNET_HELLO_BuilderGST_my_hello
 Our HELLO.
 
static struct GNUNET_CONTAINER_MultiPeerMapneighbours
 Map from PIDs to struct Neighbour entries.
 
static struct GNUNET_CONTAINER_MultiPeerMapbacktalkers
 Map from PIDs to struct Backtalker entries.
 
static struct GNUNET_CONTAINER_MultiPeerMapack_cummulators
 Map from PIDs to struct AcknowledgementCummulators.
 
static struct GNUNET_CONTAINER_MultiUuidmappending_acks
 Map of pending acknowledgements, mapping struct AcknowledgementUUID to a struct PendingAcknowledgement.
 
static struct GNUNET_CONTAINER_MultiPeerMapdv_routes
 Map from PIDs to struct DistanceVector entries describing known paths to the peer.
 
static struct GNUNET_CONTAINER_MultiPeerMapvalidation_map
 Map from PIDs to struct ValidationState entries describing addresses we are aware of and their validity state.
 
static struct GNUNET_CONTAINER_MultiHashMaprevalidation_map
 Map from addresses to struct ValidationState entries describing addresses we are aware of and their validity state.
 
static struct GNUNET_CONTAINER_MultiPeerMaplinks
 Map from PIDs to struct VirtualLink entries describing links CORE knows to exist.
 
static struct GNUNET_CONTAINER_MultiShortmapdvlearn_map
 Map from challenges to struct LearnLaunchEntry values.
 
static struct LearnLaunchEntrylle_head = NULL
 Head of a DLL sorted by launch time.
 
static struct LearnLaunchEntrylle_tail = NULL
 Tail of a DLL sorted by launch time.
 
static struct GNUNET_CONTAINER_Heapvalidation_heap
 MIN Heap sorted by "next_challenge" to struct ValidationState entries sorting addresses we are aware of by when we should next try to (re)validate (or expire) them.
 
struct GNUNET_NAT_Handlenh
 Handle for connect to the NAT service.
 
static struct GNUNET_PEERSTORE_Handlepeerstore
 Database for peer's HELLOs.
 
static struct GNUNET_PILS_Handlepils
 Service that manages our peer id.
 
static struct PilsRequestpils_requests_head
 PILS Operation DLL.
 
static struct PilsRequestpils_requests_tail
 PILS Operation DLL.
 
static struct GNUNET_SCHEDULER_Taskdvlearn_task
 Task run to initiate DV learning.
 
static struct GNUNET_SCHEDULER_Taskvalidation_task
 Task to run address validation.
 
static struct GNUNET_SCHEDULER_Taskpils_feed_task
 Task to feed addresses to PILS.
 
static struct IncomingRequestir_head
 List of incoming connections where we are trying to get a connection back established.
 
static struct IncomingRequestir_tail
 Tail of DLL starting at ir_head.
 
static unsigned int ir_total
 Length of the DLL starting at ir_head.
 
static unsigned long long logging_uuid_gen
 Generator of logging_uuid in struct PendingMessage.
 
static enum GNUNET_GenericReturnValue burst_running
 Is there a burst running?
 
static struct GNUNET_TIME_Absolute hello_mono_time
 Monotonic time we use for HELLOs generated at this time.
 
static int in_shutdown
 Indication if we have received a shutdown signal and are in the process of cleaning up.
 
static struct GNUNET_SCHEDULER_Taskburst_task
 The task to start the burst.
 
struct GNUNET_SCHEDULER_Taskburst_timeout_task
 
enum GNUNET_GenericReturnValue use_burst
 

Detailed Description

main for gnunet-service-transport

Author
Christian Grothoff

TODO: Implement next:

  • review retransmission logic, right now there is no smartness there! => congestion control, etc [PERFORMANCE-BASICS]

Optimizations-Statistics:

  • Track ACK losses based on ACK-counter [ROUTING]
  • Need to track total bandwidth per VirtualLink and adjust how frequently we send FC messages based on bandwidth-delay-product (and relation to the window size!). See OPTIMIZE-FC-BDP.
  • Consider more statistics in check_connection_quality() [FIXME-CONQ-STATISTICS]
  • Adapt available_fc_window_size, using larger values for high-bandwidth and high-latency links if we have the RAM [GOODPUT / utilization / stalls]
  • Set last_window_consum_limit promise properly based on latency and bandwidth of the respective connection [GOODPUT / utilization / stalls]

Optimizations-DV:

  • When forwarding DV learn messages, if a peer is reached that has a bidirectional link to the origin beyond 1st hop, do NOT forward it to peers other than the origin, as there is clearly a better path directly from the origin to whatever else we could reach.
  • When we passively learned DV (with unconfirmed freshness), we right now add the path to our list but with a zero path_valid_until time and only use it for unconfirmed routes. However, we could consider triggering an explicit validation mechanism ourselves, specifically routing a challenge-response message over the path [ROUTING] = if available, try to confirm unconfirmed DV paths when trying to establish virtual link for a struct IncomingRequest. (i.e. if DVH is unconfirmed, incoming requests cause us to try to validate a passively learned path (requires new message type!))

Optimizations-Fragmentation:

  • Fragments send over a reliable channel could do without the AcknowledgementUUIDP altogether, as they won't be acked! [BANDWIDTH] (-> have 2nd type of acknowledgment message; low priority, as we do not have an MTU-limited reliable communicator) [FIXME-FRAG-REL-UUID]
  • if messages are below MTU, consider adding ACKs and other stuff to the same transmission to avoid tiny messages (requires planning at receiver, and additional MST-style demultiplex at receiver!) [PACKET COUNT]

Optimizations-internals:

  • queue_send_msg by API design has to make a copy of the payload, and route_message on top of that requires a malloc/free. Change design to approximate "zero" copy better... [CPU]
  • could avoid copying body of message into each fragment and keep fragments as just pointers into the original message and only fully build fragments just before transmission (optimization, should reduce CPU and memory use) [CPU, MEMORY]

Definition in file gnunet-service-transport.c.

Macro Definition Documentation

◆ RING_BUFFER_SIZE

#define RING_BUFFER_SIZE   16

Size of ring buffer to cache CORE and forwarded DVBox messages.

Definition at line 89 of file gnunet-service-transport.c.

◆ MAX_FC_RETRANSMIT_COUNT

#define MAX_FC_RETRANSMIT_COUNT   1000

Maximum number of FC retransmissions for a running retransmission task.

Definition at line 94 of file gnunet-service-transport.c.

◆ MAX_CUMMULATIVE_ACKS

#define MAX_CUMMULATIVE_ACKS   64

Maximum number of messages we acknowledge together in one cumulative ACK.

Larger values may save a bit of bandwidth.

Definition at line 100 of file gnunet-service-transport.c.

◆ FC_NO_CHANGE_REPLY_PROBABILITY

#define FC_NO_CHANGE_REPLY_PROBABILITY   8

What is the 1:n chance that we send a Flow control response when receiving a flow control message that did not change anything for us? Basically, this is used in the case where both peers are stuck on flow control (no window changes), but one might continue sending flow control messages to the other peer as the first FC message when things stalled got lost, and then subsequently the other peer does usually not respond as nothing changed.

So to ensure that eventually the FC messages stop, we do send with 1/8th probability an FC message even if nothing changed. That prevents one peer being stuck in sending (useless) FC messages "forever".

Definition at line 114 of file gnunet-service-transport.c.

◆ IN_PACKET_SIZE_WITHOUT_MTU

#define IN_PACKET_SIZE_WITHOUT_MTU   128

What is the size we assume for a read operation in the absence of an MTU for the purpose of flow control?

Definition at line 120 of file gnunet-service-transport.c.

◆ GOODPUT_AGING_SLOTS

#define GOODPUT_AGING_SLOTS   4

Number of slots we keep of historic data for computation of goodput / message loss ratio.

Definition at line 126 of file gnunet-service-transport.c.

◆ DEFAULT_WINDOW_SIZE

#define DEFAULT_WINDOW_SIZE   (128 * 1024)

How big is the flow control window size by default; limits per-neighbour RAM utilization.

Definition at line 132 of file gnunet-service-transport.c.

◆ MAX_INCOMING_REQUEST

#define MAX_INCOMING_REQUEST   16

For how many incoming connections do we try to create a virtual link for (at the same time!).

This does NOT limit the number of incoming connections, just the number for which we are actively trying to find working addresses in the absence (!) of our own applications wanting the link to go up.

Definition at line 142 of file gnunet-service-transport.c.

◆ MAX_DV_DISCOVERY_SELECTION

#define MAX_DV_DISCOVERY_SELECTION   16

Maximum number of peers we select for forwarding DVInit messages at the same time (excluding initiator).

Definition at line 148 of file gnunet-service-transport.c.

◆ RECV_WINDOW_SIZE

#define RECV_WINDOW_SIZE   4

Window size.

How many messages to the same target do we pass to CORE without a RECV_OK in between? Small values limit throughput, large values will increase latency.

FIXME-OPTIMIZE: find out what good values are experimentally, maybe set adaptively (i.e. to observed available bandwidth).

Definition at line 158 of file gnunet-service-transport.c.

◆ MIN_DV_PATH_LENGTH_FOR_INITIATOR

#define MIN_DV_PATH_LENGTH_FOR_INITIATOR   3

Minimum number of hops we should forward DV learn messages even if they are NOT useful for us in hope of looping back to the initiator?

FIXME: allow initiator some control here instead?

Definition at line 167 of file gnunet-service-transport.c.

◆ MAX_DV_HOPS_ALLOWED

#define MAX_DV_HOPS_ALLOWED   16

Maximum DV distance allowed ever.

Definition at line 172 of file gnunet-service-transport.c.

◆ MAX_DV_LEARN_PENDING

#define MAX_DV_LEARN_PENDING   64

Maximum number of DV learning activities we may have pending at the same time.

Definition at line 178 of file gnunet-service-transport.c.

◆ MAX_DV_PATHS_TO_TARGET

#define MAX_DV_PATHS_TO_TARGET   3

Maximum number of DV paths we keep simultaneously to the same target.

Definition at line 183 of file gnunet-service-transport.c.

◆ PILS_FEED_ADDRESSES_DELAY

#define PILS_FEED_ADDRESSES_DELAY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3)

Delay between added/removed addresses and PILS feed call.

Introduced to handle cases with high address churn across communicators (startup, location change etc)

Definition at line 191 of file gnunet-service-transport.c.

350{
355 uint64_t uuid GNUNET_PACKED;
356};
357
358
363{
367 struct GNUNET_Uuid value;
368};
369
374{
379
380 /* Followed by *another* message header which is the message to
381 the communicator */
382
383 /* Followed by a 0-terminated name of the communicator */
384};
385
386
391{
396
412
417
423};
424
425
431{
436
442
454
455 /* Followed by a `struct GNUNET_MessageHeader` with a message
456 for the target peer */
457};
458
459
465{
470
478
485};
486
487
492{
500
505};
506
507
516{
521
526 uint32_t ack_counter GNUNET_PACKED;
527
528 /* followed by any number of `struct TransportCummulativeAckPayloadP`
529 messages providing ACKs */
530};
531
532
537{
542
546 uint16_t frag_off GNUNET_PACKED;
547
551 uint16_t msg_size GNUNET_PACKED;
552
561
566 struct MessageUUIDP msg_uuid;
567};
568
569
587struct DvInitPS
588{
593
607
612};
613
614
631struct DvHopPS
632{
637
642
647
652};
653
654
659struct DVPathEntryP
660{
665
671};
672
673
688{
693
698 uint16_t num_hops GNUNET_PACKED;
699
709
716
730
736
741
746
747 /* Followed by @e num_hops `struct DVPathEntryP` values,
748 excluding the initiator of the DV trace; the last entry is the
749 current sender; the current peer must not be included. */
750};
751
752
776{
781
785 unsigned int without_fc;
786
793 uint16_t total_hops GNUNET_PACKED;
794
800 uint16_t num_hops GNUNET_PACKED;
801
807
814
820 struct GNUNET_HashCode hmac;
821
827 uint16_t orig_size GNUNET_PACKED;
828
829 /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values;
830 excluding the @e origin and the current peer, the last must be
831 the ultimate target; if @e num_hops is zero, the receiver of this
832 message is the ultimate target. */
833
834 /* Followed by encrypted, variable-size payload, which
835 must begin with a `struct TransportDVBoxPayloadP` */
836
837 /* Followed by the actual message, which itself must not be a
838 a DV_LEARN or DV_BOX message! */
839};
840
841
847{
852
856 uint32_t reserved GNUNET_PACKED;
857
862
868};
869
870
876{
881
887
892};
893
894
900{
905
909 uint32_t reserved GNUNET_PACKED;
910
916
921
926 struct GNUNET_TIME_AbsoluteNBO origin_time;
927
932 struct GNUNET_TIME_RelativeNBO validity_duration;
933};
934
936{
940 unsigned int address_length;
941
942 /* Followed by @e address_length bytes of the address. */
943};
944
954{
959
967 uint32_t seq GNUNET_PACKED;
968
974
981
991
1001
1006
1010 unsigned int sync_ready;
1011
1015 unsigned int number_of_addresses;
1016
1020 size_t size_of_addresses;
1021
1022 /* Followed by @e number_of_addresses struct TransportGlobalNattedAddress. */
1023};
1024
1026
1027
1031enum ClientType
1032{
1036 CT_NONE = 0,
1037
1041 CT_CORE = 1,
1042
1046 CT_MONITOR = 2,
1047
1051 CT_COMMUNICATOR = 3,
1052
1056 CT_APPLICATION = 4
1057};
1058
1059
1065{
1069 RMO_NONE = 0,
1070
1074 RMO_DV_ALLOWED = 1,
1075
1080
1085
1091 RMO_REDUNDANT = 4
1092};
1093
1094
1098struct LearnLaunchEntry
1099{
1103 struct LearnLaunchEntry *prev;
1104
1108 struct LearnLaunchEntry *next;
1109
1114
1120};
1121
1122
1128{
1132 uint64_t bytes_sent;
1133
1138 uint64_t bytes_received;
1139};
1140
1141
1145struct PerformanceData
1146{
1151
1157
1162 unsigned int last_age;
1163};
1164
1165
1169struct TransportClient;
1170
1174struct Neighbour;
1175
1180struct DistanceVector;
1181
1186struct Queue;
1187
1191struct PendingMessage;
1192
1196struct DistanceVectorHop;
1197
1206struct VirtualLink;
1207
1208
1214{
1220
1226
1230 struct TransportClient *tc;
1231
1236
1240 const struct GNUNET_MessageHeader *mh;
1241
1246 uint16_t total_hops;
1247
1251 unsigned int continue_send;
1252};
1253
1254
1258struct RingBufferEntry
1259{
1264
1268 struct GNUNET_MessageHeader *mh;
1269};
1270
1271
1275struct CoreSentContext
1276{
1280 struct CoreSentContext *next;
1281
1285 struct CoreSentContext *prev;
1286
1290 struct VirtualLink *vl;
1291
1295 uint16_t size;
1296
1303 uint16_t isize;
1304};
1305
1306
1310struct ReassemblyContext
1311{
1316 struct MessageUUIDP msg_uuid;
1317
1321 struct VirtualLink *virtual_link;
1322
1327
1335 uint8_t *bitfield;
1336
1341
1347
1351 uint16_t msg_size;
1352
1357 uint16_t msg_missing;
1358
1359 /* Followed by @e msg_size bytes of the (partially) defragmented original
1360 * message */
1361
1362 /* Followed by @e bitfield data */
1363};
1364
1365
1374struct VirtualLink
1375{
1380
1387
1394
1399
1405
1411
1416
1421
1425 struct CoreSentContext *csc_tail;
1426
1430 struct CoreSentContext *csc_head;
1431
1439
1445
1450
1454 char *burst_addr;
1455
1459 unsigned int fc_retransmit_count;
1460
1465 unsigned int confirmed;
1466
1470 struct Neighbour *n;
1471
1475 struct DistanceVector *dv;
1476
1483
1490
1499
1505
1511
1516
1521 uint64_t message_uuid_ctr;
1522
1530 uint64_t available_fc_window_size;
1531
1539
1545 uint64_t incoming_fc_window_size;
1546
1555
1568
1573 uint64_t outbound_fc_window_size;
1574
1581
1592
1597 uint32_t fc_seq_gen;
1598
1604 uint32_t last_fc_seq;
1605
1617 int core_recv_window;
1618
1623};
1624
1625
1630{
1636
1642
1649
1656
1663
1670
1677
1684
1689
1694 struct PendingMessage *pm;
1695
1700 struct DistanceVectorHop *dvh;
1701
1706 struct Queue *queue;
1707
1712
1716 uint16_t message_size;
1717
1721 unsigned int num_send;
1722};
1723
1724
1728struct DistanceVectorHop
1729{
1733 struct DistanceVectorHop *next_dv;
1734
1738 struct DistanceVectorHop *prev_dv;
1739
1744
1749
1754
1759
1763 struct Neighbour *next_hop;
1764
1768 struct DistanceVector *dv;
1769
1775 const struct GNUNET_PeerIdentity *path;
1776
1782
1791
1795 struct PerformanceData pd;
1796
1802 unsigned int distance;
1803};
1804
1805
1810struct DistanceVector
1811{
1816
1820 struct DistanceVectorHop *dv_head;
1821
1825 struct DistanceVectorHop *dv_tail;
1826
1831
1836 struct VirtualLink *vl;
1837
1843
1848
1853
1858
1862 struct GNUNET_ShortHashCode *km;
1863};
1864
1865
1875struct QueueEntry
1876{
1880 struct QueueEntry *next;
1881
1885 struct QueueEntry *prev;
1886
1890 struct Queue *queue;
1891
1895 struct PendingMessage *pm;
1896
1900 uint64_t mid;
1901
1906};
1907
1908
1913struct Queue
1914{
1918 struct Queue *next_neighbour;
1919
1923 struct Queue *prev_neighbour;
1924
1928 struct Queue *prev_client;
1929
1933 struct Queue *next_client;
1934
1939
1944
1948 struct QueueEntry *queue_head;
1949
1953 struct QueueEntry *queue_tail;
1954
1958 struct Neighbour *neighbour;
1959
1963 struct TransportClient *tc;
1964
1968 const char *address;
1969
1973 unsigned int unlimited_length;
1974
1980
1989
1993 struct PerformanceData pd;
1994
2000
2005 uint64_t mid_gen;
2006
2010 uint32_t qid;
2011
2015 uint32_t mtu;
2016
2020 uint32_t num_msg_pending;
2021
2025 uint32_t num_bytes_pending;
2026
2030 unsigned int queue_length;
2031
2035 uint64_t q_capacity;
2036
2040 uint32_t priority;
2041
2046
2051
2056 int idle;
2057
2062};
2063
2064
2068struct Neighbour
2069{
2073 struct GNUNET_PeerIdentity pid;
2074
2079 struct DistanceVectorHop *dv_head;
2080
2085 struct DistanceVectorHop *dv_tail;
2086
2090 struct Queue *queue_head;
2091
2095 struct Queue *queue_tail;
2096
2102
2108
2113 struct VirtualLink *vl;
2114
2120
2126
2131
2135 unsigned int number_of_addresses;
2136
2141
2146};
2147
2148
2153struct IncomingRequest
2154{
2158 struct IncomingRequest *next;
2159
2163 struct IncomingRequest *prev;
2164
2169
2173 struct GNUNET_PeerIdentity pid;
2174};
2175
2176
2180struct PeerRequest
2181{
2185 struct GNUNET_PeerIdentity pid;
2186
2190 struct TransportClient *tc;
2191
2196
2203
2208};
2209
2210
2215{
2219 PMT_CORE = 0,
2220
2224 PMT_FRAGMENT_BOX = 1,
2225
2230
2234 PMT_DV_BOX = 3
2235};
2236
2237
2264struct PendingMessage
2265{
2269 struct PendingMessage *next_vl;
2270
2274 struct PendingMessage *prev_vl;
2275
2280
2285
2290 struct PendingMessage *next_frag;
2291
2296 struct PendingMessage *prev_frag;
2297
2302
2307
2312 struct PendingMessage *bpm;
2313
2318 struct VirtualLink *vl;
2319
2324
2333 struct QueueEntry *qe;
2334
2338 struct TransportClient *client;
2339
2343 struct PendingMessage *head_frag;
2344
2348 struct PendingMessage *tail_frag;
2349
2354
2359
2364
2369 struct MessageUUIDP msg_uuid;
2370
2375 uint64_t logging_uuid;
2376
2381
2387
2392
2396 uint16_t bytes_msg;
2397
2401 uint16_t frag_off;
2402
2406 uint32_t frags_in_flight;
2407
2411 uint32_t frags_in_flight_round;
2412
2416 uint16_t frag_count;
2417
2421 int16_t msg_uuid_set;
2422
2423 /* Followed by @e bytes_msg to transmit */
2424};
2425
2426
2431{
2437
2442};
2443
2444
2450{
2455
2460
2467
2472
2478 uint32_t ack_counter;
2479
2483 unsigned int num_acks;
2484};
2485
2486
2490struct AddressListEntry
2491{
2495 struct AddressListEntry *next;
2496
2500 struct AddressListEntry *prev;
2501
2505 struct TransportClient *tc;
2506
2511
2515 const char *address;
2516
2520 void *signed_address;
2521
2525 size_t signed_address_len;
2526
2531
2535 struct GNUNET_SCHEDULER_Task *st;
2536
2542
2546 uint32_t aid;
2547
2552};
2553
2554
2558struct TransportClient
2559{
2563 struct TransportClient *next;
2564
2568 struct TransportClient *prev;
2569
2574
2578 struct GNUNET_MQ_Handle *mq;
2579
2583 enum ClientType type;
2584
2585 union
2586 {
2590 struct
2591 {
2597
2602 } core;
2603
2607 struct
2608 {
2615
2619 int one_shot;
2620 } monitor;
2621
2622
2626 struct
2627 {
2632 char *address_prefix;
2633
2637 struct Queue *queue_head;
2638
2642 struct Queue *queue_tail;
2643
2649
2655
2661 unsigned int total_queue_length;
2662
2667
2672
2677
2678 } communicator;
2679
2683 struct
2684 {
2690 } application;
2691 } details;
2692};
2693
2694
2699struct ValidationState
2700{
2705 struct GNUNET_PeerIdentity pid;
2706
2714
2720
2727 struct GNUNET_TIME_Absolute first_challenge_use;
2728
2735 struct GNUNET_TIME_Absolute last_challenge_use;
2736
2744 struct GNUNET_TIME_Absolute next_challenge;
2745
2754 struct GNUNET_TIME_Relative challenge_backoff;
2755
2760 struct GNUNET_TIME_Relative validation_rtt;
2761
2769 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
2770
2774 struct GNUNET_HashCode hc;
2775
2779 struct GNUNET_SCHEDULER_Task *revalidation_task;
2780
2784 char *address;
2785
2791 struct GNUNET_CONTAINER_HeapNode *hn;
2792
2798
2804 uint32_t last_window_consum_limit;
2805
2810 int awaiting_queue;
2811};
2812
2813
2820struct Backtalker
2821{
2825 struct GNUNET_PeerIdentity pid;
2826
2831
2836
2841
2847
2852
2858
2864
2869 size_t body_size;
2870};
2871
2876
2880static unsigned int ring_buffer_head;
2881
2885static unsigned int is_ring_buffer_full;
2886
2891
2895static unsigned int ring_buffer_dv_head;
2896
2900static unsigned int is_ring_buffer_dv_full;
2901
2905static struct TransportClient *clients_head;
2906
2910static struct TransportClient *clients_tail;
2911
2915static struct GNUNET_STATISTICS_Handle *GST_stats;
2916
2920static const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
2921
2926
2931
2937
2943
2949
2955
2961
2967
2973
2979
2984
2988static struct LearnLaunchEntry *lle_head = NULL;
2989
2993static struct LearnLaunchEntry *lle_tail = NULL;
2994
3001
3005struct GNUNET_NAT_Handle *nh;
3006
3010static struct GNUNET_PEERSTORE_Handle *peerstore;
3011
3015static struct GNUNET_PILS_Handle *pils;
3016
3020struct PilsRequest
3021{
3025 struct PilsRequest *prev;
3026
3030 struct PilsRequest *next;
3031
3035 struct GNUNET_PILS_Operation *op;
3036};
3037
3041static struct PilsRequest *pils_requests_head;
3042
3046static struct PilsRequest *pils_requests_tail;
3047
3051static struct GNUNET_SCHEDULER_Task *dvlearn_task;
3052
3057
3062
3068static struct IncomingRequest *ir_head;
3069
3073static struct IncomingRequest *ir_tail;
3074
3078static unsigned int ir_total;
3079
3083static unsigned long long logging_uuid_gen;
3084
3089
3099
3104static int in_shutdown;
3105
3109static struct GNUNET_SCHEDULER_Task *burst_task;
3110
3112
3114
3125static unsigned int
3126get_age ()
3127{
3128 struct GNUNET_TIME_Absolute now;
3129
3130 now = GNUNET_TIME_absolute_get ();
3131 return now.abs_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us / 15;
3132}
3133
3134
3140static void
3142{
3144 GNUNET_assert (ir_total > 0);
3145 ir_total--;
3146 if (NULL != ir->nc)
3148 ir->nc = NULL;
3149 GNUNET_free (ir);
3150}
3151
3152
3158static void
3160{
3161 struct Queue *q = pa->queue;
3162 struct PendingMessage *pm = pa->pm;
3163 struct DistanceVectorHop *dvh = pa->dvh;
3164
3166 "free_pending_acknowledgement\n");
3167 if (NULL != q)
3168 {
3169 GNUNET_CONTAINER_MDLL_remove (queue, q->pa_head, q->pa_tail, pa);
3170 pa->queue = NULL;
3171 }
3172 if (NULL != pm)
3173 {
3175 "remove pa from message\n");
3177 "remove pa from message %" PRIu64 "\n",
3178 pm->logging_uuid);
3180 "remove pa from message %u\n",
3181 pm->pmt);
3183 "remove pa from message %s\n",
3185 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3186 pa->pm = NULL;
3187 }
3188 if (NULL != dvh)
3189 {
3190 GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
3191 pa->queue = NULL;
3192 }
3195 &pa->ack_uuid.value,
3196 pa));
3197 GNUNET_free (pa);
3198}
3199
3200
3209static void
3211{
3212 struct PendingMessage *frag;
3213
3214 while (NULL != (frag = root->head_frag))
3215 {
3216 struct PendingAcknowledgement *pa;
3217
3218 free_fragment_tree (frag);
3219 while (NULL != (pa = frag->pa_head))
3220 {
3221 GNUNET_CONTAINER_MDLL_remove (pm, frag->pa_head, frag->pa_tail, pa);
3222 pa->pm = NULL;
3223 }
3224 GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag);
3225 if (NULL != frag->qe)
3226 {
3227 GNUNET_assert (frag == frag->qe->pm);
3228 frag->qe->pm = NULL;
3229 }
3231 "Free frag %p\n",
3232 frag);
3233 GNUNET_free (frag);
3234 }
3235}
3236
3237
3245static void
3247{
3248 struct TransportClient *tc = pm->client;
3249 struct VirtualLink *vl = pm->vl;
3250 struct PendingAcknowledgement *pa;
3251
3253 "Freeing pm %p\n",
3254 pm);
3255 if (NULL != tc)
3256 {
3258 tc->details.core.pending_msg_head,
3259 tc->details.core.pending_msg_tail,
3260 pm);
3261 }
3262 if ((NULL != vl) && (NULL == pm->frag_parent))
3263 {
3265 "Removing pm %" PRIu64 "\n",
3266 pm->logging_uuid);
3268 vl->pending_msg_head,
3269 vl->pending_msg_tail,
3270 pm);
3271 }
3272 else if (NULL != pm->frag_parent && PMT_DV_BOX != pm->pmt)
3273 {
3274 struct PendingMessage *root = pm->frag_parent;
3275
3276 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
3277 root = root->frag_parent;
3278
3279 root->frag_count--;
3280 }
3281 while (NULL != (pa = pm->pa_head))
3282 {
3283 if (NULL == pa)
3285 "free pending pa null\n");
3286 if (NULL == pm->pa_tail)
3288 "free pending pa_tail null\n");
3289 if (NULL == pa->prev_pa)
3291 "free pending pa prev null\n");
3292 if (NULL == pa->next_pa)
3294 "free pending pa next null\n");
3295 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3296 pa->pm = NULL;
3297 }
3298
3300 if (NULL != pm->qe)
3301 {
3302 GNUNET_assert (pm == pm->qe->pm);
3303 pm->qe->pm = NULL;
3304 }
3305 if (NULL != pm->bpm)
3306 {
3307 free_fragment_tree (pm->bpm);
3308 if (NULL != pm->bpm->qe)
3309 {
3310 struct QueueEntry *qe = pm->bpm->qe;
3311
3312 qe->pm = NULL;
3313 }
3314 GNUNET_free (pm->bpm);
3315 }
3316
3317 GNUNET_free (pm);
3319 "Freeing pm done\n");
3320}
3321
3322
3328static void
3330{
3331 struct VirtualLink *vl = rc->virtual_link;
3332
3336 rc->msg_uuid.uuid,
3337 rc));
3338 GNUNET_free (rc);
3339}
3340
3341
3347static void
3348reassembly_cleanup_task (void *cls)
3349{
3350 struct VirtualLink *vl = cls;
3351 struct ReassemblyContext *rc;
3352
3353 vl->reassembly_timeout_task = NULL;
3354 while (NULL != (rc = GNUNET_CONTAINER_heap_peek (vl->reassembly_heap)))
3355 {
3357 .rel_value_us)
3358 {
3360 continue;
3361 }
3366 vl);
3367 return;
3368 }
3369}
3370
3371
3380static int
3381free_reassembly_cb (void *cls, uint32_t key, void *value)
3382{
3383 struct ReassemblyContext *rc = value;
3384
3385 (void) cls;
3386 (void) key;
3388 return GNUNET_OK;
3389}
3390
3391
3397static void
3398free_virtual_link (struct VirtualLink *vl)
3399{
3400 struct PendingMessage *pm;
3401 struct CoreSentContext *csc;
3402
3404 "free virtual link %p\n",
3405 vl);
3406
3407 if (NULL != vl->reassembly_map)
3408 {
3411 NULL);
3413 vl->reassembly_map = NULL;
3415 vl->reassembly_heap = NULL;
3416 }
3417 if (NULL != vl->reassembly_timeout_task)
3418 {
3421 }
3422 while (NULL != (pm = vl->pending_msg_head))
3426 if (NULL != vl->visibility_task)
3427 {
3429 vl->visibility_task = NULL;
3430 }
3431 if (NULL != vl->fc_retransmit_task)
3432 {
3434 vl->fc_retransmit_task = NULL;
3435 }
3436 while (NULL != (csc = vl->csc_head))
3437 {
3439 GNUNET_assert (vl == csc->vl);
3440 csc->vl = NULL;
3441 }
3442 GNUNET_break (NULL == vl->n);
3443 GNUNET_break (NULL == vl->dv);
3444 GNUNET_free (vl);
3445}
3446
3447
3453static void
3455{
3456 if (NULL != vs->revalidation_task)
3457 {
3458 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
3459 vs->revalidation_task = NULL;
3460 }
3461 /*memcpy (&hkey,
3462 &hc,
3463 sizeof (hkey));*/
3465 "Remove key %s for address %s map size %u contains %u during freeing state\n",
3466 GNUNET_h2s (&vs->hc),
3467 vs->address,
3470 &vs->hc));
3473 GNUNET_YES ==
3476 vs->hn = NULL;
3477 if (NULL != vs->sc)
3478 {
3480 "store cancel\n");
3482 vs->sc = NULL;
3483 }
3484 GNUNET_free (vs->address);
3485 GNUNET_free (vs);
3486}
3487
3488
3495static struct Neighbour *
3497{
3499}
3500
3501
3508static struct VirtualLink *
3510{
3512}
3513
3514
3518struct MonitorEvent
3519{
3526
3531
3536
3540 uint32_t num_msg_pending;
3541
3545 uint32_t num_bytes_pending;
3546};
3547
3548
3557static void
3559{
3560 struct Neighbour *n = dvh->next_hop;
3561 struct DistanceVector *dv = dvh->dv;
3562 struct PendingAcknowledgement *pa;
3563
3564 while (NULL != (pa = dvh->pa_head))
3565 {
3567 pa->dvh = NULL;
3568 }
3569 GNUNET_CONTAINER_MDLL_remove (neighbour, n->dv_head, n->dv_tail, dvh);
3571 GNUNET_free (dvh);
3572}
3573
3574
3581static void
3582check_link_down (void *cls);
3583
3584
3590static void
3592{
3594 "Informing CORE clients about disconnect from %s\n",
3595 GNUNET_i2s (pid));
3596 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3597 {
3598 struct GNUNET_MQ_Envelope *env;
3599 struct DisconnectInfoMessage *dim;
3600
3601 if (CT_CORE != tc->type)
3602 continue;
3604 dim->peer = *pid;
3605 GNUNET_MQ_send (tc->mq, env);
3606 }
3607}
3608
3609
3616static void
3617free_dv_route (struct DistanceVector *dv)
3618{
3619 struct DistanceVectorHop *dvh;
3620 struct VirtualLink *vl;
3621
3622 while (NULL != (dvh = dv->dv_head))
3624
3626 GNUNET_YES ==
3628 if (NULL != (vl = dv->vl))
3629 {
3630 GNUNET_assert (dv == vl->dv);
3631 vl->dv = NULL;
3632 if (NULL == vl->n)
3633 {
3635 free_virtual_link (vl);
3636 }
3637 else
3638 {
3641 }
3642 dv->vl = NULL;
3643 }
3644
3645 if (NULL != dv->timeout_task)
3646 {
3648 dv->timeout_task = NULL;
3649 }
3650 GNUNET_free (dv->km);
3651 GNUNET_free (dv);
3652}
3653
3654
3668static void
3670 const struct GNUNET_PeerIdentity *peer,
3671 const char *address,
3673 const struct MonitorEvent *me)
3674{
3675 struct GNUNET_MQ_Envelope *env;
3677 size_t addr_len = strlen (address) + 1;
3678
3680 addr_len,
3682 md->nt = htonl ((uint32_t) nt);
3683 md->peer = *peer;
3684 md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
3685 md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
3686 md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
3687 md->rtt = GNUNET_TIME_relative_hton (me->rtt);
3688 md->cs = htonl ((uint32_t) me->cs);
3689 md->num_msg_pending = htonl (me->num_msg_pending);
3690 md->num_bytes_pending = htonl (me->num_bytes_pending);
3691 memcpy (&md[1], address, addr_len);
3692 GNUNET_MQ_send (tc->mq, env);
3693}
3694
3695
3705static void
3707 const char *address,
3709 const struct MonitorEvent *me)
3710{
3711 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3712 {
3713 if (CT_MONITOR != tc->type)
3714 continue;
3715 if (tc->details.monitor.one_shot)
3716 continue;
3717 if ((GNUNET_NO == GNUNET_is_zero (&tc->details.monitor.peer)) &&
3718 (0 != GNUNET_memcmp (&tc->details.monitor.peer, peer)))
3719 continue;
3721 }
3722}
3723
3724
3734static void *
3735client_connect_cb (void *cls,
3736 struct GNUNET_SERVICE_Client *client,
3737 struct GNUNET_MQ_Handle *mq)
3738{
3739 struct TransportClient *tc;
3740
3741 (void) cls;
3742 tc = GNUNET_new (struct TransportClient);
3743 tc->client = client;
3744 tc->mq = mq;
3747 "Client %p of type %u connected\n",
3748 tc,
3749 tc->type);
3750 return tc;
3751}
3752
3753
3754static enum GNUNET_GenericReturnValue
3755remove_global_addresses (void *cls,
3756 const struct GNUNET_PeerIdentity *pid,
3757 void *value)
3758{
3759 struct TransportGlobalNattedAddress *tgna = value;
3760 (void) cls;
3761
3762 GNUNET_free (tgna);
3763
3764 return GNUNET_OK;
3765}
3766
3767
3774static void
3775free_neighbour (struct Neighbour *neighbour,
3776 enum GNUNET_GenericReturnValue drop_link)
3777{
3778 struct DistanceVectorHop *dvh;
3779 struct VirtualLink *vl;
3780
3781 GNUNET_assert (NULL == neighbour->queue_head);
3784 &neighbour->pid,
3785 neighbour));
3787 "Freeing neighbour\n");
3790 NULL);
3792 while (NULL != (dvh = neighbour->dv_head))
3793 {
3794 struct DistanceVector *dv = dvh->dv;
3795
3797 if (NULL == dv->dv_head)
3798 free_dv_route (dv);
3799 }
3800 if (NULL != neighbour->get)
3801 {
3803 neighbour->get = NULL;
3804 }
3805 if (NULL != neighbour->sc)
3806 {
3808 "store cancel\n");
3809 GNUNET_PEERSTORE_store_cancel (neighbour->sc);
3810 neighbour->sc = NULL;
3811 }
3812 if (NULL != (vl = neighbour->vl))
3813 {
3814 GNUNET_assert (neighbour == vl->n);
3815 vl->n = NULL;
3816 if ((GNUNET_YES == drop_link) || (NULL == vl->dv))
3817 {
3820 }
3821 else
3822 {
3825 }
3826 neighbour->vl = NULL;
3827 }
3828 GNUNET_free (neighbour);
3829}
3830
3831
3838static void
3840 const struct GNUNET_PeerIdentity *pid)
3841{
3842 struct GNUNET_MQ_Envelope *env;
3843 struct ConnectInfoMessage *cim;
3844
3845 GNUNET_assert (CT_CORE == tc->type);
3847 cim->id = *pid;
3848 GNUNET_MQ_send (tc->mq, env);
3849}
3850
3851
3857static void
3859{
3861 "Informing CORE clients about connection to %s\n",
3862 GNUNET_i2s (pid));
3863 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3864 {
3865 if (CT_CORE != tc->type)
3866 continue;
3868 }
3869}
3870
3871
3879static void
3880transmit_on_queue (void *cls);
3881
3882
3886static unsigned int
3888{
3889 for (struct Queue *s = queue_head; NULL != s;
3890 s = s->next_client)
3891 {
3892 if (s->tc->details.communicator.address_prefix !=
3893 queue->tc->details.communicator.address_prefix)
3894 {
3896 "queue address %s qid %u compare with queue: address %s qid %u\n",
3897 queue->address,
3898 queue->qid,
3899 s->address,
3900 s->qid);
3901 if ((s->priority > queue->priority) && (0 < s->q_capacity) &&
3902 (QUEUE_LENGTH_LIMIT > s->queue_length) )
3903 return GNUNET_YES;
3905 "Lower prio\n");
3906 }
3907 }
3908 return GNUNET_NO;
3909}
3910
3911
3919static void
3921 struct Queue *queue,
3923{
3925
3926 if (queue->validated_until.abs_value_us < now.abs_value_us)
3927 return;
3929 queue->tc->details.communicator.
3930 queue_head))
3931 return;
3932
3933 if (queue->tc->details.communicator.total_queue_length >=
3935 {
3937 "Transmission on queue %s (QID %u) throttled due to communicator queue limit\n",
3938 queue->address,
3939 queue->qid);
3941 GST_stats,
3942 "# Transmission throttled due to communicator queue limit",
3943 1,
3944 GNUNET_NO);
3945 queue->idle = GNUNET_NO;
3946 return;
3947 }
3948 if (queue->queue_length >= QUEUE_LENGTH_LIMIT)
3949 {
3951 "Transmission on queue %s (QID %u) throttled due to communicator queue length limit\n",
3952 queue->address,
3953 queue->qid);
3955 "# Transmission throttled due to queue queue limit",
3956 1,
3957 GNUNET_NO);
3958 queue->idle = GNUNET_NO;
3959 return;
3960 }
3961 if (0 == queue->q_capacity)
3962 {
3964 "Transmission on queue %s (QID %u) throttled due to communicator message has capacity %"
3965 PRIu64 ".\n",
3966 queue->address,
3967 queue->qid,
3968 queue->q_capacity);
3970 "# Transmission throttled due to message queue capacity",
3971 1,
3972 GNUNET_NO);
3973 queue->idle = GNUNET_NO;
3974 return;
3975 }
3976 /* queue might indeed be ready, schedule it */
3977 if (NULL != queue->transmit_task)
3978 GNUNET_SCHEDULER_cancel (queue->transmit_task);
3979 queue->transmit_task =
3981 queue);
3983 "Considering transmission on queue `%s' QID %llu to %s\n",
3984 queue->address,
3985 (unsigned long long) queue->qid,
3986 GNUNET_i2s (&queue->neighbour->pid));
3987}
3988
3989
3996static void
3997check_link_down (void *cls)
3998{
3999 struct VirtualLink *vl = cls;
4000 struct DistanceVector *dv = vl->dv;
4001 struct Neighbour *n = vl->n;
4002 struct GNUNET_TIME_Absolute dvh_timeout;
4003 struct GNUNET_TIME_Absolute q_timeout;
4004
4006 "Checking if link is down\n");
4007 vl->visibility_task = NULL;
4008 dvh_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
4009 if (NULL != dv)
4010 {
4011 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4012 pos = pos->next_dv)
4013 dvh_timeout = GNUNET_TIME_absolute_max (dvh_timeout,
4014 pos->path_valid_until);
4015 if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
4016 {
4017 vl->dv->vl = NULL;
4018 vl->dv = NULL;
4019 }
4020 }
4021 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
4022 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
4023 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
4025 {
4026 vl->n->vl = NULL;
4027 vl->n = NULL;
4028 }
4029 if ((NULL == vl->n) && (NULL == vl->dv))
4030 {
4032 free_virtual_link (vl);
4033 return;
4034 }
4035 vl->visibility_task =
4036 GNUNET_SCHEDULER_add_at (GNUNET_TIME_absolute_max (q_timeout, dvh_timeout),
4038 vl);
4039}
4040
4041
4047static void
4048free_queue (struct Queue *queue)
4049{
4050 struct Neighbour *neighbour = queue->neighbour;
4051 struct TransportClient *tc = queue->tc;
4052 struct MonitorEvent me = { .cs = GNUNET_TRANSPORT_CS_DOWN,
4054 struct QueueEntry *qe;
4055 int maxxed;
4056 struct PendingAcknowledgement *pa;
4057 struct VirtualLink *vl;
4058
4060 "Cleaning up queue %u\n", queue->qid);
4061 if (NULL != queue->mo)
4062 {
4064 queue->mo = NULL;
4065 }
4066 if (NULL != queue->transmit_task)
4067 {
4068 GNUNET_SCHEDULER_cancel (queue->transmit_task);
4069 queue->transmit_task = NULL;
4070 }
4071 while (NULL != (pa = queue->pa_head))
4072 {
4073 GNUNET_CONTAINER_MDLL_remove (queue, queue->pa_head, queue->pa_tail, pa);
4074 pa->queue = NULL;
4075 }
4076
4078 neighbour->queue_head,
4079 neighbour->queue_tail,
4080 queue);
4082 tc->details.communicator.queue_head,
4083 tc->details.communicator.queue_tail,
4084 queue);
4086 tc->details.communicator.total_queue_length);
4088 "Cleaning up queue with length %u\n",
4089 queue->queue_length);
4090 while (NULL != (qe = queue->queue_head))
4091 {
4092 GNUNET_CONTAINER_DLL_remove (queue->queue_head, queue->queue_tail, qe);
4093 queue->queue_length--;
4094 tc->details.communicator.total_queue_length--;
4095 if (NULL != qe->pm)
4096 {
4097 GNUNET_assert (qe == qe->pm->qe);
4098 qe->pm->qe = NULL;
4099 }
4100 GNUNET_free (qe);
4101 }
4102 GNUNET_assert (0 == queue->queue_length);
4103 if ((maxxed) && (COMMUNICATOR_TOTAL_QUEUE_LIMIT >
4104 tc->details.communicator.total_queue_length))
4105 {
4106 /* Communicator dropped below threshold, resume all _other_ queues */
4108 GST_stats,
4109 "# Transmission throttled due to communicator queue limit",
4110 -1,
4111 GNUNET_NO);
4112 for (struct Queue *s = tc->details.communicator.queue_head; NULL != s;
4113 s = s->next_client)
4115 s,
4117 }
4118 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
4120
4121 vl = lookup_virtual_link (&neighbour->pid);
4122 if ((NULL != vl) && (neighbour == vl->n))
4123 {
4125 check_link_down (vl);
4126 }
4127 if (NULL == neighbour->queue_head)
4128 {
4129 free_neighbour (neighbour, GNUNET_NO);
4130 }
4131}
4132
4133
4139static void
4141{
4142 struct TransportClient *tc = ale->tc;
4143
4144 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
4145 tc->details.communicator.addr_tail,
4146 ale);
4147 if (NULL != ale->sc)
4148 {
4150 "store cancel\n");
4152 ale->sc = NULL;
4153 }
4154 if (NULL != ale->st)
4155 {
4157 ale->st = NULL;
4158 }
4159 if (NULL != ale->signed_address)
4161 GNUNET_free (ale);
4162}
4163
4164
4173static int
4174stop_peer_request (void *cls,
4175 const struct GNUNET_PeerIdentity *pid,
4176 void *value)
4177{
4178 struct TransportClient *tc = cls;
4179 struct PeerRequest *pr = value;
4180
4181 if (NULL != pr->nc)
4183 pr->nc = NULL;
4185 GNUNET_YES ==
4186 GNUNET_CONTAINER_multipeermap_remove (tc->details.application.requests,
4187 pid,
4188 pr));
4189 GNUNET_free (pr);
4190
4191 return GNUNET_OK;
4192}
4193
4194
4195static void
4196do_shutdown (void *cls);
4197
4206static void
4207client_disconnect_cb (void *cls,
4208 struct GNUNET_SERVICE_Client *client,
4209 void *app_ctx)
4210{
4211 struct TransportClient *tc = app_ctx;
4212
4213 (void) cls;
4214 (void) client;
4216 switch (tc->type)
4217 {
4218 case CT_NONE:
4220 "Unknown Client %p disconnected, cleaning up.\n",
4221 tc);
4222 break;
4223
4224 case CT_CORE: {
4225 struct PendingMessage *pm;
4227 "CORE Client %p disconnected, cleaning up.\n",
4228 tc);
4229
4230
4231 while (NULL != (pm = tc->details.core.pending_msg_head))
4232 {
4234 tc->details.core.pending_msg_head,
4235 tc->details.core.pending_msg_tail,
4236 pm);
4237 pm->client = NULL;
4238 }
4239 }
4240 break;
4241
4242 case CT_MONITOR:
4244 "MONITOR Client %p disconnected, cleaning up.\n",
4245 tc);
4246
4247 break;
4248
4249 case CT_COMMUNICATOR: {
4250 struct Queue *q;
4251 struct AddressListEntry *ale;
4252
4254 "COMMUNICATOR Client %p disconnected, cleaning up.\n",
4255 tc);
4256
4257 if (NULL != tc->details.communicator.free_queue_entry_task)
4259 tc->details.communicator.free_queue_entry_task);
4260 while (NULL != (q = tc->details.communicator.queue_head))
4261 free_queue (q);
4262 while (NULL != (ale = tc->details.communicator.addr_head))
4264 GNUNET_free (tc->details.communicator.address_prefix);
4265 }
4266 break;
4267
4268 case CT_APPLICATION:
4270 "APPLICATION Client %p disconnected, cleaning up.\n",
4271 tc);
4272
4273 GNUNET_CONTAINER_multipeermap_iterate (tc->details.application.requests,
4275 tc);
4276 GNUNET_CONTAINER_multipeermap_destroy (tc->details.application.requests);
4277 break;
4278 }
4279 GNUNET_free (tc);
4280 if ((GNUNET_YES == in_shutdown) && (NULL == clients_head))
4281 {
4283 "Our last client disconnected\n");
4284 do_shutdown (cls);
4285 }
4286}
4287
4288
4298static int
4300 const struct GNUNET_PeerIdentity *pid,
4301 void *value)
4302{
4303 struct TransportClient *tc = cls;
4304 struct VirtualLink *vl = value;
4305
4306 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4307 return GNUNET_OK;
4308
4310 "Telling new CORE client about existing connection to %s\n",
4311 GNUNET_i2s (pid));
4313 return GNUNET_OK;
4314}
4315
4316
4322static void
4324 unsigned
4325 int free_cmc);
4326
4327static enum GNUNET_GenericReturnValue
4328resume_communicators (void *cls,
4329 const struct GNUNET_PeerIdentity *pid,
4330 void *value)
4331{
4332 struct VirtualLink *vl = value;
4333 struct CommunicatorMessageContext *cmc;
4334
4335 /* resume communicators */
4336 while (NULL != (cmc = vl->cmc_tail))
4337 {
4339 if (GNUNET_NO == cmc->continue_send)
4341 }
4342 return GNUNET_OK;
4343}
4344
4345
4354static void
4355handle_client_start (void *cls, const struct StartMessage *start)
4356{
4357 struct TransportClient *tc = cls;
4358 // uint32_t options;
4359 //
4360 // FIXME ignore the check of the peer ids for now.
4361 // (also deprecate the old way of obtaining our own peer ID)
4362 // options = ntohl (start->options);
4363 // if ((0 != (1 & options)) &&
4364 // (0 != GNUNET_memcmp (&start->self, &GST_my_identity)))
4365 // {
4366 // /* client thinks this is a different peer, reject */
4367 // GNUNET_break (0);
4368 // GNUNET_SERVICE_client_drop (tc->client);
4369 // return;
4370 // }
4371 if (CT_NONE != tc->type)
4372 {
4373 GNUNET_break (0);
4375 return;
4376 }
4377 tc->type = CT_CORE;
4379 "New CORE client with PID %s registered\n",
4380 GNUNET_i2s (&start->self));
4383 tc);
4386 NULL);
4388}
4389
4390
4397static int
4398check_client_send (void *cls, const struct OutboundMessage *obm)
4399{
4400 struct TransportClient *tc = cls;
4401 uint16_t size;
4402 const struct GNUNET_MessageHeader *obmm;
4403
4404 if (CT_CORE != tc->type)
4405 {
4406 GNUNET_break (0);
4407 return GNUNET_SYSERR;
4408 }
4409 size = ntohs (obm->header.size) - sizeof(struct OutboundMessage);
4410 if (size < sizeof(struct GNUNET_MessageHeader))
4411 {
4412 GNUNET_break (0);
4413 return GNUNET_SYSERR;
4414 }
4415 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
4416 if (size != ntohs (obmm->size))
4417 {
4418 GNUNET_break (0);
4419 return GNUNET_SYSERR;
4420 }
4421 return GNUNET_OK;
4422}
4423
4424
4432static void
4434{
4435 struct TransportClient *tc = pm->client;
4436 struct VirtualLink *vl = pm->vl;
4437
4439 "client send response\n");
4440 if (NULL != tc)
4441 {
4442 struct GNUNET_MQ_Envelope *env;
4443 struct SendOkMessage *so_msg;
4444
4446 so_msg->peer = vl->target;
4448 "Confirming transmission of <%" PRIu64 "> to %s\n",
4449 pm->logging_uuid,
4450 GNUNET_i2s (&vl->target));
4451 GNUNET_MQ_send (tc->mq, env);
4452 }
4454}
4455
4456
4466static unsigned int
4467pick_random_dv_hops (const struct DistanceVector *dv,
4469 struct DistanceVectorHop **hops_array,
4470 unsigned int hops_array_length)
4471{
4472 uint64_t choices[hops_array_length];
4473 uint64_t num_dv;
4474 unsigned int dv_count;
4475
4476 /* Pick random vectors, but weighted by distance, giving more weight
4477 to shorter vectors */
4478 num_dv = 0;
4479 dv_count = 0;
4480 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4481 pos = pos->next_dv)
4482 {
4483 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
4484 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
4485 .rel_value_us == 0))
4486 continue; /* pos unconfirmed and confirmed required */
4487 num_dv += MAX_DV_HOPS_ALLOWED - pos->distance;
4488 dv_count++;
4489 }
4490 if (0 == dv_count)
4491 return 0;
4492 if (dv_count <= hops_array_length)
4493 {
4494 dv_count = 0;
4495 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4496 pos = pos->next_dv)
4497 hops_array[dv_count++] = pos;
4498 return dv_count;
4499 }
4500 for (unsigned int i = 0; i < hops_array_length; i++)
4501 {
4502 int ok = GNUNET_NO;
4503 while (GNUNET_NO == ok)
4504 {
4505 choices[i] =
4507 ok = GNUNET_YES;
4508 for (unsigned int j = 0; j < i; j++)
4509 if (choices[i] == choices[j])
4510 {
4511 ok = GNUNET_NO;
4512 break;
4513 }
4514 }
4515 }
4516 dv_count = 0;
4517 num_dv = 0;
4518 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4519 pos = pos->next_dv)
4520 {
4521 uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance;
4522
4523 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
4524 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
4525 .rel_value_us == 0))
4526 continue; /* pos unconfirmed and confirmed required */
4527 for (unsigned int i = 0; i < hops_array_length; i++)
4528 if ((num_dv <= choices[i]) && (num_dv + delta > choices[i]))
4529 hops_array[dv_count++] = pos;
4530 num_dv += delta;
4531 }
4532 return dv_count;
4533}
4534
4535
4542static int
4544 void *cls,
4546{
4547 struct TransportClient *tc = cls;
4548 uint16_t size;
4549
4550 if (CT_NONE != tc->type)
4551 {
4552 GNUNET_break (0);
4553 return GNUNET_SYSERR;
4554 }
4555 tc->type = CT_COMMUNICATOR;
4556 size = ntohs (cam->header.size) - sizeof(*cam);
4557 if (0 == size)
4558 return GNUNET_OK; /* receive-only communicator */
4560 return GNUNET_OK;
4561}
4562
4563
4569static void
4571 unsigned
4572 int free_cmc)
4573{
4574 if (0 != ntohl (cmc->im.fc_on))
4575 {
4576 /* send ACK when done to communicator for flow control! */
4577 struct GNUNET_MQ_Envelope *env;
4579
4581 "Acknowledge message with flow control id %" PRIu64 "\n",
4582 cmc->im.fc_id);
4584 ack->reserved = htonl (0);
4585 ack->fc_id = cmc->im.fc_id;
4586 ack->sender = cmc->im.neighbour_sender;
4587 GNUNET_MQ_send (cmc->tc->mq, env);
4588 }
4589
4591
4592 if (GNUNET_YES == free_cmc)
4593 {
4594 GNUNET_free (cmc);
4595 }
4596}
4597
4598
4599static void
4601{
4603}
4604
4605
4615static void
4616handle_client_recv_ok (void *cls, const struct RecvOkMessage *rom)
4617{
4618 struct TransportClient *tc = cls;
4619 struct VirtualLink *vl;
4620 uint32_t delta;
4621 struct CommunicatorMessageContext *cmc;
4622
4623 if (CT_CORE != tc->type)
4624 {
4625 GNUNET_break (0);
4627 return;
4628 }
4629 vl = lookup_virtual_link (&rom->peer);
4630 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4631 {
4633 "# RECV_OK dropped: virtual link unknown",
4634 1,
4635 GNUNET_NO);
4637 return;
4638 }
4639 delta = ntohl (rom->increase_window_delta);
4640 vl->core_recv_window += delta;
4642 "CORE ack receiving message, increased CORE recv window to %d\n",
4643 vl->core_recv_window);
4645 if (vl->core_recv_window <= 0)
4646 return;
4647 /* resume communicators */
4648 while (NULL != (cmc = vl->cmc_tail))
4649 {
4651 if (GNUNET_NO == cmc->continue_send)
4653 }
4654}
4655
4656
4663static void
4665 void *cls,
4667{
4668 struct TransportClient *tc = cls;
4669 uint16_t size;
4670
4671 size = ntohs (cam->header.size) - sizeof(*cam);
4672 if (0 == size)
4673 {
4675 "Receive-only communicator connected\n");
4676 return; /* receive-only communicator */
4677 }
4678 tc->details.communicator.address_prefix =
4679 GNUNET_strdup ((const char *) &cam[1]);
4680 tc->details.communicator.cc = ntohl (cam->cc);
4681 tc->details.communicator.can_burst = ntohl (cam->can_burst);
4683 "Communicator for peer %s with prefix '%s' connected %s\n",
4685 tc->details.communicator.address_prefix,
4686 tc->details.communicator.can_burst ? "can burst" :
4687 "can not burst");
4689}
4690
4691
4699static int
4701 void *cls,
4703{
4704 const struct GNUNET_MessageHeader *inbox;
4705 const char *is;
4706 uint16_t msize;
4707 uint16_t isize;
4708
4709 (void) cls;
4710 msize = ntohs (cb->header.size) - sizeof(*cb);
4711 inbox = (const struct GNUNET_MessageHeader *) &cb[1];
4712 isize = ntohs (inbox->size);
4713 if (isize >= msize)
4714 {
4715 GNUNET_break (0);
4716 return GNUNET_SYSERR;
4717 }
4718 is = (const char *) inbox;
4719 is += isize;
4720 msize -= isize;
4721 GNUNET_assert (0 < msize);
4722 if ('\0' != is[msize - 1])
4723 {
4724 GNUNET_break (0);
4725 return GNUNET_SYSERR;
4726 }
4727 return GNUNET_OK;
4728}
4729
4730
4731struct SignDvCls
4732{
4733 struct DistanceVector *dv;
4734 struct PilsRequest *req;
4735};
4736
4737
4738static void
4739sign_dv_cb (void *cls,
4740 const struct GNUNET_PeerIdentity *pid,
4741 const struct GNUNET_CRYPTO_EddsaSignature *sig)
4742{
4743 struct SignDvCls *sign_dv_cls = cls;
4744 struct DistanceVector *dv = sign_dv_cls->dv;
4745 struct PilsRequest *pr = sign_dv_cls->req;
4746
4747 pr->op = NULL;
4750 pr);
4751 GNUNET_free (pr);
4752
4753 dv->sender_sig = *sig;
4754}
4755
4756
4762static void
4763sign_ephemeral (struct DistanceVector *dv)
4764{
4765 struct EphemeralConfirmationPS ec;
4766 struct SignDvCls *sign_dv_cls;
4767
4771 ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL);
4772 ec.target = dv->target;
4773 ec.ephemeral_key = dv->ephemeral_key;
4774 ec.sender_monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
4775 ec.purpose.size = htonl (sizeof(ec));
4776 sign_dv_cls = GNUNET_new (struct SignDvCls);
4777 sign_dv_cls->req = GNUNET_new (struct PilsRequest);
4778 sign_dv_cls->dv = dv;
4781 sign_dv_cls->req);
4783 &ec.purpose,
4784 sign_dv_cb,
4785 sign_dv_cls);
4786}
4787
4788
4789static void
4791 struct TransportClient *tc);
4792
4793
4794static void
4795free_timedout_queue_entry (void *cls)
4796{
4797 struct TransportClient *tc = cls;
4799
4801 "freeing timedout queue entries\n");
4802
4803 tc->details.communicator.free_queue_entry_task = NULL;
4804 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
4805 queue = queue->next_client)
4806 {
4807 struct QueueEntry *qep = queue->queue_head;
4808
4810 "checking QID %u for timedout queue entries\n",
4811 queue->qid);
4812 while (NULL != qep)
4813 {
4814 struct QueueEntry *pos = qep;
4816 pos->creation_timestamp, now);
4817 qep = qep->next;
4818
4820 "diff to now %s \n",
4823 {
4825 "Freeing timed out QueueEntry with MID %" PRIu64
4826 " and QID %u\n",
4827 pos->mid,
4828 queue->qid);
4829 free_queue_entry (pos, tc);
4830 }
4831 }
4832 }
4833}
4834
4835
4845static void
4846queue_send_msg (struct Queue *queue,
4847 struct PendingMessage *pm,
4848 const void *payload,
4849 size_t payload_size)
4850{
4851 struct Neighbour *n = queue->neighbour;
4853 struct GNUNET_MQ_Envelope *env;
4854 struct PendingAcknowledgement *pa;
4855
4856 GNUNET_log (
4858 "Queueing %u bytes of payload for transmission <%" PRIu64
4859 "> on queue %llu to %s\n",
4860 (unsigned int) payload_size,
4861 (NULL == pm) ? 0 : pm->logging_uuid,
4862 (unsigned long long) queue->qid,
4863 GNUNET_i2s (&queue->neighbour->pid));
4864 env = GNUNET_MQ_msg_extra (smt,
4865 payload_size,
4867 smt->qid = htonl (queue->qid);
4868 smt->mid = GNUNET_htonll (queue->mid_gen);
4869 smt->receiver = n->pid;
4870 memcpy (&smt[1], payload, payload_size);
4871 {
4872 /* Pass the env to the communicator of queue for transmission. */
4873 struct QueueEntry *qe;
4874
4875 qe = GNUNET_new (struct QueueEntry);
4876 qe->creation_timestamp = GNUNET_TIME_absolute_get ();
4877 qe->mid = queue->mid_gen;
4879 "Create QueueEntry with MID %" PRIu64
4880 " and QID %u and prefix %s\n",
4881 qe->mid,
4882 queue->qid,
4883 queue->tc->details.communicator.address_prefix);
4884 queue->mid_gen++;
4885 qe->queue = queue;
4886 if (NULL != pm)
4887 {
4888 qe->pm = pm;
4889 // TODO Why do we have a retransmission. When we know, make decision if we still want this.
4890 // GNUNET_assert (NULL == pm->qe);
4891 if (NULL != pm->qe)
4892 {
4894 "Retransmitting message <%" PRIu64
4895 "> remove pm from qe with MID: %llu \n",
4896 pm->logging_uuid,
4897 (unsigned long long) pm->qe->mid);
4898 pm->qe->pm = NULL;
4899 }
4900 pm->qe = qe;
4901 }
4902 GNUNET_assert (CT_COMMUNICATOR == queue->tc->type);
4903 if (0 == queue->q_capacity)
4904 {
4905 // Messages without FC or fragments can get here.
4906 if (NULL != pm)
4907 {
4909 "Message %" PRIu64
4910 " (pm type %u) was not send because queue has no capacity.\n",
4911 pm->logging_uuid,
4912 pm->pmt);
4913 pm->qe = NULL;
4914 }
4915 GNUNET_free (env);
4916 GNUNET_free (qe);
4917 return;
4918 }
4919 GNUNET_CONTAINER_DLL_insert (queue->queue_head, queue->queue_tail, qe);
4920 queue->queue_length++;
4921 queue->tc->details.communicator.total_queue_length++;
4922 if (GNUNET_NO == queue->unlimited_length)
4923 queue->q_capacity--;
4925 "Queue %s with qid %u has capacity %" PRIu64 "\n",
4926 queue->address,
4927 queue->qid,
4928 queue->q_capacity);
4930 queue->tc->details.communicator.total_queue_length)
4931 queue->idle = GNUNET_NO;
4932 if (QUEUE_LENGTH_LIMIT == queue->queue_length)
4933 queue->idle = GNUNET_NO;
4934 if (0 == queue->q_capacity)
4935 queue->idle = GNUNET_NO;
4936
4937 if (GNUNET_NO == queue->idle)
4938 {
4939 struct TransportClient *tc = queue->tc;
4940
4941 if (NULL == tc->details.communicator.free_queue_entry_task)
4942 tc->details.communicator.free_queue_entry_task =
4944 &
4946 tc);
4947 }
4948 if (NULL != pm && NULL != (pa = pm->pa_head))
4949 {
4950 while (pm != pa->pm)
4951 pa = pa->next_pa;
4952 pa->num_send++;
4953 }
4954 // GNUNET_CONTAINER_multiuuidmap_get (pending_acks, &ack[i].ack_uuid.value);
4956 "Sending message MID %" PRIu64
4957 " of type %u (%u) and size %lu with MQ %p queue %s (QID %u) pending %"
4958 PRIu64 "\n",
4959 GNUNET_ntohll (smt->mid),
4960 ntohs (((const struct GNUNET_MessageHeader *) payload)->type),
4961 ntohs (smt->header.size),
4962 (unsigned long) payload_size,
4963 queue->tc->mq,
4964 queue->address,
4965 queue->qid,
4966 (NULL == pm) ? 0 : pm->logging_uuid);
4967 GNUNET_MQ_send (queue->tc->mq, env);
4968 }
4969}
4970
4971
4982static struct GNUNET_TIME_Relative
4983route_via_neighbour (const struct Neighbour *n,
4984 const struct GNUNET_MessageHeader *hdr,
4986{
4987 struct GNUNET_TIME_Absolute now;
4988 unsigned int candidates;
4989 unsigned int sel1;
4990 unsigned int sel2;
4991 struct GNUNET_TIME_Relative rtt;
4992
4993 /* Pick one or two 'random' queues from n (under constraints of options) */
4994 now = GNUNET_TIME_absolute_get ();
4995 /* FIXME-OPTIMIZE: give queues 'weights' and pick proportional to
4996 weight in the future; weight could be assigned by observed
4997 bandwidth (note: not sure if we should do this for this type
4998 of control traffic though). */
4999 candidates = 0;
5000 for (struct Queue *pos = n->queue_head; NULL != pos;
5001 pos = pos->next_neighbour)
5002 {
5003 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
5004 (pos->validated_until.abs_value_us > now.abs_value_us))
5005 candidates++;
5006 }
5007 if (0 == candidates)
5008 {
5009 /* This can happen rarely if the last confirmed queue timed
5010 out just as we were beginning to process this message. */
5012 "Could not route message of type %u to %s: no valid queue\n",
5013 ntohs (hdr->type),
5014 GNUNET_i2s (&n->pid));
5016 "# route selection failed (all no valid queue)",
5017 1,
5018 GNUNET_NO);
5020 }
5021
5024 if (0 == (options & RMO_REDUNDANT))
5025 sel2 = candidates; /* picks none! */
5026 else
5028 candidates = 0;
5029 for (struct Queue *pos = n->queue_head; NULL != pos;
5030 pos = pos->next_neighbour)
5031 {
5032 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
5033 (pos->validated_until.abs_value_us > now.abs_value_us))
5034 {
5035 if ((sel1 == candidates) || (sel2 == candidates))
5036 {
5038 "Routing message of type %u to %s using %s (#%u)\n",
5039 ntohs (hdr->type),
5040 GNUNET_i2s (&n->pid),
5041 pos->address,
5042 (sel1 == candidates) ? 1 : 2);
5043 rtt = GNUNET_TIME_relative_min (rtt, pos->pd.aged_rtt);
5044 queue_send_msg (pos, NULL, hdr, ntohs (hdr->size));
5045 }
5046 candidates++;
5047 }
5048 }
5049 return rtt;
5050}
5051
5052
5056struct DVKeyState
5057{
5061 gcry_cipher_hd_t cipher;
5062
5066 struct
5067 {
5072
5076 char aes_key[256 / 8];
5077
5081 char aes_ctr[128 / 8];
5082 } material;
5083};
5084
5085
5094static void
5096 const struct GNUNET_ShortHashCode *iv,
5097 struct DVKeyState *key)
5098{
5099 /* must match what we defive from decapsulated key */
5101 GNUNET_CRYPTO_hkdf_expand (&key->material,
5102 sizeof(key->material),
5103 km,
5104 "gnunet-transport-dv-key",
5105 strlen ("gnunet-transport-dv-key")
5106 ,
5107 km,
5108 sizeof(*km),
5109 iv,
5110 sizeof(*iv),
5111 NULL));
5113 "Deriving backchannel key based on KM %s and IV %s\n",
5114 GNUNET_sh2s (km),
5115 GNUNET_sh2s (iv));
5116 GNUNET_assert (0 == gcry_cipher_open (&key->cipher,
5117 GCRY_CIPHER_AES256 /* low level: go for speed */
5118 ,
5119 GCRY_CIPHER_MODE_CTR,
5120 0 /* flags */));
5121 GNUNET_assert (0 == gcry_cipher_setkey (key->cipher,
5122 &key->material.aes_key,
5123 sizeof(key->material.aes_key)));
5124 gcry_cipher_setctr (key->cipher,
5125 &key->material.aes_ctr,
5126 sizeof(key->material.aes_ctr));
5127}
5128
5129
5139static void
5140dv_hmac (const struct DVKeyState *key,
5141 struct GNUNET_HashCode *hmac,
5142 const void *data,
5143 size_t data_size)
5144{
5145 GNUNET_CRYPTO_hmac (&key->material.hmac_key, data, data_size, hmac);
5146}
5147
5148
5158static void
5159dv_encrypt (struct DVKeyState *key, const void *in, void *dst, size_t in_size)
5160{
5161 GNUNET_assert (0 ==
5162 gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size));
5163}
5164
5165
5176static enum GNUNET_GenericReturnValue
5177dv_decrypt (struct DVKeyState *key,
5178 void *out,
5179 const void *ciph,
5180 size_t out_size)
5181{
5182 return (0 ==
5183 gcry_cipher_decrypt (key->cipher,
5184 out, out_size,
5185 ciph, out_size)) ? GNUNET_OK : GNUNET_SYSERR;
5186}
5187
5188
5194static void
5195dv_key_clean (struct DVKeyState *key)
5196{
5197 gcry_cipher_close (key->cipher);
5198 GNUNET_CRYPTO_zero_keys (&key->material, sizeof(key->material));
5199}
5200
5201
5212typedef void (*DVMessageHandler) (void *cls,
5213 struct Neighbour *next_hop,
5214 const struct GNUNET_MessageHeader *hdr,
5216
5231static struct GNUNET_TIME_Relative
5233 unsigned int num_dvhs,
5234 struct DistanceVectorHop **dvhs,
5235 const struct GNUNET_MessageHeader *hdr,
5236 DVMessageHandler use,
5237 void *use_cls,
5239 enum GNUNET_GenericReturnValue without_fc)
5240{
5241 struct TransportDVBoxMessage box_hdr;
5242 struct TransportDVBoxPayloadP payload_hdr;
5243 uint16_t enc_body_size = ntohs (hdr->size);
5244 char enc[sizeof(struct TransportDVBoxPayloadP) + enc_body_size] GNUNET_ALIGN;
5245 struct DVKeyState *key;
5246 struct GNUNET_TIME_Relative rtt;
5247 struct GNUNET_ShortHashCode km;
5248
5249 key = GNUNET_new (struct DVKeyState);
5250 /* Encrypt payload */
5251 box_hdr.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX);
5252 box_hdr.total_hops = htons (0);
5253 box_hdr.without_fc = htons (without_fc);
5254 // update_ephemeral (dv);
5255 if (0 ==
5256 GNUNET_TIME_absolute_get_remaining (dv->ephemeral_validity).rel_value_us)
5257 {
5258 GNUNET_CRYPTO_eddsa_kem_encaps (&dv->target.public_key,
5259 &dv->ephemeral_key,
5260 &km);
5261 dv->km = GNUNET_new (struct GNUNET_ShortHashCode);
5262 GNUNET_memcpy (dv->km, &km, sizeof(struct GNUNET_ShortHashCode));
5263 sign_ephemeral (dv);
5264 }
5265 box_hdr.ephemeral_key = dv->ephemeral_key;
5266 payload_hdr.sender_sig = dv->sender_sig;
5267
5269 &box_hdr.iv,
5270 sizeof(box_hdr.iv));
5271 // We are creating this key, so this must work.
5272 // FIXME: Possibly also add return values here. We are processing
5273 // Input from other peers...
5274 dv_setup_key_state_from_km (dv->km, &box_hdr.iv, key);
5275 payload_hdr.sender = *GST_my_identity;
5276 payload_hdr.monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
5277 dv_encrypt (key, &payload_hdr, enc, sizeof(payload_hdr));
5278 dv_encrypt (key,
5279 hdr,
5280 &enc[sizeof(struct TransportDVBoxPayloadP)],
5281 enc_body_size);
5282 dv_hmac (key, &box_hdr.hmac, enc, sizeof(enc));
5283 dv_key_clean (key);
5285 /* For each selected path, take the pre-computed header and body
5286 and add the path in the middle of the message; then send it. */
5287 for (unsigned int i = 0; i < num_dvhs; i++)
5288 {
5289 struct DistanceVectorHop *dvh = dvhs[i];
5290 unsigned int num_hops = dvh->distance + 1;
5291 char buf[sizeof(struct TransportDVBoxMessage)
5292 + sizeof(struct GNUNET_PeerIdentity) * num_hops
5293 + sizeof(struct TransportDVBoxPayloadP)
5294 + enc_body_size] GNUNET_ALIGN;
5295 struct GNUNET_PeerIdentity *dhops;
5296
5297 box_hdr.header.size = htons (sizeof(buf));
5298 box_hdr.orig_size = htons (sizeof(buf));
5299 box_hdr.num_hops = htons (num_hops);
5300 memcpy (buf, &box_hdr, sizeof(box_hdr));
5301 dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
5302 memcpy (dhops,
5303 dvh->path,
5304 dvh->distance * sizeof(struct GNUNET_PeerIdentity));
5305 dhops[dvh->distance] = dv->target;
5306 if (GNUNET_EXTRA_LOGGING > 0)
5307 {
5308 char *path;
5309
5311 for (unsigned int j = 0; j < num_hops; j++)
5312 {
5313 char *tmp;
5314
5315 GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
5316 GNUNET_free (path);
5317 path = tmp;
5318 }
5320 "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
5321 ntohs (hdr->type),
5322 GNUNET_i2s (&dv->target),
5323 i + 1,
5324 num_dvhs,
5325 path);
5326 GNUNET_free (path);
5327 }
5328 rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
5329 memcpy (&dhops[num_hops], enc, sizeof(enc));
5330 use (use_cls,
5331 dvh->next_hop,
5332 (const struct GNUNET_MessageHeader *) buf,
5333 options);
5334 GNUNET_free (key);
5335 }
5336 return rtt;
5337}
5338
5339
5349static void
5350send_dv_to_neighbour (void *cls,
5351 struct Neighbour *next_hop,
5352 const struct GNUNET_MessageHeader *hdr,
5354{
5355 (void) cls;
5356 (void) route_via_neighbour (next_hop, hdr, RMO_UNCONFIRMED_ALLOWED);
5357}
5358
5359
5371static struct GNUNET_TIME_Relative
5373// route_control_message_without_fc (const struct GNUNET_PeerIdentity *target,
5374 const struct GNUNET_MessageHeader *hdr,
5376{
5377 // struct VirtualLink *vl;
5378 struct Neighbour *n;
5379 struct DistanceVector *dv;
5380 struct GNUNET_TIME_Relative rtt1;
5381 struct GNUNET_TIME_Relative rtt2;
5382 const struct GNUNET_PeerIdentity *target = &vl->target;
5383
5385 "Trying to route message of type %u to %s without fc\n",
5386 ntohs (hdr->type),
5387 GNUNET_i2s (target));
5388
5389 // TODO Do this elsewhere. vl should be given as parameter to method.
5390 // vl = lookup_virtual_link (target);
5391 GNUNET_assert (NULL != vl && GNUNET_YES == vl->confirmed);
5392 if (NULL == vl)
5394 n = vl->n;
5395 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
5396 if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
5397 {
5398 /* if confirmed is required, and we do not have anything
5399 confirmed, drop respective options */
5400 if (NULL == n)
5401 n = lookup_neighbour (target);
5402 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
5404 }
5405 if ((NULL == n) && (NULL == dv))
5406 {
5408 "Cannot route message of type %u to %s: no route\n",
5409 ntohs (hdr->type),
5410 GNUNET_i2s (target));
5412 "# Messages dropped in routing: no acceptable method",
5413 1,
5414 GNUNET_NO);
5416 }
5418 "Routing message of type %u to %s with options %X\n",
5419 ntohs (hdr->type),
5420 GNUNET_i2s (target),
5421 (unsigned int) options);
5422 /* If both dv and n are possible and we must choose:
5423 flip a coin for the choice between the two; for now 50/50 */
5424 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
5425 {
5427 n = NULL;
5428 else
5429 dv = NULL;
5430 }
5431 if ((NULL != n) && (NULL != dv))
5432 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
5433 enough for redundancy, so clear the flag. */
5436 if (NULL != n)
5437 {
5439 "Try to route message of type %u to %s without fc via neighbour\n",
5440 ntohs (hdr->type),
5441 GNUNET_i2s (target));
5442 rtt1 = route_via_neighbour (n, hdr, options);
5443 }
5444 if (NULL != dv)
5445 {
5446 struct DistanceVectorHop *hops[2];
5447 unsigned int res;
5448
5450 options,
5451 hops,
5452 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
5453 if (0 == res)
5454 {
5456 "Failed to route message, could not determine DV path\n");
5457 return rtt1;
5458 }
5460 "encapsulate_for_dv 1\n");
5461 rtt2 = encapsulate_for_dv (dv,
5462 res,
5463 hops,
5464 hdr,
5466 NULL,
5468 GNUNET_YES);
5469 }
5470 return GNUNET_TIME_relative_min (rtt1, rtt2);
5471}
5472
5473
5474static void
5475consider_sending_fc (void *cls);
5476
5483static void
5484task_consider_sending_fc (void *cls)
5485{
5486 struct VirtualLink *vl = cls;
5487 vl->fc_retransmit_task = NULL;
5488 consider_sending_fc (cls);
5489}
5490
5491
5492static char *
5493get_address_without_port (const char *address);
5494
5495
5497{
5498 size_t off;
5499 char *tgnas;
5500};
5501
5502
5503static enum GNUNET_GenericReturnValue
5504add_global_addresses (void *cls,
5505 const struct GNUNET_PeerIdentity *pid,
5506 void *value)
5507{
5508 struct AddGlobalAddressesContext *ctx = cls;
5509 struct TransportGlobalNattedAddress *tgna = value;
5510 char *addr = (char *) &tgna[1];
5511
5513 "sending address %s length %u\n",
5514 addr,
5515 ntohl (tgna->address_length));
5516 GNUNET_memcpy (&(ctx->tgnas[ctx->off]), tgna, sizeof (struct
5518 + ntohl (tgna->address_length));
5519 ctx->off += sizeof(struct TransportGlobalNattedAddress) + ntohl (tgna->
5521
5522 return GNUNET_OK;
5523}
5524
5525
5526static struct GNUNET_TIME_Relative
5527calculate_rtt (struct DistanceVector *dv);
5528
5529
5536static void
5537consider_sending_fc (void *cls)
5538{
5539 struct VirtualLink *vl = cls;
5540 struct GNUNET_TIME_Absolute monotime;
5541 struct TransportFlowControlMessage *fc;
5543 struct GNUNET_TIME_Relative rtt;
5544 struct GNUNET_TIME_Relative rtt_average;
5545 struct Neighbour *n = vl->n;
5546
5547 if (NULL != n && 0 < n->number_of_addresses)
5548 {
5549 size_t addresses_size =
5550 n->number_of_addresses * sizeof (struct TransportGlobalNattedAddress) + n
5551 ->size_of_global_addresses;
5552 char *tgnas = GNUNET_malloc (addresses_size);
5554 ctx.off = 0;
5555 ctx.tgnas = tgnas;
5556
5558 + addresses_size);
5559 fc->header.size = htons (sizeof(struct TransportFlowControlMessage)
5560 + addresses_size);
5561 fc->size_of_addresses = htonl (n->size_of_global_addresses);
5562 fc->number_of_addresses = htonl (n->number_of_addresses);
5565 &ctx);
5568 }
5569 else
5570 {
5571 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage));
5572 fc->header.size = htons (sizeof(struct TransportFlowControlMessage));
5573 }
5574
5576 /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
5577 it always! */
5578 /* For example, we should probably ONLY do this if a bit more than
5579 an RTT has passed, or if the window changed "significantly" since
5580 then. See vl->last_fc_rtt! NOTE: to do this properly, we also
5581 need an estimate for the bandwidth-delay-product for the entire
5582 VL, as that determines "significantly". We have the delay, but
5583 the bandwidth statistics need to be added for the VL!*/(void) duration;
5584
5585 if (NULL != vl->dv)
5586 rtt_average = calculate_rtt (vl->dv);
5587 else
5588 rtt_average = GNUNET_TIME_UNIT_FOREVER_REL;
5589 fc->rtt = GNUNET_TIME_relative_hton (rtt_average);
5591 "Sending FC seq %u to %s with new window %llu %lu %u\n",
5592 (unsigned int) vl->fc_seq_gen,
5593 GNUNET_i2s (&vl->target),
5594 (unsigned long long) vl->incoming_fc_window_size,
5595 (unsigned long) rtt_average.rel_value_us,
5596 vl->sync_ready);
5598 vl->last_fc_transmission = monotime;
5599 fc->sync_ready = vl->sync_ready;
5601 fc->seq = htonl (vl->fc_seq_gen++);
5602 fc->inbound_window_size = GNUNET_htonll (vl->incoming_fc_window_size
5605 fc->outbound_sent = GNUNET_htonll (vl->outbound_fc_window_size_used);
5606 fc->outbound_window_size = GNUNET_htonll (vl->outbound_fc_window_size);
5607 fc->sender_time = GNUNET_TIME_absolute_hton (monotime);
5609 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
5610 {
5613 "FC retransmission to %s failed, will retry in %s\n",
5614 GNUNET_i2s (&vl->target),
5617 }
5618 else
5619 {
5620 /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
5621 vl->last_fc_rtt = rtt;
5622 }
5623 if (NULL != vl->fc_retransmit_task)
5626 {
5628 vl->fc_retransmit_count = 0;
5629 }
5630 vl->fc_retransmit_task =
5632 vl->fc_retransmit_count++;
5633 GNUNET_free (fc);
5634}
5635
5636
5653static void
5655{
5656 struct Neighbour *n = vl->n;
5657 struct DistanceVector *dv = vl->dv;
5658 struct GNUNET_TIME_Absolute now;
5659 struct VirtualLink *vl_next_hop;
5660 int elig;
5661
5663 "check_vl_transmission to target %s\n",
5664 GNUNET_i2s (&vl->target));
5665 /* Check that we have an eligible pending message!
5666 (cheaper than having #transmit_on_queue() find out!) */
5667 elig = GNUNET_NO;
5668 for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
5669 pm = pm->next_vl)
5670 {
5672 "check_vl_transmission loop\n");
5673 if (NULL != pm->qe)
5674 continue; /* not eligible, is in a queue! */
5675 if (pm->bytes_msg + vl->outbound_fc_window_size_used >
5677 {
5679 "Stalled message %" PRIu64
5680 " transmission on VL %s due to flow control: %llu < %llu\n",
5681 pm->logging_uuid,
5682 GNUNET_i2s (&vl->target),
5683 (unsigned long long) vl->outbound_fc_window_size,
5684 (unsigned long long) (pm->bytes_msg
5687 return; /* We have a message, but flow control says "nope" */
5688 }
5690 "Target window on VL %s not stalled. Scheduling transmission on queue\n",
5691 GNUNET_i2s (&vl->target));
5692 /* Notify queues at direct neighbours that we are interested */
5693 now = GNUNET_TIME_absolute_get ();
5694 if (NULL != n)
5695 {
5696 for (struct Queue *queue = n->queue_head; NULL != queue;
5697 queue = queue->next_neighbour)
5698 {
5699 if ((GNUNET_YES == queue->idle) &&
5700 (queue->validated_until.abs_value_us > now.abs_value_us))
5701 {
5703 "Direct neighbour %s not stalled\n",
5704 GNUNET_i2s (&n->pid));
5706 queue,
5708 elig = GNUNET_YES;
5709 }
5710 else
5712 "Neighbour Queue QID: %u (%u) busy or invalid\n",
5713 queue->qid,
5714 queue->idle);
5715 }
5716 }
5717 /* Notify queues via DV that we are interested */
5718 if (NULL != dv)
5719 {
5720 /* Do DV with lower scheduler priority, which effectively means that
5721 IF a neighbour exists and is available, we prefer it. */
5722 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5723 pos = pos->next_dv)
5724 {
5725 struct Neighbour *nh_iter = pos->next_hop;
5726
5727
5728 if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
5729 continue; /* skip this one: path not validated */
5730 else
5731 {
5732 vl_next_hop = lookup_virtual_link (&nh_iter->pid);
5733 GNUNET_assert (NULL != vl_next_hop);
5734 if (pm->bytes_msg + vl_next_hop->outbound_fc_window_size_used >
5735 vl_next_hop->outbound_fc_window_size)
5736 {
5738 "Stalled message %" PRIu64
5739 " transmission on next hop %s due to flow control: %llu < %llu\n",
5740 pm->logging_uuid,
5741 GNUNET_i2s (&vl_next_hop->target),
5742 (unsigned long
5743 long) vl_next_hop->outbound_fc_window_size,
5744 (unsigned long long) (pm->bytes_msg
5745 + vl_next_hop->
5746 outbound_fc_window_size_used));
5747 consider_sending_fc (vl_next_hop);
5748 continue; /* We have a message, but flow control says "nope" for the first hop of this path */
5749 }
5750 for (struct Queue *queue = nh_iter->queue_head; NULL != queue;
5751 queue = queue->next_neighbour)
5752 if ((GNUNET_YES == queue->idle) &&
5753 (queue->validated_until.abs_value_us > now.abs_value_us))
5754 {
5756 "Next hop neighbour %s not stalled\n",
5757 GNUNET_i2s (&nh_iter->pid));
5759 queue,
5761 elig = GNUNET_YES;
5762 }
5763 else
5765 "DV Queue QID: %u (%u) busy or invalid\n",
5766 queue->qid,
5767 queue->idle);
5768 }
5769 }
5770 }
5771 if (GNUNET_YES == elig)
5773 "Eligible message %" PRIu64 " of size %u to %s: %llu/%llu\n",
5774 pm->logging_uuid,
5775 pm->bytes_msg,
5776 GNUNET_i2s (&vl->target),
5777 (unsigned long long) vl->outbound_fc_window_size,
5778 (unsigned long long) (pm->bytes_msg
5780 break;
5781 }
5782}
5783
5784
5791static void
5792handle_client_send (void *cls, const struct OutboundMessage *obm)
5793{
5794 struct TransportClient *tc = cls;
5795 struct PendingMessage *pm;
5796 const struct GNUNET_MessageHeader *obmm;
5797 uint32_t bytes_msg;
5798 struct VirtualLink *vl;
5800
5801 GNUNET_assert (CT_CORE == tc->type);
5802 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
5803 bytes_msg = ntohs (obmm->size);
5804 pp = ntohl (obm->priority);
5805 vl = lookup_virtual_link (&obm->peer);
5806 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
5807 {
5809 "Don't have %s as a neighbour (anymore).\n",
5810 GNUNET_i2s (&obm->peer));
5811 /* Failure: don't have this peer as a neighbour (anymore).
5812 Might have gone down asynchronously, so this is NOT
5813 a protocol violation by CORE. Still count the event,
5814 as this should be rare. */
5817 "# messages dropped (neighbour unknown)",
5818 1,
5819 GNUNET_NO);
5820 return;
5821 }
5822
5823 pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
5825 "1 created pm %p storing vl %p\n",
5826 pm,
5827 vl);
5828 pm->logging_uuid = logging_uuid_gen++;
5829 pm->prefs = pp;
5830 pm->client = tc;
5831 pm->vl = vl;
5832 pm->bytes_msg = bytes_msg;
5833 memcpy (&pm[1], obmm, bytes_msg);
5835 "Sending message of type %u with %u bytes as <%" PRIu64
5836 "> to %s\n",
5837 ntohs (obmm->type),
5838 bytes_msg,
5839 pm->logging_uuid,
5840 GNUNET_i2s (&obm->peer));
5842 tc->details.core.pending_msg_head,
5843 tc->details.core.pending_msg_tail,
5844 pm);
5846 vl->pending_msg_head,
5847 vl->pending_msg_tail,
5848 pm);
5851}
5852
5853
5863static void
5865 void *cls,
5867{
5868 struct Neighbour *n;
5869 struct VirtualLink *vl;
5870 struct TransportClient *tc = cls;
5871 const struct GNUNET_MessageHeader *inbox =
5872 (const struct GNUNET_MessageHeader *) &cb[1];
5873 uint16_t isize = ntohs (inbox->size);
5874 const char *is = ((const char *) &cb[1]) + isize;
5875 size_t slen = strlen (is) + 1;
5876 char
5877 mbuf[slen + isize
5878 + sizeof(struct
5882
5883 /* 0-termination of 'is' was checked already in
5884 #check_communicator_backchannel() */
5886 "Preparing backchannel transmission to %s:%s of type %u and size %u\n",
5887 GNUNET_i2s (&cb->pid),
5888 is,
5889 ntohs (inbox->type),
5890 ntohs (inbox->size));
5891 /* encapsulate and encrypt message */
5892 be->header.type =
5894 be->header.size = htons (sizeof(mbuf));
5895 memcpy (&be[1], inbox, isize);
5896 memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
5897 + isize],
5898 is,
5899 strlen (is) + 1);
5900 // route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
5901 vl = lookup_virtual_link (&cb->pid);
5902 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
5903 {
5905 }
5906 else
5907 {
5908 /* Use route via neighbour */
5909 n = lookup_neighbour (&cb->pid);
5910 if (NULL != n)
5912 n,
5913 &be->header,
5914 RMO_NONE);
5915 }
5917}
5918
5919
5927static int
5928check_add_address (void *cls,
5929 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5930{
5931 struct TransportClient *tc = cls;
5932
5933 if (CT_COMMUNICATOR != tc->type)
5934 {
5935 GNUNET_break (0);
5936 return GNUNET_SYSERR;
5937 }
5939 return GNUNET_OK;
5940}
5941
5942
5948static void
5949store_pi (void *cls);
5950
5951
5956{
5957
5961 struct AddressListEntry *ale;
5962
5966 struct PilsRequest *req;
5967
5968
5972 struct GNUNET_TIME_Absolute et;
5973};
5974
5975
5976static void
5977shc_cont (void *cls, int success)
5978{
5979 struct PilsAddressSignContext *pc = cls;
5980
5981 GNUNET_assert (NULL == pc->req);
5982 if (GNUNET_OK != success)
5983 {
5985 "Failed to store our address `%s' with peerstore\n",
5986 pc->ale->address);
5987 if (NULL == pc->ale->st)
5988 {
5990 &store_pi,
5991 pc->ale);
5992 }
5993 }
5994 GNUNET_free (pc);
5995}
5996
5997
6001static void
6002pils_sign_hello_cb (void *cls,
6003 const struct GNUNET_PeerIdentity *pid,
6004 const struct GNUNET_CRYPTO_EddsaSignature *sig)
6005{
6006 struct PilsAddressSignContext *pc = cls;
6007 struct GNUNET_MQ_Envelope *env;
6008 const struct GNUNET_MessageHeader *msg;
6009
6010 pc->req->op = NULL;
6013 pc->req);
6014 GNUNET_free (pc->req);
6015 pc->req = NULL;
6018 pid,
6019 sig,
6020 pc->et);
6023 "store_pi 1\n");
6025 msg,
6026 shc_cont,
6027 pc);
6028 GNUNET_free (env);
6029}
6030
6031
6038static void
6039peerstore_store_own_cb (void *cls, int success)
6040{
6041 struct PilsAddressSignContext *pc = cls;
6042
6043 pc->ale->sc = NULL;
6044 if (GNUNET_YES != success)
6046 "Failed to store our own address `%s' in peerstore!\n",
6047 pc->ale->address);
6048 else
6050 "Successfully stored our own address `%s' in peerstore!\n",
6051 pc->ale->address);
6052 /* refresh period is 1/4 of expiration time, that should be plenty
6053 without being excessive. */
6054 if (NULL == pc->ale->st)
6055 {
6056 pc->ale->st =
6058 GNUNET_TIME_relative_divide (pc->ale->expiration,
6059 4ULL),
6060 &store_pi,
6061 pc->ale);
6062 }
6063
6064 /* Now we have to update our HELLO! */
6066 pc->req = GNUNET_new (struct PilsRequest);
6069 pc->req);
6070 pc->req->op = GNUNET_PILS_sign_hello (pils,
6072 pc->et,
6074 pc);
6075}
6076
6077
6078// This function
6079static void
6080pils_sign_addr_cb (void *cls,
6081 const struct GNUNET_PeerIdentity *pid,
6082 const struct GNUNET_CRYPTO_EddsaSignature *sig)
6083{
6084 struct PilsAddressSignContext *pc = cls;
6085 char *sig_str;
6086 void *result;
6087 size_t result_size;
6088
6089 pc->req->op = NULL;
6092 pc->req);
6093 GNUNET_free (pc->req);
6094 sig_str = NULL;
6095 (void) GNUNET_STRINGS_base64_encode (sig, sizeof(*sig), &sig_str);
6096 result_size =
6097 1 + GNUNET_asprintf (
6098 (char **) &result,
6099 "%s;%llu;%u;%s",
6100 sig_str,
6101 (unsigned long long) pc->et.abs_value_us,
6102 (unsigned int) pc->ale->nt,
6103 pc->ale->address);
6104 GNUNET_free (sig_str);
6105
6107 "Build our HELLO URI `%s'\n",
6108 (char*) result);
6109
6110 pc->ale->signed_address = result;
6111 pc->ale->signed_address_len = result_size;
6113
6114 expiration = GNUNET_TIME_relative_to_absolute (pc->ale->expiration);
6116 "transport",
6117 GST_my_identity, // FIXME
6119 result,
6120 result_size,
6121 expiration,
6124 pc);
6125}
6126
6127
6131struct SignedAddress
6132{
6137
6142
6146 struct GNUNET_HashCode addr_hash GNUNET_PACKED;
6147};
6148
6149
6163void
6165 struct AddressListEntry *ale,
6166 struct GNUNET_TIME_Absolute mono_time)
6167{
6168 struct SignedAddress sa;
6169 struct PilsAddressSignContext *pc;
6170
6171 sa.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS);
6172 sa.purpose.size = htonl (sizeof(sa));
6173 sa.mono_time = GNUNET_TIME_absolute_hton (mono_time);
6174 GNUNET_CRYPTO_hash (ale->address, strlen (ale->address), &sa.addr_hash);
6176 pc->ale = ale;
6177 pc->et = mono_time;
6178 pc->req = GNUNET_new (struct PilsRequest);
6180 &sa.purpose,
6182 pc);
6185 pc->req);
6186}
6187
6188
6194static void
6195store_pi (void *cls)
6196{
6197 struct AddressListEntry *ale = cls;
6198 const char *dash;
6199 char *address_uri;
6201 unsigned int add_success;
6202
6203 if (NULL == GST_my_identity)
6204 {
6206 &store_pi,
6207 ale);
6208 return;
6209 }
6210
6211 dash = strchr (ale->address, '-');
6212 GNUNET_assert (NULL != dash);
6213 dash++;
6214 GNUNET_asprintf (&address_uri,
6215 "%s://%s",
6216 prefix,
6217 dash);
6219 ale->st = NULL;
6221 "Storing our address `%s' in peerstore until %s!\n",
6222 ale->address,
6225 address_uri);
6226 if (GNUNET_OK != add_success)
6227 {
6229 "Storing our address `%s' %s\n",
6230 address_uri,
6231 GNUNET_NO == add_success ? "not done" : "failed");
6232 GNUNET_free (address_uri);
6233 return;
6234 }
6235 else
6236 {
6237
6239 "Storing our address `%s'\n",
6240 address_uri);
6241 }
6242 // FIXME hello_mono_time used here?? What about expiration in ale?
6243 pils_sign_address (ale,
6245 // TODO keep track of op and potentially cancle/clean
6246 GNUNET_free (address_uri);
6247}
6248
6249
6250static struct AddressListEntry *
6254 const char *address,
6255 uint32_t aid,
6256 size_t slen)
6257{
6258 struct AddressListEntry *ale;
6259 char *address_without_port;
6260
6261 ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
6262 ale->tc = tc;
6263 ale->address = (const char *) &ale[1];
6264 ale->expiration = expiration;
6265 ale->aid = aid;
6266 ale->nt = nt;
6267 memcpy (&ale[1], address, slen);
6268 address_without_port = get_address_without_port (ale->address);
6270 "Is this %s a local address (%s)\n",
6271 address_without_port,
6272 ale->address);
6273 if (0 != strcmp ("127.0.0.1", address_without_port))
6274 {
6275 if (NULL != ale->st)
6276 {
6278 }
6279 ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
6280 }
6281 GNUNET_free (address_without_port);
6282
6283 return ale;
6284}
6285
6286
6287static void
6288feed_addresses_to_pils (void *cls)
6289{
6290
6292 "Feeding addresses to PILS\n");
6293 pils_feed_task = NULL;
6294
6296 GST_my_hello);
6297}
6298
6299
6306static void
6307handle_add_address (void *cls,
6308 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
6309{
6310 struct TransportClient *tc = cls;
6311 struct AddressListEntry *ale;
6312 size_t slen;
6313 char *address;
6314
6315 /* 0-termination of &aam[1] was checked in #check_add_address */
6317 "Communicator added address `%s'!\n",
6318 (const char *) &aam[1]);
6319 slen = ntohs (aam->header.size) - sizeof(*aam);
6320 address = GNUNET_malloc (slen);
6321 memcpy (address, &aam[1], slen);
6322 ale = create_address_entry (tc,
6324 ntohl (aam->nt),
6325 address,
6326 aam->aid,
6327 slen);
6328 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
6329 tc->details.communicator.addr_tail,
6330 ale);
6331 {
6332 for (struct AddressListEntry *iter = tc->details.communicator.addr_head;
6333 (NULL != iter && NULL != iter->next);
6334 iter = iter->next)
6335 {
6336 char *address_uri;
6337 char *dash = strchr (ale->address, '-');
6339 GNUNET_assert (NULL != dash);
6340 dash++;
6341 GNUNET_asprintf (&address_uri,
6342 "%s://%s",
6343 prefix,
6344 dash);
6347 GNUNET_free (address_uri);
6348 }
6349 if (NULL != pils_feed_task)
6353 NULL);
6354 }
6357}
6358
6359
6366static void
6367handle_del_address (void *cls,
6368 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
6369{
6370 struct TransportClient *tc = cls;
6371 struct AddressListEntry *alen;
6372
6373 if (CT_COMMUNICATOR != tc->type)
6374 {
6375 GNUNET_break (0);
6377 return;
6378 }
6379 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
6380 NULL != ale;
6381 ale = alen)
6382 {
6383 alen = ale->next;
6384 if (dam->aid != ale->aid)
6385 continue;
6386 GNUNET_assert (ale->tc == tc);
6388 "Communicator deleted address `%s'!\n",
6389 ale->address);
6391 ale->address);
6392 if (NULL != pils_feed_task)
6396 NULL);
6399 return;
6400 }
6402 "Communicator removed address we did not even have.\n");
6404 // GNUNET_SERVICE_client_drop (tc->client);
6405}
6406
6407
6415static void
6417
6418
6426static void
6427core_env_sent_cb (void *cls)
6428{
6429 struct CoreSentContext *ctx = cls;
6430 struct VirtualLink *vl = ctx->vl;
6431
6432 if (NULL == vl)
6433 {
6434 /* lost the link in the meantime, ignore */
6435 GNUNET_free (ctx);
6436 return;
6437 }
6440 vl->incoming_fc_window_size_ram -= ctx->size;
6441 vl->incoming_fc_window_size_used += ctx->isize;
6443 GNUNET_free (ctx);
6444}
6445
6446
6447static void
6449 const struct GNUNET_MessageHeader *mh,
6450 struct CommunicatorMessageContext *cmc,
6451 unsigned int free_cmc)
6452{
6453 uint16_t size = ntohs (mh->size);
6454 int have_core;
6455
6456 if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
6457 {
6459 "# CORE messages dropped (FC arithmetic overflow)",
6460 1,
6461 GNUNET_NO);
6463 "CORE messages of type %u with %u bytes dropped (FC arithmetic overflow)\n",
6464 (unsigned int) ntohs (mh->type),
6465 (unsigned int) ntohs (mh->size));
6466 if (GNUNET_YES == free_cmc)
6468 return;
6469 }
6471 {
6473 "# CORE messages dropped (FC window overflow)",
6474 1,
6475 GNUNET_NO);
6477 "CORE messages of type %u with %u bytes dropped (FC window overflow)\n",
6478 (unsigned int) ntohs (mh->type),
6479 (unsigned int) ntohs (mh->size));
6480 if (GNUNET_YES == free_cmc)
6482 return;
6483 }
6484
6485 /* Forward to all CORE clients */
6486 have_core = GNUNET_NO;
6487 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
6488 {
6489 struct GNUNET_MQ_Envelope *env;
6490 struct InboundMessage *im;
6491 struct CoreSentContext *ctx;
6492
6493 if (CT_CORE != tc->type)
6494 continue;
6497 ctx = GNUNET_new (struct CoreSentContext);
6498 ctx->vl = vl;
6499 ctx->size = size;
6500 ctx->isize = (GNUNET_NO == have_core) ? size : 0;
6501 have_core = GNUNET_YES;
6504 im->peer = cmc->im.sender;
6505 memcpy (&im[1], mh, size);
6506 GNUNET_MQ_send (tc->mq, env);
6508 }
6509 if (GNUNET_NO == have_core)
6510 {
6512 "Dropped message to CORE: no CORE client connected!\n");
6513 /* Nevertheless, count window as used, as it is from the
6514 perspective of the other peer! */
6516 /* TODO-M1 */
6518 "Dropped message of type %u with %u bytes to CORE: no CORE client connected!\n",
6519 (unsigned int) ntohs (mh->type),
6520 (unsigned int) ntohs (mh->size));
6521 if (GNUNET_YES == free_cmc)
6523 return;
6524 }
6526 "Delivered message from %s of type %u to CORE recv window %d\n",
6527 GNUNET_i2s (&cmc->im.sender),
6528 ntohs (mh->type),
6530 if (vl->core_recv_window > 0)
6531 {
6532 if (GNUNET_YES == free_cmc)
6534 return;
6535 }
6536 /* Wait with calling #finish_cmc_handling(cmc) until the message
6537 was processed by CORE MQs (for CORE flow control)! */
6538 if (GNUNET_YES == free_cmc)
6540}
6541
6542
6551static void
6552handle_raw_message (void *cls, const struct GNUNET_MessageHeader *mh)
6553{
6554 struct CommunicatorMessageContext *cmc = cls;
6555 // struct CommunicatorMessageContext *cmc_copy =
6556 // GNUNET_new (struct CommunicatorMessageContext);
6557 struct GNUNET_MessageHeader *mh_copy;
6558 struct RingBufferEntry *rbe;
6559 struct VirtualLink *vl;
6560 uint16_t size = ntohs (mh->size);
6561
6563 "Handling raw message of type %u with %u bytes\n",
6564 (unsigned int) ntohs (mh->type),
6565 (unsigned int) ntohs (mh->size));
6566
6567 if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
6568 (size < sizeof(struct GNUNET_MessageHeader)))
6569 {
6570 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6571
6572 GNUNET_break (0);
6573 finish_cmc_handling (cmc);
6575 return;
6576 }
6577 vl = lookup_virtual_link (&cmc->im.sender);
6578 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6579 {
6580 /* FIXME: sender is giving us messages for CORE but we don't have
6581 the link up yet! I *suspect* this can happen right now (i.e.
6582 sender has verified us, but we didn't verify sender), but if
6583 we pass this on, CORE would be confused (link down, messages
6584 arrive). We should investigate more if this happens often,
6585 or in a persistent manner, and possibly do "something" about
6586 it. Thus logging as error for now. */
6587
6588 mh_copy = GNUNET_malloc (size);
6589 rbe = GNUNET_new (struct RingBufferEntry);
6590 rbe->cmc = cmc;
6591 /*cmc_copy->tc = cmc->tc;
6592 cmc_copy->im = cmc->im;*/
6593 GNUNET_memcpy (mh_copy, mh, size);
6594
6595 rbe->mh = mh_copy;
6596
6598 {
6599 struct RingBufferEntry *rbe_old = ring_buffer[ring_buffer_head];
6600 GNUNET_free (rbe_old->cmc);
6601 GNUNET_free (rbe_old->mh);
6602 GNUNET_free (rbe_old);
6603 }
6604 ring_buffer[ring_buffer_head] = rbe;// cmc_copy;
6605 // cmc_copy->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6606 cmc->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6608 "Storing message for %s and type %u (%u) in ring buffer head %u is full %u\n",
6609 GNUNET_i2s (&cmc->im.sender),
6610 (unsigned int) ntohs (mh->type),
6611 (unsigned int) ntohs (mh_copy->type),
6615 {
6616 ring_buffer_head = 0;
6618 }
6619 else
6621
6623 "%u items stored in ring buffer\n",
6626
6627 /*GNUNET_break_op (0);
6628 GNUNET_STATISTICS_update (GST_stats,
6629 "# CORE messages dropped (virtual link still down)",
6630 1,
6631 GNUNET_NO);
6632
6633 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6634 "CORE messages of type %u with %u bytes dropped (virtual link still down)\n",
6635 (unsigned int) ntohs (mh->type),
6636 (unsigned int) ntohs (mh->size));
6637 finish_cmc_handling (cmc);*/
6640 // GNUNET_free (cmc);
6641 return;
6642 }
6644}
6645
6646
6654static int
6655check_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
6656{
6657 uint16_t size = ntohs (fb->header.size);
6658 uint16_t bsize = size - sizeof(*fb);
6659
6660 (void) cls;
6661 if (0 == bsize)
6662 {
6663 GNUNET_break_op (0);
6664 return GNUNET_SYSERR;
6665 }
6666 if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
6667 {
6668 GNUNET_break_op (0);
6669 return GNUNET_SYSERR;
6670 }
6671 if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
6672 {
6673 GNUNET_break_op (0);
6674 return GNUNET_SYSERR;
6675 }
6676 return GNUNET_YES;
6677}
6678
6679
6685static void
6686destroy_ack_cummulator (void *cls)
6687{
6688 struct AcknowledgementCummulator *ac = cls;
6689
6690 ac->task = NULL;
6691 GNUNET_assert (0 == ac->num_acks);
6693 GNUNET_YES ==
6695 GNUNET_free (ac);
6696}
6697
6698
6704static void
6706{
6707 struct Neighbour *n;
6708 struct VirtualLink *vl;
6709 struct AcknowledgementCummulator *ac = cls;
6710 char buf[sizeof(struct TransportReliabilityAckMessage)
6711 + ac->num_acks
6713 struct TransportReliabilityAckMessage *ack =
6714 (struct TransportReliabilityAckMessage *) buf;
6716
6717 ac->task = NULL;
6719 "Sending ACK with %u components to %s\n",
6720 ac->num_acks,
6721 GNUNET_i2s (&ac->target));
6722 GNUNET_assert (0 < ac->num_acks);
6724 ack->header.size =
6725 htons (sizeof(*ack)
6726 + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP));
6727 ack->ack_counter = htonl (ac->ack_counter += ac->num_acks);
6728 ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
6729 for (unsigned int i = 0; i < ac->num_acks; i++)
6730 {
6731 ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
6734 }
6735 /*route_control_message_without_fc (
6736 &ac->target,
6737 &ack->header,
6738 RMO_DV_ALLOWED);*/
6739 vl = lookup_virtual_link (&ac->target);
6740 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
6741 {
6743 vl,
6744 &ack->header,
6746 }
6747 else
6748 {
6749 /* Use route via neighbour */
6750 n = lookup_neighbour (&ac->target);
6751 if (NULL != n)
6753 n,
6754 &ack->header,
6755 RMO_NONE);
6756 }
6757 ac->num_acks = 0;
6760 ac);
6761}
6762
6763
6772static void
6774 const struct AcknowledgementUUIDP *ack_uuid,
6775 struct GNUNET_TIME_Absolute max_delay)
6776{
6777 struct AcknowledgementCummulator *ac;
6778
6780 "Scheduling ACK %s for transmission to %s\n",
6781 GNUNET_uuid2s (&ack_uuid->value),
6782 GNUNET_i2s (pid));
6784 if (NULL == ac)
6785 {
6787 ac->target = *pid;
6788 ac->min_transmission_time = max_delay;
6792 &ac->target,
6793 ac,
6795 }
6796 else
6797 {
6798 if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
6799 {
6800 /* must run immediately, ack buffer full! */
6802 }
6806 }
6809 ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
6810 ac->num_acks++;
6813 ac);
6814}
6815
6816
6821{
6826
6830 struct ReassemblyContext *rc;
6831};
6832
6833
6843static int
6844find_by_message_uuid (void *cls, uint32_t key, void *value)
6845{
6846 struct FindByMessageUuidContext *fc = cls;
6847 struct ReassemblyContext *rc = value;
6848
6849 (void) key;
6850 if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
6851 {
6852 fc->rc = rc;
6853 return GNUNET_NO;
6854 }
6855 return GNUNET_YES;
6856}
6857
6858
6866static void
6867handle_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
6868{
6869 struct CommunicatorMessageContext *cmc = cls;
6870 struct VirtualLink *vl;
6871 struct ReassemblyContext *rc;
6872 const struct GNUNET_MessageHeader *msg;
6873 uint16_t msize;
6874 uint16_t fsize;
6875 uint16_t frag_off;
6876 char *target;
6877 struct GNUNET_TIME_Relative cdelay;
6878 struct FindByMessageUuidContext fc;
6879
6880 vl = lookup_virtual_link (&cmc->im.sender);
6881 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6882 {
6883 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6884
6886 "No virtual link for %s to handle fragment\n",
6887 GNUNET_i2s (&cmc->im.sender));
6888 GNUNET_break (0);
6889 finish_cmc_handling (cmc);
6891 return;
6892 }
6893 if (NULL == vl->reassembly_map)
6894 {
6896 vl->reassembly_heap =
6901 vl);
6902 }
6903 msize = ntohs (fb->msg_size);
6904 fc.message_uuid = fb->msg_uuid;
6905 fc.rc = NULL;
6907 fb->msg_uuid.uuid,
6909 &fc);
6910 fsize = ntohs (fb->header.size) - sizeof(*fb);
6911 if (NULL == (rc = fc.rc))
6912 {
6913 rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */
6914 + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
6915 rc->msg_uuid = fb->msg_uuid;
6916 rc->virtual_link = vl;
6917 rc->msg_size = msize;
6918 rc->reassembly_timeout =
6922 rc,
6926 vl->reassembly_map,
6927 rc->msg_uuid.uuid,
6928 rc,
6930 target = (char *) &rc[1];
6931 rc->bitfield = (uint8_t *) (target + rc->msg_size);
6932 if (fsize != rc->msg_size)
6933 rc->msg_missing = rc->msg_size;
6934 else
6935 rc->msg_missing = 0;
6937 "Received fragment with size %u at offset %u/%u %u bytes missing from %s for NEW message %"
6938 PRIu64 "\n",
6939 fsize,
6940 ntohs (fb->frag_off),
6941 msize,
6942 rc->msg_missing,
6943 GNUNET_i2s (&cmc->im.sender),
6944 fb->msg_uuid.uuid);
6945 }
6946 else
6947 {
6948 target = (char *) &rc[1];
6950 "Received fragment at offset %u/%u from %s for message %u\n",
6951 ntohs (fb->frag_off),
6952 msize,
6953 GNUNET_i2s (&cmc->im.sender),
6954 (unsigned int) fb->msg_uuid.uuid);
6955 }
6956 if (msize != rc->msg_size)
6957 {
6958 GNUNET_break (0);
6959 finish_cmc_handling (cmc);
6960 return;
6961 }
6962
6963 /* reassemble */
6964 if (0 == fsize)
6965 {
6966 GNUNET_break (0);
6967 finish_cmc_handling (cmc);
6968 return;
6969 }
6970 frag_off = ntohs (fb->frag_off);
6971 if (frag_off + fsize > msize)
6972 {
6973 /* Fragment (plus fragment size) exceeds message size! */
6974 GNUNET_break_op (0);
6975 finish_cmc_handling (cmc);
6976 return;
6977 }
6978 memcpy (&target[frag_off], &fb[1], fsize);
6979 /* update bitfield and msg_missing */
6980 for (unsigned int i = frag_off; i < frag_off + fsize; i++)
6981 {
6982 if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
6983 {
6984 rc->bitfield[i / 8] |= (1 << (i % 8));
6985 rc->msg_missing--;
6986 }
6987 }
6988
6989 /* Compute cumulative ACK */
6991 cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
6992 if (0 == rc->msg_missing)
6993 cdelay = GNUNET_TIME_UNIT_ZERO;
6994 cummulative_ack (&cmc->im.sender,
6995 &fb->ack_uuid,
6998 /* is reassembly complete? */
6999 if (0 != rc->msg_missing)
7000 {
7001 finish_cmc_handling (cmc);
7002 return;
7003 }
7004 /* reassembly is complete, verify result */
7005 msg = (const struct GNUNET_MessageHeader *) &rc[1];
7006 if (ntohs (msg->size) != rc->msg_size)
7007 {
7008 GNUNET_break (0);
7010 finish_cmc_handling (cmc);
7011 return;
7012 }
7013 /* successful reassembly */
7015 "Fragment reassembly complete for message %u\n",
7016 (unsigned int) fb->msg_uuid.uuid);
7017 /* FIXME: check that the resulting msg is NOT a
7018 DV Box or Reliability Box, as that is NOT allowed! */
7019 cmc->mh = msg;
7021 /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
7022 en-route and we forget that we finished this reassembly immediately!
7023 -> keep around until timeout?
7024 -> shorten timeout based on ACK? */
7026}
7027
7028
7036static int
7037check_reliability_box (void *cls,
7038 const struct TransportReliabilityBoxMessage *rb)
7039{
7040 const struct GNUNET_MessageHeader *box = (const struct
7041 GNUNET_MessageHeader *) &rb[1];
7042 (void) cls;
7043
7045 "check_send_msg with size %u: inner msg type %u and size %u (%lu %lu)\n",
7046 ntohs (rb->header.size),
7047 ntohs (box->type),
7048 ntohs (box->size),
7049 sizeof (struct TransportReliabilityBoxMessage),
7050 sizeof (struct GNUNET_MessageHeader));
7052 return GNUNET_YES;
7053}
7054
7055
7063static void
7064handle_reliability_box (void *cls,
7065 const struct TransportReliabilityBoxMessage *rb)
7066{
7067 struct CommunicatorMessageContext *cmc = cls;
7068 const struct GNUNET_MessageHeader *inbox =
7069 (const struct GNUNET_MessageHeader *) &rb[1];
7070 struct GNUNET_TIME_Relative rtt;
7071
7073 "Received reliability box from %s with UUID %s of type %u\n",
7074 GNUNET_i2s (&cmc->im.sender),
7076 (unsigned int) ntohs (inbox->type));
7077 rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
7078 do not really have an RTT for the
7079 * incoming* queue (should we have
7080 the sender add it to the rb message?) */
7082 &cmc->im.sender,
7083 &rb->ack_uuid,
7084 (0 == ntohl (rb->ack_countdown))
7087 GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
7088 /* continue with inner message */
7089 /* FIXME: check that inbox is NOT a DV Box, fragment or another
7090 reliability box (not allowed!) */
7091 cmc->mh = inbox;
7093}
7094
7095
7104static void
7105update_pd_age (struct PerformanceData *pd, unsigned int age)
7106{
7107 unsigned int sage;
7108
7109 if (age == pd->last_age)
7110 return; /* nothing to do */
7111 sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
7112 for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
7113 {
7114 struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
7115
7116 the->bytes_sent = 0;
7117 the->bytes_received = 0;
7118 }
7119 pd->last_age = age;
7120}
7121
7122
7131static void
7133 struct GNUNET_TIME_Relative rtt,
7134 uint16_t bytes_transmitted_ok)
7135{
7136 uint64_t nval = rtt.rel_value_us;
7137 uint64_t oval = pd->aged_rtt.rel_value_us;
7138 unsigned int age = get_age ();
7139 struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
7140
7141 if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
7142 pd->aged_rtt = rtt;
7143 else
7144 pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
7145 update_pd_age (pd, age);
7146 the->bytes_received += bytes_transmitted_ok;
7147}
7148
7149
7157static void
7159 struct GNUNET_TIME_Relative rtt,
7160 uint16_t bytes_transmitted_ok)
7161{
7162 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
7163}
7164
7165
7173static void
7175 struct GNUNET_TIME_Relative rtt,
7176 uint16_t bytes_transmitted_ok)
7177{
7178 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
7179}
7180
7181
7189static void
7191{
7192 struct PendingMessage *pos;
7193
7195 "Complete transmission of message %" PRIu64 " %u\n",
7196 pm->logging_uuid,
7197 pm->pmt);
7198 switch (pm->pmt)
7199 {
7200 case PMT_CORE:
7202 /* Full message sent, we are done */
7204 return;
7205
7206 case PMT_FRAGMENT_BOX:
7207 /* Fragment sent over reliable channel */
7208 pos = pm->frag_parent;
7212 "pos frag_off %lu pos bytes_msg %lu pmt %u parent %u\n",
7213 (unsigned long) pos->frag_off,
7214 (unsigned long) pos->bytes_msg,
7215 pos->pmt,
7216 NULL == pos->frag_parent ? 1 : 0);
7217 /* check if subtree is done */
7218 while ((NULL == pos->head_frag) && (pos->frag_off == (pos->bytes_msg
7219 - sizeof(struct
7221 &&
7222 (NULL != pos->frag_parent))
7223 {
7224 pm = pos;
7225 pos = pm->frag_parent;
7226 if ((NULL == pos) && (PMT_DV_BOX == pm->pmt))
7227 {
7229 return;
7230 }
7231 else if (PMT_DV_BOX == pm->pmt)
7232 {
7234 return;
7235 }
7238 }
7239
7240 /* Was this the last applicable fragment? */
7241 if ((NULL == pos->head_frag) && (NULL == pos->frag_parent || PMT_DV_BOX ==
7242 pos->pmt) &&
7243 (pos->frag_off == pos->bytes_msg))
7245 return;
7246
7247 case PMT_DV_BOX:
7249 "Completed transmission of message %" PRIu64 " (DV Box)\n",
7250 pm->logging_uuid);
7251 if (NULL != pm->frag_parent)
7252 {
7253 pos = pm->frag_parent;
7255 pos->bpm = NULL;
7257 }
7258 else
7260 return;
7261 }
7262}
7263
7264
7272static void
7274 struct GNUNET_TIME_Relative ack_delay)
7275{
7276 struct GNUNET_TIME_Relative delay;
7277
7279 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
7280 if (NULL != pa->queue && 1 == pa->num_send)
7282 if (NULL != pa->dvh && 1 == pa->num_send)
7283 update_dvh_performance (pa->dvh, delay, pa->message_size);
7284 if (NULL != pa->pm)
7287}
7288
7289
7297static int
7298check_reliability_ack (void *cls,
7299 const struct TransportReliabilityAckMessage *ra)
7300{
7301 unsigned int n_acks;
7302
7303 (void) cls;
7304 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7305 / sizeof(struct TransportCummulativeAckPayloadP);
7306 if (0 == n_acks)
7307 {
7308 GNUNET_break_op (0);
7309 return GNUNET_SYSERR;
7310 }
7311 if ((ntohs (ra->header.size) - sizeof(*ra)) !=
7312 n_acks * sizeof(struct TransportCummulativeAckPayloadP))
7313 {
7314 GNUNET_break_op (0);
7315 return GNUNET_SYSERR;
7316 }
7317 return GNUNET_OK;
7318}
7319
7320
7328static void
7329handle_reliability_ack (void *cls,
7330 const struct TransportReliabilityAckMessage *ra)
7331{
7332 struct CommunicatorMessageContext *cmc = cls;
7333 const struct TransportCummulativeAckPayloadP *ack;
7334 unsigned int n_acks;
7335 uint32_t ack_counter;
7336
7337 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7338 / sizeof(struct TransportCummulativeAckPayloadP);
7339 ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
7340 for (unsigned int i = 0; i < n_acks; i++)
7341 {
7342 struct PendingAcknowledgement *pa =
7344 if (NULL == pa)
7345 {
7347 "Received ACK from %s with UUID %s which is unknown to us!\n",
7348 GNUNET_i2s (&cmc->im.sender),
7349 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7351 GST_stats,
7352 "# FRAGMENT_ACKS dropped, no matching pending message",
7353 1,
7354 GNUNET_NO);
7355 continue;
7356 }
7358 "Received ACK from %s with UUID %s\n",
7359 GNUNET_i2s (&cmc->im.sender),
7360 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7361 handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
7362 }
7363
7364 ack_counter = htonl (ra->ack_counter);
7365 (void) ack_counter; /* silence compiler warning for now */
7366 // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
7367 // (DV and/or Neighbour?)
7368 finish_cmc_handling (cmc);
7369}
7370
7371
7379static int
7381 void *cls,
7383{
7384 uint16_t size = ntohs (be->header.size) - sizeof(*be);
7385 const struct GNUNET_MessageHeader *inbox =
7386 (const struct GNUNET_MessageHeader *) &be[1];
7387 const char *is;
7388 uint16_t isize;
7389
7390 (void) cls;
7391 if (ntohs (inbox->size) >= size)
7392 {
7393 GNUNET_break_op (0);
7394 return GNUNET_SYSERR;
7395 }
7396 isize = ntohs (inbox->size);
7397 is = ((const char *) inbox) + isize;
7398 size -= isize;
7399 if ('\0' != is[size - 1])
7400 {
7401 GNUNET_break_op (0);
7402 return GNUNET_SYSERR;
7403 }
7404 return GNUNET_YES;
7405}
7406
7407
7416static void
7418 void *cls,
7420{
7421 struct CommunicatorMessageContext *cmc = cls;
7423 struct GNUNET_MQ_Envelope *env;
7424 struct TransportClient *tc;
7425 const struct GNUNET_MessageHeader *inbox =
7426 (const struct GNUNET_MessageHeader *) &be[1];
7427 uint16_t isize = ntohs (inbox->size);
7428 const char *target_communicator = ((const char *) inbox) + isize;
7429 char *sender;
7430 char *self;
7431
7432 GNUNET_asprintf (&sender,
7433 "%s",
7434 GNUNET_i2s (&cmc->im.sender));
7435 GNUNET_asprintf (&self,
7436 "%s",
7438
7439 /* Find client providing this communicator */
7440 for (tc = clients_head; NULL != tc; tc = tc->next)
7441 if ((CT_COMMUNICATOR == tc->type) &&
7442 (0 ==
7443 strcmp (tc->details.communicator.address_prefix, target_communicator)))
7444 break;
7445 if (NULL == tc)
7446 {
7447 char *stastr;
7448
7450 &stastr,
7451 "# Backchannel message dropped: target communicator `%s' unknown",
7452 target_communicator);
7454 GNUNET_free (stastr);
7455 finish_cmc_handling (cmc);
7456 return;
7457 }
7458 /* Finally, deliver backchannel message to communicator */
7460 "Delivering backchannel message from %s to %s of type %u to %s\n",
7461 sender,
7462 self,
7463 ntohs (inbox->type),
7464 target_communicator);
7466 cbi,
7467 isize,
7469 cbi->pid = cmc->im.sender;
7470 memcpy (&cbi[1], inbox, isize);
7471 GNUNET_MQ_send (tc->mq, env);
7472 finish_cmc_handling (cmc);
7473}
7474
7475
7485static void
7486path_cleanup_cb (void *cls)
7487{
7488 struct DistanceVector *dv = cls;
7489 struct DistanceVectorHop *pos;
7490
7491 dv->timeout_task = NULL;
7492 while (NULL != (pos = dv->dv_head))
7493 {
7494 GNUNET_assert (dv == pos->dv);
7496 break;
7498 }
7499 if (NULL == pos)
7500 {
7501 free_dv_route (dv);
7502 return;
7503 }
7504 dv->timeout_task =
7506}
7507
7508
7509static void
7511{
7512
7513 const struct GNUNET_PeerIdentity target = vl->target;
7514
7515
7517 {
7518 struct RingBufferEntry *ring_buffer_copy[RING_BUFFER_SIZE];
7519 unsigned int tail = GNUNET_YES == is_ring_buffer_full ? ring_buffer_head :
7520 0;
7521 unsigned int head = GNUNET_YES == is_ring_buffer_full ? RING_BUFFER_SIZE :
7524 struct CommunicatorMessageContext *cmc;
7525 struct RingBufferEntry *rbe;
7526 struct GNUNET_MessageHeader *mh;
7527
7529 "Sending from ring buffer, which has %u items\n",
7530 head);
7531
7532 ring_buffer_head = 0;
7533 for (unsigned int i = 0; i < head; i++)
7534 {
7535 rbe = ring_buffer[(i + tail) % RING_BUFFER_SIZE];
7536 cmc = rbe->cmc;
7537 mh = rbe->mh;
7538
7539 im = cmc->im;
7540 // mh = cmc->mh;
7542 "Sending message of type %u to ring buffer target %s using vl target %s index %u\n",
7543 mh->type,
7544 GNUNET_i2s (&im.sender),
7545 GNUNET_i2s2 (&target),
7546 (i + tail) % RING_BUFFER_SIZE);
7547 if (0 == GNUNET_memcmp (&target, &im.sender))
7548 {
7550 "Finish handling message of type %u and size %u\n",
7551 (unsigned int) ntohs (mh->type),
7552 (unsigned int) ntohs (mh->size));
7554 GNUNET_free (mh);
7555 GNUNET_free (rbe->cmc);
7556 GNUNET_free (rbe);
7557 }
7558 else
7559 {
7560 ring_buffer_copy[ring_buffer_head] = rbe;
7562 }
7563 }
7564
7567 {
7569 }
7570
7571 for (unsigned int i = 0; i < ring_buffer_head; i++)
7572 {
7573 ring_buffer[i] = ring_buffer_copy[i];
7575 "ring_buffer_copy[i]->mh->type for i %u %u\n",
7576 i,
7577 ring_buffer_copy[i]->mh->type);
7579 "ring_buffer[i]->mh->type for i %u %u\n",
7580 i,
7581 ring_buffer[i]->mh->type);
7582 }
7583
7585 "%u items still in ring buffer\n",
7587 }
7588
7590 {
7591 struct PendingMessage *ring_buffer_dv_copy[RING_BUFFER_SIZE];
7592 struct PendingMessage *pm;
7593 unsigned int tail = GNUNET_YES == is_ring_buffer_dv_full ?
7595 0;
7596 unsigned int head = GNUNET_YES == is_ring_buffer_dv_full ?
7599
7601 "Sending from ring buffer dv, which has %u items\n",
7602 head);
7603
7605 for (unsigned int i = 0; i < head; i++)
7606 {
7607 pm = ring_buffer_dv[(i + tail) % RING_BUFFER_SIZE];
7608
7610 "Sending to ring buffer target %s using vl target %s\n",
7611 GNUNET_i2s (&pm->target),
7612 GNUNET_i2s2 (&target));
7613 if (0 == GNUNET_memcmp (&target, &pm->target))
7614 {
7616 "Adding PendingMessage to vl, checking transmission.\n");
7617 pm->vl = vl;
7621 pm);
7622
7624 }
7625 else
7626 {
7627 ring_buffer_dv_copy[ring_buffer_dv_head] = pm;
7629 }
7630 }
7631
7633 {
7635 }
7636
7637 for (unsigned int i = 0; i < ring_buffer_dv_head; i++)
7638 ring_buffer_dv[i] = ring_buffer_dv_copy[i];
7639
7641 "%u items still in ring buffer dv.\n",
7643
7644 }
7645}
7646
7647
7655static void
7657{
7658 struct DistanceVector *dv = hop->dv;
7659 struct VirtualLink *vl;
7660
7661 vl = lookup_virtual_link (&dv->target);
7662 if (NULL == vl)
7663 {
7664
7665 vl = GNUNET_new (struct VirtualLink);
7667 "Creating new virtual link %p to %s using DV!\n",
7668 vl,
7669 GNUNET_i2s (&dv->target));
7670 vl->burst_addr = NULL;
7671 vl->confirmed = GNUNET_YES;
7672 vl->message_uuid_ctr =
7674 vl->target = dv->target;
7680 links,
7681 &vl->target,
7682 vl,
7684 vl->dv = dv;
7685 dv->vl = vl;
7686 vl->visibility_task =
7689 /* We lacked a confirmed connection to the target
7690 before, so tell CORE about it (finally!) */
7693 }
7694 else
7695 {
7696 /* Link was already up, remember dv is also now available and we are done */
7697 vl->dv = dv;
7698 dv->vl = vl;
7699 if (GNUNET_NO == vl->confirmed)
7700 {
7701 vl->confirmed = GNUNET_YES;
7702 vl->visibility_task =
7705 /* We lacked a confirmed connection to the target
7706 before, so tell CORE about it (finally!) */
7709 }
7710 else
7712 "Virtual link to %s could now also use DV!\n",
7713 GNUNET_i2s (&dv->target));
7714 }
7715}
7716
7717
7743static int
7744learn_dv_path (const struct GNUNET_PeerIdentity *path,
7745 unsigned int path_len,
7746 struct GNUNET_TIME_Relative network_latency,
7747 struct GNUNET_TIME_Absolute path_valid_until)
7748{
7749 struct DistanceVectorHop *hop;
7750 struct DistanceVector *dv;
7751 struct Neighbour *next_hop;
7752 unsigned int shorter_distance;
7753
7754 if (path_len < 3)
7755 {
7756 /* what a boring path! not allowed! */
7757 GNUNET_break (0);
7758 return GNUNET_SYSERR;
7759 }
7760 GNUNET_assert (0 == GNUNET_memcmp (GST_my_identity, &path[0]));
7761 next_hop = lookup_neighbour (&path[1]);
7762 if (NULL == next_hop)
7763 {
7764 /* next hop must be a neighbour, otherwise this whole thing is useless! */
7765 GNUNET_break (0);
7766 return GNUNET_SYSERR;
7767 }
7768 for (unsigned int i = 2; i < path_len; i++)
7769 {
7770 struct Neighbour *n = lookup_neighbour (&path[i]);
7771 struct GNUNET_TIME_Absolute q_timeout;
7772
7773 if (NULL != n)
7774 {
7775 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
7776 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
7777 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
7779 "remaining %lu to %s\n",
7780 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout)
7781 .rel_value_us,
7782 GNUNET_i2s (&n->pid));
7783 if (0 != GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
7784 {
7785 /* Useless path: we have a direct active connection to some hop
7786 in the middle of the path, so this one is not even
7787 terribly useful for redundancy */
7789 "Path of %u hops useless: directly link to hop %u (%s)\n",
7790 path_len,
7791 i,
7792 GNUNET_i2s (&path[i]));
7794 "# Useless DV path ignored: hop is neighbour",
7795 1,
7796 GNUNET_NO);
7797 return GNUNET_SYSERR;
7798 }
7799 }
7800 }
7801 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
7802 if (NULL == dv)
7803 {
7804 dv = GNUNET_new (struct DistanceVector);
7805 dv->target = path[path_len - 1];
7808 dv);
7811 dv_routes,
7812 &dv->target,
7813 dv,
7815 }
7816 /* Check if we have this path already! */
7817 shorter_distance = 0;
7818 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
7819 pos = pos->next_dv)
7820 {
7821 if (pos->distance < path_len - 3)
7822 shorter_distance++;
7823 /* Note that the distances in 'pos' excludes us (path[0]),
7824 the next_hop (path[1]) and the target so we need to subtract three
7825 and check next_hop explicitly */
7826 if ((pos->distance == path_len - 3) && (pos->next_hop == next_hop))
7827 {
7828 int match = GNUNET_YES;
7829
7830 for (unsigned int i = 0; i < pos->distance; i++)
7831 {
7832 if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
7833 {
7834 match = GNUNET_NO;
7835 break;
7836 }
7837 }
7838 if (GNUNET_YES == match)
7839 {
7840 struct GNUNET_TIME_Relative last_timeout;
7841
7842 /* Re-discovered known path, update timeout */
7844 "# Known DV path refreshed",
7845 1,
7846 GNUNET_NO);
7847 last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
7848 pos->timeout =
7850 pos->path_valid_until =
7851 GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
7852 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
7853 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
7854 if (0 <
7857 if (last_timeout.rel_value_us <
7860 .rel_value_us)
7861 {
7862 /* Some peer send DV learn messages too often, we are learning
7863 the same path faster than it would be useful; do not forward! */
7865 "Rediscovered path too quickly, not forwarding further\n")
7866 ;
7867 return GNUNET_NO;
7868 }
7870 "Refreshed known path to %s valid until %s, forwarding further\n",
7871 GNUNET_i2s (&dv->target),
7873 pos->path_valid_until));
7874 return GNUNET_YES;
7875 }
7876 }
7877 }
7878 /* Count how many shorter paths we have (incl. direct
7879 neighbours) before simply giving up on this one! */
7880 if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
7881 {
7882 /* We have a shorter path already! */
7884 "Have many shorter DV paths %s, not forwarding further\n",
7885 GNUNET_i2s (&dv->target));
7886 return GNUNET_NO;
7887 }
7888 /* create new DV path entry */
7890 "Discovered new DV path to %s valid until %s\n",
7891 GNUNET_i2s (&dv->target),
7892 GNUNET_STRINGS_absolute_time_to_string (path_valid_until));
7893 hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
7894 + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7895 hop->next_hop = next_hop;
7896 hop->dv = dv;
7897 hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
7898 memcpy (&hop[1],
7899 &path[2],
7900 sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7902 hop->path_valid_until = path_valid_until;
7903 hop->distance = path_len - 3;
7904 hop->pd.aged_rtt = network_latency;
7905 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
7907 next_hop->dv_head,
7908 next_hop->dv_tail,
7909 hop);
7910 if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
7912 return GNUNET_YES;
7913}
7914
7915
7923static int
7924check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
7925{
7926 uint16_t size = ntohs (dvl->header.size);
7927 uint16_t num_hops = ntohs (dvl->num_hops);
7928 const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
7929
7930 (void) cls;
7931 if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
7932 {
7933 GNUNET_break_op (0);
7934 return GNUNET_SYSERR;
7935 }
7936 if (num_hops > MAX_DV_HOPS_ALLOWED)
7937 {
7938 GNUNET_break_op (0);
7939 return GNUNET_SYSERR;
7940 }
7941 for (unsigned int i = 0; i < num_hops; i++)
7942 {
7943 if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
7944 {
7945 GNUNET_break_op (0);
7946 return GNUNET_SYSERR;
7947 }
7948 if (0 == GNUNET_memcmp (GST_my_identity, &hops[i].hop))
7949 {
7950 GNUNET_break_op (0);
7951 return GNUNET_SYSERR;
7952 }
7953 }
7954 return GNUNET_YES;
7955}
7956
7957
7958struct SignDhpCls
7959{
7960 struct DVPathEntryP *dhops;
7961 uint16_t nhops;
7962 const struct GNUNET_PeerIdentity *next_hop;
7964 struct PilsRequest *pr;
7965};
7966
7967
7968static void
7969sign_dhp_cp (void *cls,
7970 const struct GNUNET_PeerIdentity *pid,
7971 const struct GNUNET_CRYPTO_EddsaSignature *sig)
7972{
7973 struct SignDhpCls *sign_dhp_cls = cls;
7974 struct VirtualLink *vl;
7975 struct DVPathEntryP *dhops = sign_dhp_cls->dhops;
7976 uint16_t nhops = sign_dhp_cls->nhops;
7977 const struct GNUNET_PeerIdentity *next_hop = sign_dhp_cls->next_hop;
7978 struct TransportDVLearnMessage *fwd = sign_dhp_cls->fwd;
7979 struct Neighbour *n;
7980
7981 sign_dhp_cls->pr->op = NULL;
7984 sign_dhp_cls->pr);
7985 GNUNET_free (sign_dhp_cls->pr);
7986 dhops[nhops].hop_sig = *sig;
7987
7988 /*route_control_message_without_fc (next_hop,
7989 &fwd->header,
7990 RMO_UNCONFIRMED_ALLOWED);*/
7991 vl = lookup_virtual_link (next_hop);
7992 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
7993 {
7995 &fwd->header,
7997 }
7998 else
7999 {
8000 /* Use route via neighbour */
8001 n = lookup_neighbour (next_hop);
8002 if (NULL != n)
8004 n,
8005 &fwd->header,
8007 }
8008 GNUNET_free (sign_dhp_cls);
8009}
8010
8011
8023static void
8024forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop,
8025 const struct TransportDVLearnMessage *msg,
8026 uint16_t bi_history,
8027 uint16_t nhops,
8028 const struct DVPathEntryP *hops,
8029 struct GNUNET_TIME_Absolute in_time)
8030{
8031 struct DVPathEntryP *dhops;
8032 char buf[sizeof(struct TransportDVLearnMessage)
8033 + (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
8034 struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
8035 struct GNUNET_TIME_Relative nnd;
8036
8037 /* compute message for forwarding */
8039 "Forwarding DV learn message originating from %s to %s\n",
8040 GNUNET_i2s (&msg->initiator),
8041 GNUNET_i2s2 (next_hop));
8044 fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
8045 + (nhops + 1) * sizeof(struct DVPathEntryP));
8046 fwd->num_hops = htons (nhops + 1);
8047 fwd->bidirectional = htons (bi_history);
8050 msg->non_network_delay));
8052 fwd->init_sig = msg->init_sig;
8053 fwd->initiator = msg->initiator;
8054 fwd->challenge = msg->challenge;
8055 fwd->monotonic_time = msg->monotonic_time;
8056 dhops = (struct DVPathEntryP *) &fwd[1];
8057 GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
8058 dhops[nhops].hop = *GST_my_identity;
8059 {
8060 struct DvHopPS dhp = {
8062 .purpose.size = htonl (sizeof(dhp)),
8063 .pred = (0 == nhops) ? msg->initiator : dhops[nhops - 1].hop,
8064 .succ = *next_hop,
8066 };
8067 struct SignDhpCls *sign_dhp_cls = GNUNET_new (struct SignDhpCls);
8068 sign_dhp_cls->dhops = dhops;
8069 sign_dhp_cls->nhops = nhops;
8070 sign_dhp_cls->next_hop = next_hop;
8071 sign_dhp_cls->fwd = fwd;
8072 sign_dhp_cls->pr = GNUNET_new (struct PilsRequest);
8075 sign_dhp_cls->pr);
8076 sign_dhp_cls->pr->op =
8078 &dhp.purpose,
8080 sign_dhp_cls);
8081 }
8082}
8083
8084
8094static int
8096 struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
8097 const struct GNUNET_PeerIdentity *init,
8098 const struct GNUNET_CRYPTO_ChallengeNonceP *challenge,
8099 const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
8100{
8101 struct DvInitPS ip = { .purpose.purpose = htonl (
8103 .purpose.size = htonl (sizeof(ip)),
8104 .monotonic_time = sender_monotonic_time,
8105 .challenge = *challenge };
8106
8107 if (
8108 GNUNET_OK !=
8110 &ip,
8111 init_sig,
8112 &init->public_key))
8113 {
8114 GNUNET_break_op (0);
8115 return GNUNET_SYSERR;
8116 }
8117 return GNUNET_OK;
8118}
8119
8120
8125{
8129 const struct TransportDVLearnMessage *dvl;
8130
8134 const struct DVPathEntryP *hops;
8135
8140
8145
8149 unsigned int num_eligible;
8150
8154 unsigned int num_selections;
8155
8159 uint16_t nhops;
8160
8164 uint16_t bi_history;
8165};
8166
8167
8176static int
8177dv_neighbour_selection (void *cls,
8178 const struct GNUNET_PeerIdentity *pid,
8179 void *value)
8180{
8181 struct NeighbourSelectionContext *nsc = cls;
8182
8183 (void) value;
8184 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8185 return GNUNET_YES; /* skip initiator */
8186 for (unsigned int i = 0; i < nsc->nhops; i++)
8187 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8188 return GNUNET_YES;
8189 /* skip peers on path */
8190 nsc->num_eligible++;
8191 return GNUNET_YES;
8192}
8193
8194
8205static int
8206dv_neighbour_transmission (void *cls,
8207 const struct GNUNET_PeerIdentity *pid,
8208 void *value)
8209{
8210 struct NeighbourSelectionContext *nsc = cls;
8211
8213 "transmission %s\n",
8214 GNUNET_i2s (pid));
8215 (void) value;
8216 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8217 return GNUNET_YES; /* skip initiator */
8218 for (unsigned int i = 0; i < nsc->nhops; i++)
8219 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8220 return GNUNET_YES;
8221 /* skip peers on path */
8222 for (unsigned int i = 0; i < nsc->num_selections; i++)
8223 {
8224 if (nsc->selections[i] == nsc->num_eligible)
8225 {
8227 nsc->dvl,
8228 nsc->bi_history,
8229 nsc->nhops,
8230 nsc->hops,
8231 nsc->in_time);
8232 break;
8233 }
8234 }
8235 nsc->num_eligible++;
8236 return GNUNET_YES;
8237}
8238
8239
8283static unsigned int
8284calculate_fork_degree (unsigned int hops_taken,
8285 unsigned int neighbour_count,
8286 unsigned int eligible_count)
8287{
8288 double target_total = 50.0; /* FIXME: use LOG(NSE)? */
8289 double eligible_ratio =
8290 ((double) eligible_count) / ((double) neighbour_count);
8291 double boost_factor = eligible_ratio * eligible_ratio;
8292 unsigned int rnd;
8293 double left;
8294
8295 if (hops_taken >= 64)
8296 {
8297 GNUNET_break (0);
8298 return 0; /* precaution given bitshift below */
8299 }
8300 for (unsigned int i = 1; i < hops_taken; i++)
8301 {
8302 /* For each hop, subtract the expected number of targets
8303 reached at distance d (so what remains divided by 2^d) */
8304 target_total -= (target_total * boost_factor / (1LLU << i));
8305 }
8306 rnd =
8307 (unsigned int) floor (target_total * boost_factor / (1LLU << hops_taken));
8308 /* round up or down probabilistically depending on how close we were
8309 when floor()ing to rnd */
8310 left = target_total - (double) rnd;
8311 if (UINT32_MAX * left >
8313 rnd++; /* round up */
8315 "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
8316 hops_taken,
8317 rnd,
8318 eligible_count,
8319 neighbour_count);
8320 return rnd;
8321}
8322
8323
8330static void
8331neighbour_store_dvmono_cb (void *cls, int success)
8332{
8333 struct Neighbour *n = cls;
8334
8335 n->sc = NULL;
8336 if (GNUNET_YES != success)
8338 "Failed to store other peer's monotonic time in peerstore!\n");
8339}
8340
8341
8342static struct GNUNET_TIME_Relative
8344{
8345 struct GNUNET_TIME_Relative host_latency_sum;
8346 struct GNUNET_TIME_Relative latency;
8347 struct GNUNET_TIME_Relative network_latency;
8348 uint16_t nhops = ntohs (dvl->num_hops);;
8349
8350 /* We initiated this, learn the forward path! */
8351 host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
8352
8353 // Need also something to lookup initiation time
8354 // to compute RTT! -> add RTT argument here?
8356 dvl->monotonic_time));
8357 GNUNET_assert (latency.rel_value_us >= host_latency_sum.rel_value_us);
8358 // latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
8359 // (based on dvl->challenge, we can identify time of origin!)
8360
8361 network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
8362 /* assumption: latency on all links is the same */
8363 network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
8364
8365 return network_latency;
8366}
8367
8368
8376static void
8377handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
8378{
8379 struct CommunicatorMessageContext *cmc = cls;
8381 int bi_hop;
8382 uint16_t nhops;
8383 uint16_t bi_history;
8384 const struct DVPathEntryP *hops;
8385 int do_fwd;
8386 int did_initiator;
8387 struct GNUNET_TIME_Absolute in_time;
8388 struct Neighbour *n;
8389
8390 nhops = ntohs (dvl->num_hops); /* 0 = sender is initiator */
8391 bi_history = ntohs (dvl->bidirectional);
8392 hops = (const struct DVPathEntryP *) &dvl[1];
8393 if (0 == nhops)
8394 {
8395 /* sanity check */
8396 if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
8397 {
8398 GNUNET_break (0);
8399 finish_cmc_handling (cmc);
8400 return;
8401 }
8402 }
8403 else
8404 {
8406 "handle dv learn message last hop %s\n",
8407 GNUNET_i2s (&hops[nhops - 1].hop));
8408 /* sanity check */
8409 if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
8410 {
8411 GNUNET_break (0);
8412 finish_cmc_handling (cmc);
8413 return;
8414 }
8415 }
8416
8418 cc = cmc->tc->details.communicator.cc;
8419 bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
8420 cc); // FIXME: add bi-directional flag to cc?
8421 in_time = GNUNET_TIME_absolute_get ();
8422
8423 /* continue communicator here, everything else can happen asynchronous! */
8424 finish_cmc_handling (cmc);
8425
8426 n = lookup_neighbour (&dvl->initiator);
8427 if (NULL != n)
8428 {
8429 if ((n->dv_monotime_available == GNUNET_YES) &&
8432 {
8434 "DV learn from %s discarded due to time travel",
8435 GNUNET_i2s (&dvl->initiator));
8437 "# DV learn discarded due to time travel",
8438 1,
8439 GNUNET_NO);
8440 return;
8441 }
8443 &dvl->initiator,
8444 &dvl->challenge,
8445 &dvl->init_sig))
8446 {
8448 "DV learn signature from %s invalid\n",
8449 GNUNET_i2s (&dvl->initiator));
8450 GNUNET_break_op (0);
8451 return;
8452 }
8455 {
8456 if (NULL != n->sc)
8457 {
8459 "store cancel\n");
8461 }
8462 n->sc =
8464 "transport",
8465 &dvl->initiator,
8467 &dvl->monotonic_time,
8468 sizeof(dvl->monotonic_time),
8472 n);
8473 }
8474 }
8475 /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
8476 If signature verification load too high, implement random drop strategy */
8477 for (unsigned int i = 0; i < nhops; i++)
8478 {
8479 struct DvHopPS dhp = { .purpose.purpose =
8481 .purpose.size = htonl (sizeof(dhp)),
8482 .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
8483 .succ = (nhops == i + 1) ? *GST_my_identity
8484 : hops[i + 1].hop,
8485 .challenge = dvl->challenge };
8486
8487 if (GNUNET_OK !=
8489 &dhp,
8490 &hops[i].hop_sig,
8491 &hops[i].hop.public_key))
8492 {
8494 "DV learn from %s signature of hop %u invalid\n",
8495 GNUNET_i2s (&dvl->initiator),
8496 i);
8498 "signature of hop %s invalid\n",
8499 GNUNET_i2s (&hops[i].hop));
8501 "pred %s\n",
8502 GNUNET_i2s (&dhp.pred));
8504 "succ %s\n",
8505 GNUNET_i2s (&dhp.succ));
8507 "hash %s\n",
8508 GNUNET_sh2s (&dhp.challenge.value));
8509 GNUNET_break_op (0);
8510 return;
8511 }
8512 }
8513 if (GNUNET_EXTRA_LOGGING > 0)
8514 {
8515 char *path;
8516
8517 path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
8518 for (unsigned int i = 0; i < nhops; i++)
8519 {
8520 char *tmp;
8521
8522 GNUNET_asprintf (&tmp,
8523 "%s%s%s",
8524 path,
8525 (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
8526 GNUNET_i2s (&hops[i].hop));
8527 GNUNET_free (path);
8528 path = tmp;
8529 }
8531 "Received DVInit via %s%s%s\n",
8532 path,
8533 bi_hop ? "<->" : "-->",
8535 GNUNET_free (path);
8536 }
8537 do_fwd = GNUNET_YES;
8538 if (0 == GNUNET_memcmp (GST_my_identity, &dvl->initiator))
8539 {
8540 struct GNUNET_PeerIdentity path[nhops + 1];
8541 struct GNUNET_TIME_Relative network_latency;
8542
8543 /* We initiated this, learn the forward path! */
8544 path[0] = *GST_my_identity;
8545 path[1] = hops[0].hop;
8546
8547 network_latency = get_network_latency (dvl);
8548
8549 for (unsigned int i = 2; i <= nhops; i++)
8550 {
8551 struct GNUNET_TIME_Relative ilat;
8552
8553 /* assumption: linear latency increase per hop */
8554 ilat = GNUNET_TIME_relative_multiply (network_latency, i);
8555 path[i] = hops[i - 1].hop;
8557 "Learned path with %u hops to %s with latency %s\n",
8558 i,
8559 GNUNET_i2s (&path[i]),
8561 learn_dv_path (path,
8562 i + 1,
8563 ilat,
8566 }
8567 /* as we initiated, do not forward again (would be circular!) */
8568 do_fwd = GNUNET_NO;
8569 return;
8570 }
8571 if (bi_hop)
8572 {
8573 /* last hop was bi-directional, we could learn something here! */
8574 struct GNUNET_PeerIdentity path[nhops + 2];
8575 struct GNUNET_TIME_Relative ilat;
8576 struct GNUNET_TIME_Relative network_latency;
8577
8578 path[0] = *GST_my_identity;
8579 path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
8580 for (unsigned int i = 0; i < nhops; i++)
8581 {
8582 int iret;
8583
8584 if (0 == (bi_history & (1 << i)))
8585 break; /* i-th hop not bi-directional, stop learning! */
8586 if (i == nhops - 1)
8587 {
8588 path[i + 2] = dvl->initiator;
8589 }
8590 else
8591 {
8592 path[i + 2] = hops[nhops - i - 2].hop;
8593 }
8594
8596 "Learned inverse path with %u hops to %s\n",
8597 i + 2,
8598 GNUNET_i2s (&path[i + 2]));
8599 network_latency = get_network_latency (dvl);
8600 ilat = GNUNET_TIME_relative_multiply (network_latency, i + 2);
8601 iret = learn_dv_path (path,
8602 i + 3,
8603 ilat,
8606 if (GNUNET_SYSERR == iret)
8607 {
8608 /* path invalid or too long to be interesting for US, thus should also
8609 not be interesting to our neighbours, cut path when forwarding to
8610 'i' hops, except of course for the one that goes back to the
8611 initiator */
8613 "# DV learn not forwarded due invalidity of path",
8614 1,
8615 GNUNET_NO);
8616 do_fwd = GNUNET_NO;
8617 break;
8618 }
8619 if ((GNUNET_NO == iret) && (nhops == i + 1))
8620 {
8621 /* we have better paths, and this is the longest target,
8622 so there cannot be anything interesting later */
8624 "# DV learn not forwarded, got better paths",
8625 1,
8626 GNUNET_NO);
8627 do_fwd = GNUNET_NO;
8628 break;
8629 }
8630 }
8631 }
8632 if (MAX_DV_HOPS_ALLOWED == nhops)
8633 {
8634 /* At limit, we're out of here! */
8635 return;
8636 }
8637
8638 /* Forward to initiator, if path non-trivial and possible */
8639 bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
8640 did_initiator = GNUNET_NO;
8641 if ((1 <= nhops) &&
8642 (GNUNET_YES ==
8644 {
8645 /* send back to origin! */
8647 "Sending DVL back to initiator %s\n",
8648 GNUNET_i2s (&dvl->initiator));
8649 forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
8650 did_initiator = GNUNET_YES;
8651 }
8652 /* We forward under two conditions: either we still learned something
8653 ourselves (do_fwd), or the path was darn short and thus the initiator is
8654 likely to still be very interested in this (and we did NOT already
8655 send it back to the initiator) */
8656 if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
8657 (GNUNET_NO == did_initiator)))
8658 {
8659 /* Pick random neighbours that are not yet on the path */
8660 struct NeighbourSelectionContext nsc;
8661 unsigned int n_cnt;
8662
8664 nsc.nhops = nhops;
8665 nsc.dvl = dvl;
8666 nsc.bi_history = bi_history;
8667 nsc.hops = hops;
8668 nsc.in_time = in_time;
8669 nsc.num_eligible = 0;
8672 &nsc);
8673 if (0 == nsc.num_eligible)
8674 return; /* done here, cannot forward to anyone else */
8676 nsc.num_selections =
8679 "Forwarding DVL to %u other peers\n",
8680 nsc.num_selections);
8681 for (unsigned int i = 0; i < nsc.num_selections; i++)
8682 nsc.selections[i] =
8683 (nsc.num_selections == n_cnt)
8684 ? i /* all were selected, avoid collisions by chance */
8686 nsc.num_eligible = 0;
8689 &nsc);
8690 }
8691}
8692
8693
8701static int
8702check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
8703{
8704 uint16_t size = ntohs (dvb->header.size);
8705 uint16_t num_hops = ntohs (dvb->num_hops);
8706 const struct GNUNET_PeerIdentity *hops =
8707 (const struct GNUNET_PeerIdentity *) &dvb[1];
8708
8709 (void) cls;
8710 if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
8711 + sizeof(struct GNUNET_MessageHeader))
8712 {
8713 GNUNET_break_op (0);
8714 return GNUNET_SYSERR;
8715 }
8716 /* This peer must not be on the path */
8717 for (unsigned int i = 0; i < num_hops; i++)
8718 if (0 == GNUNET_memcmp (&hops[i], GST_my_identity))
8719 {
8720 GNUNET_break_op (0);
8721 return GNUNET_SYSERR;
8722 }
8723 return GNUNET_YES;
8724}
8725
8726
8739static void
8740forward_dv_box (struct Neighbour *next_hop,
8741 struct TransportDVBoxMessage *hdr,
8742 uint16_t total_hops,
8743 uint16_t num_hops,
8744 const struct GNUNET_PeerIdentity *hops,
8745 const void *enc_payload,
8746 uint16_t enc_payload_size)
8747{
8748 struct VirtualLink *vl = next_hop->vl;
8749 struct PendingMessage *pm;
8750 size_t msg_size = sizeof(struct TransportDVBoxMessage)
8751 + num_hops * sizeof(struct GNUNET_PeerIdentity)
8752 + enc_payload_size;
8753 char *buf;
8754 char msg_buf[msg_size] GNUNET_ALIGN;
8755 struct GNUNET_PeerIdentity *dhops;
8756
8757 hdr->num_hops = htons (num_hops);
8758 hdr->total_hops = htons (total_hops);
8759 hdr->header.size = htons (msg_size);
8760 memcpy (msg_buf, hdr, sizeof(*hdr));
8761 dhops = (struct GNUNET_PeerIdentity *) &msg_buf[sizeof(struct
8763 ;
8764 memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
8765 memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
8766
8767 if (GNUNET_YES == ntohs (hdr->without_fc))
8768 {
8770 "Forwarding control message (payload size %u) in DV Box to next hop %s (%u/%u) \n",
8771 enc_payload_size,
8772 GNUNET_i2s (&next_hop->pid),
8773 (unsigned int) num_hops,
8774 (unsigned int) total_hops);
8775 route_via_neighbour (next_hop, (const struct
8776 GNUNET_MessageHeader *) msg_buf,
8778 }
8779 else
8780 {
8781 pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
8783 "2 created pm %p storing vl %p \n",
8784 pm,
8785 vl);
8786 pm->pmt = PMT_DV_BOX;
8787 pm->vl = vl;
8788 pm->target = next_hop->pid;
8790 pm->logging_uuid = logging_uuid_gen++;
8792 pm->bytes_msg = msg_size;
8793 buf = (char *) &pm[1];
8794 memcpy (buf, msg_buf, msg_size);
8795
8797 "Created pending message %" PRIu64
8798 " for DV Box with next hop %s (%u/%u)\n",
8799 pm->logging_uuid,
8800 GNUNET_i2s (&next_hop->pid),
8801 (unsigned int) num_hops,
8802 (unsigned int) total_hops);
8803
8804 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
8805 {
8807 vl->pending_msg_head,
8808 vl->pending_msg_tail,
8809 pm);
8810
8812 }
8813 else
8814 {
8816 "The virtual link is not ready for forwarding a DV Box with payload, storing PendingMessage in ring buffer.\n");
8817
8819 {
8821
8822 GNUNET_free (pm_old);
8823 }
8826 {
8829 }
8830 else
8832
8834 "%u items stored in DV ring buffer\n",
8837 }
8838 }
8839}
8840
8841
8847static void
8848free_backtalker (struct Backtalker *b)
8849{
8850 if (NULL != b->get)
8851 {
8853 b->get = NULL;
8854 GNUNET_assert (NULL != b->cmc);
8856 b->cmc = NULL;
8857 }
8858 if (NULL != b->task)
8859 {
8861 b->task = NULL;
8862 }
8863 if (NULL != b->sc)
8864 {
8866 "store cancel\n");
8868 b->sc = NULL;
8869 }
8871 "Removing backtalker for %s\n",
8872 GNUNET_i2s (&b->pid));
8874 GNUNET_YES ==
8876 GNUNET_free (b);
8877}
8878
8879
8888static int
8889free_backtalker_cb (void *cls,
8890 const struct GNUNET_PeerIdentity *pid,
8891 void *value)
8892{
8893 struct Backtalker *b = value;
8894
8895 (void) cls;
8896 (void) pid;
8897 free_backtalker (b);
8898 return GNUNET_OK;
8899}
8900
8901
8907static void
8908backtalker_timeout_cb (void *cls)
8909{
8910 struct Backtalker *b = cls;
8911
8913 "backtalker timeout.\n");
8914 b->task = NULL;
8916 {
8918 return;
8919 }
8920 GNUNET_assert (NULL == b->sc);
8921 free_backtalker (b);
8922}
8923
8924
8933static void
8934backtalker_monotime_cb (void *cls,
8935 const struct GNUNET_PEERSTORE_Record *record,
8936 const char *emsg)
8937{
8938 struct Backtalker *b = cls;
8939 struct GNUNET_TIME_AbsoluteNBO *mtbe;
8940 struct GNUNET_TIME_Absolute mt;
8941
8942 (void) emsg;
8943 if (NULL == record)
8944 {
8945 /* we're done with #backtalker_monotime_cb() invocations,
8946 continue normal processing */
8947 b->get = NULL;
8948 GNUNET_assert (NULL != b->cmc);
8949 b->cmc->mh = (const struct GNUNET_MessageHeader *) &b[1];
8950 if (0 != b->body_size)
8952 else
8954 b->cmc = NULL;
8955 return;
8956 }
8957 if (sizeof(*mtbe) != record->value_size)
8958 {
8960 GNUNET_break (0);
8961 return;
8962 }
8963 mtbe = record->value;
8964 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
8965 if (mt.abs_value_us > b->monotonic_time.abs_value_us)
8966 {
8968 "Backtalker message from %s dropped, monotime in the past\n",
8969 GNUNET_i2s (&b->pid));
8971 GST_stats,
8972 "# Backchannel messages dropped: monotonic time not increasing",
8973 1,
8974 GNUNET_NO);
8975 b->monotonic_time = mt;
8976 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
8977 */
8978 b->body_size = 0;
8979 }
8981}
8982
8983
8991static void
8992backtalker_monotime_store_cb (void *cls, int success)
8993{
8994 struct Backtalker *b = cls;
8995
8996 if (GNUNET_OK != success)
8997 {
8999 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
9000 }
9001 b->sc = NULL;
9002 if (NULL != b->task)
9003 {
9005 b->task = NULL;
9006 }
9008}
9009
9010
9016static void
9018{
9019 struct GNUNET_TIME_AbsoluteNBO mtbe;
9020
9021 if (NULL != b->sc)
9022 {
9024 "store cancel before store with sc %p\n",
9025 b->sc);
9026 /*GNUNET_PEERSTORE_store_cancel (b->sc);
9027 b->sc = NULL;*/
9029 "store cancel before store with sc %p is null\n",
9030 b->sc);
9031 }
9032 else
9033 {
9035 b->task = NULL;
9036 }
9038 b->sc =
9040 "transport",
9041 &b->pid,
9043 &mtbe,
9044 sizeof(mtbe),
9048 b);
9049}
9050
9051
9052struct DecapsDvBoxCls
9053{
9055 const struct TransportDVBoxMessage *dvb;
9056 struct PilsRequest *pr;
9057};
9058
9059
9060static void
9061decaps_dv_box_cb (void *cls, const struct GNUNET_ShortHashCode *km)
9062{
9063 struct DecapsDvBoxCls *decaps_dv_box_cls = cls;
9064 struct CommunicatorMessageContext *cmc = decaps_dv_box_cls->cmc;
9065 const struct TransportDVBoxMessage *dvb = dvb;
9066 struct DVKeyState key;
9067 const char *hdr;
9068 size_t hdr_len;
9069 struct GNUNET_HashCode hmac;
9070
9071 decaps_dv_box_cls->pr->op = NULL;
9074 decaps_dv_box_cls->pr);
9075 GNUNET_free (decaps_dv_box_cls->pr);
9076 if (NULL == km)
9077 {
9078 GNUNET_break_op (0);
9079 finish_cmc_handling (cmc);
9080 return;
9081 }
9082 dv_setup_key_state_from_km (km, &dvb->iv, &key);
9083 hdr = (const char *) &dvb[1];
9084 hdr_len = ntohs (dvb->orig_size) - sizeof(*dvb) - sizeof(struct
9086 * ntohs (dvb->total_hops);
9087
9088 dv_hmac (&key, &hmac, hdr, hdr_len);
9089 if (0 != GNUNET_memcmp (&hmac, &dvb->hmac))
9090 {
9091 /* HMAC mismatch, discard! */
9092 GNUNET_break_op (0);
9093 finish_cmc_handling (cmc);
9094 return;
9095 }
9096 /* begin actual decryption */
9097 {
9098 struct Backtalker *b;
9099 struct GNUNET_TIME_Absolute monotime;
9100 struct TransportDVBoxPayloadP ppay;
9101 char body[hdr_len - sizeof(ppay)] GNUNET_ALIGN;
9102 const struct GNUNET_MessageHeader *mh;
9103
9104 GNUNET_assert (hdr_len >=
9105 sizeof(ppay) + sizeof(struct GNUNET_MessageHeader));
9106 if (GNUNET_OK != dv_decrypt (&key, &ppay, hdr, sizeof(ppay)))
9107 {
9109 "Error decrypting DV payload header\n");
9110 GNUNET_break_op (0);
9111 finish_cmc_handling (cmc);
9112 return;
9113 }
9114 if (GNUNET_OK != dv_decrypt (&key, body,
9115 &hdr[sizeof(ppay)], hdr_len - sizeof(ppay)))
9116 {
9118 "Error decrypting DV payload\n");
9119 GNUNET_break_op (0);
9120 finish_cmc_handling (cmc);
9121 return;
9122 }
9123 mh = (const struct GNUNET_MessageHeader *) body;
9124 dv_key_clean (&key);
9125 if (ntohs (mh->size) != sizeof(body))
9126 {
9127 GNUNET_break_op (0);
9128 finish_cmc_handling (cmc);
9129 return;
9130 }
9131 /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
9132 switch (ntohs (mh->type))
9133 {
9135 GNUNET_break_op (0);
9136 finish_cmc_handling (cmc);
9137 return;
9138
9140 GNUNET_break_op (0);
9141 finish_cmc_handling (cmc);
9142 return;
9143
9144 default:
9145 /* permitted, continue */
9146 break;
9147 }
9148 monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time);
9150 "Decrypted backtalk from %s\n",
9151 GNUNET_i2s (&ppay.sender));
9153 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
9154 {
9156 GST_stats,
9157 "# Backchannel messages dropped: monotonic time not increasing",
9158 1,
9159 GNUNET_NO);
9160 finish_cmc_handling (cmc);
9161 return;
9162 }
9163 if ((NULL == b) ||
9164 (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
9165 {
9166 /* Check signature */
9167 struct EphemeralConfirmationPS ec;
9168
9170 ec.target = *GST_my_identity;
9171 ec.ephemeral_key = dvb->ephemeral_key;
9172 ec.purpose.size = htonl (sizeof(ec));
9173 ec.sender_monotonic_time = ppay.monotonic_time;
9174 if (
9175 GNUNET_OK !=
9178 &ec,
9179 &ppay.sender_sig,
9180 &ppay.sender.public_key))
9181 {
9182 /* Signature invalid, discard! */
9183 GNUNET_break_op (0);
9184 finish_cmc_handling (cmc);
9185 return;
9186 }
9187 }
9188 /* Update sender, we now know the real origin! */
9190 "DVBox received for me from %s via %s\n",
9191 GNUNET_i2s2 (&ppay.sender),
9192 GNUNET_i2s (&cmc->im.sender));
9193 cmc->im.sender = ppay.sender;
9194
9195 if (NULL != b)
9196 {
9197 /* update key cache and mono time */
9198 b->last_ephemeral = dvb->ephemeral_key;
9199 b->monotonic_time = monotime;
9201 b->timeout =
9203 cmc->mh = mh;
9205 return;
9206 }
9207 /* setup data structure to cache signature AND check
9208 monotonic time with PEERSTORE before forwarding backchannel payload */
9209 b = GNUNET_malloc (sizeof(struct Backtalker) + sizeof(body));
9210 b->pid = ppay.sender;
9211 b->body_size = sizeof(body);
9212 memcpy (&b[1], body, sizeof(body));
9216 &b->pid,
9217 b,
9219 b->monotonic_time = monotime; /* NOTE: to be checked still! */
9220 b->cmc = cmc;
9221 b->timeout =
9224 b->get =
9226 "transport",
9227 &b->pid,
9230 b);
9231 } /* end actual decryption */
9232}
9233
9234
9242static void
9243handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
9244{
9245 struct CommunicatorMessageContext *cmc = cls;
9246 uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
9247 uint16_t num_hops = ntohs (dvb->num_hops);
9248 const struct GNUNET_PeerIdentity *hops =
9249 (const struct GNUNET_PeerIdentity *) &dvb[1];
9250 const char *enc_payload = (const char *) &hops[num_hops];
9251 uint16_t enc_payload_size =
9252 size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
9253 struct DecapsDvBoxCls *decaps_dv_box_cls;
9254
9255 if (GNUNET_EXTRA_LOGGING > 0)
9256 {
9257 char *path;
9258
9260 for (unsigned int i = 0; i < num_hops; i++)
9261 {
9262 char *tmp;
9263
9264 GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
9265 GNUNET_free (path);
9266 path = tmp;
9267 }
9269 "Received DVBox with remaining path %s\n",
9270 path);
9271 GNUNET_free (path);
9272 }
9273
9274 if (num_hops > 0)
9275 {
9276 /* We're trying from the end of the hops array, as we may be
9277 able to find a shortcut unknown to the origin that way */
9278 for (int i = num_hops - 1; i >= 0; i--)
9279 {
9280 struct Neighbour *n;
9281
9282 if (0 == GNUNET_memcmp (&hops[i], GST_my_identity))
9283 {
9284 GNUNET_break_op (0);
9285 finish_cmc_handling (cmc);
9286 return;
9287 }
9288 n = lookup_neighbour (&hops[i]);
9289 if (NULL == n)
9290 continue;
9292 "Skipping %u/%u hops ahead while routing DV Box\n",
9293 i,
9294 num_hops);
9295
9296 forward_dv_box (n,
9297 (struct TransportDVBoxMessage *) dvb,
9298 ntohs (dvb->total_hops) + 1,
9299 num_hops - i - 1, /* number of hops left */
9300 &hops[i + 1], /* remaining hops */
9301 enc_payload,
9302 enc_payload_size);
9304 "# DV hops skipped routing boxes",
9305 i,
9306 GNUNET_NO);
9308 "# DV boxes routed (total)",
9309 1,
9310 GNUNET_NO);
9311 finish_cmc_handling (cmc);
9312 return;
9313 }
9314 /* Woopsie, next hop not in neighbours, drop! */
9316 "# DV Boxes dropped: next hop unknown",
9317 1,
9318 GNUNET_NO);
9319 finish_cmc_handling (cmc);
9320 return;
9321 }
9322 /* We are the target. Unbox and handle message. */
9324 "# DV boxes opened (ultimate target)",
9325 1,
9326 GNUNET_NO);
9327 cmc->total_hops = ntohs (dvb->total_hops);
9328
9329 {
9330 // DH key derivation with received DV, could be garbage.
9331 decaps_dv_box_cls = GNUNET_new (struct DecapsDvBoxCls);
9332 decaps_dv_box_cls->cmc = cmc;
9333 decaps_dv_box_cls->dvb = dvb;
9334 decaps_dv_box_cls->pr = GNUNET_new (struct PilsRequest);
9335
9338 decaps_dv_box_cls->pr);
9339 decaps_dv_box_cls->pr->op = GNUNET_PILS_kem_decaps (pils,
9340 &dvb->ephemeral_key,
9342 decaps_dv_box_cls);
9343 }
9344 // TODO keep track of cls and potentially clean
9345}
9346
9347
9355static int
9356check_incoming_msg (void *cls,
9357 const struct GNUNET_TRANSPORT_IncomingMessage *im)
9358{
9359 struct TransportClient *tc = cls;
9360
9361 if (CT_COMMUNICATOR != tc->type)
9362 {
9363 GNUNET_break (0);
9364 return GNUNET_SYSERR;
9365 }
9367 return GNUNET_OK;
9368}
9369
9370
9375{
9379 const char *address;
9380
9384 struct ValidationState *vs;
9385};
9386
9387
9397static int
9398check_known_address (void *cls,
9399 const struct GNUNET_PeerIdentity *pid,
9400 void *value)
9401{
9402 struct CheckKnownAddressContext *ckac = cls;
9403 struct ValidationState *vs = value;
9404
9405 (void) pid;
9406 if (0 != strcmp (vs->address, ckac->address))
9407 return GNUNET_OK;
9408 ckac->vs = vs;
9409 return GNUNET_NO;
9410}
9411
9412
9418static void
9419validation_start_cb (void *cls);
9420
9421
9429static void
9431 struct GNUNET_TIME_Absolute new_time)
9432{
9434
9435 if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
9436 return; /* be lazy */
9437 vs->next_challenge = new_time;
9438 if (NULL == vs->hn)
9439 vs->hn =
9441 else
9444 (NULL != validation_task))
9445 return;
9446 if (NULL != validation_task)
9448 /* randomize a bit */
9451 MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
9452 new_time = GNUNET_TIME_absolute_add (new_time, delta);
9455}
9456
9457
9464static void
9466 const char *address)
9467{
9468 struct GNUNET_TIME_Absolute now;
9469 struct ValidationState *vs;
9470 struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
9471
9473 pid,
9475 &ckac);
9476 if (NULL != (vs = ckac.vs))
9477 {
9478 /* if 'vs' is not currently valid, we need to speed up retrying the
9479 * validation */
9480 if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
9481 {
9482 /* reduce backoff as we got a fresh advertisement */
9483 vs->challenge_backoff =
9486 vs->challenge_backoff,
9487 2));
9490 vs->challenge_backoff));
9491 }
9492 return;
9493 }
9495 vs = GNUNET_new (struct ValidationState);
9496 vs->pid = *pid;
9497 vs->valid_until =
9499 vs->first_challenge_use = now;
9500 vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
9502 &vs->challenge,
9503 sizeof(vs->challenge));
9504 vs->address = GNUNET_strdup (address);
9505 GNUNET_CRYPTO_hash (vs->address, strlen (vs->address), &vs->hc);
9507 "Starting address validation `%s' of peer %s using challenge %s\n",
9508 address,
9509 GNUNET_i2s (pid),
9510 GNUNET_sh2s (&vs->challenge.value));
9514 &vs->pid,
9515 vs,
9518}
9519
9520
9521static struct Queue *
9522find_queue (const struct GNUNET_PeerIdentity *pid, const char *address);
9523
9524
9525static void
9526suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address);
9527
9528
9529static void
9530hello_for_incoming_cb (void *cls,
9531 const struct GNUNET_PeerIdentity *pid,
9532 const char *uri)
9533{
9534 struct Queue *q;
9535 int pfx_len;
9536 const char *eou;
9537 char *address;
9538 (void) cls;
9539
9540 eou = strstr (uri,
9541 "://");
9542 pfx_len = eou - uri;
9543 eou += 3;
9545 "%.*s-%s",
9546 pfx_len,
9547 uri,
9548 eou);
9549
9551 "helo for client %s\n",
9552 address);
9553 q = find_queue (pid, address);
9554 if (NULL == q)
9555 {
9557 }
9558 else
9561}
9562
9563
9571static void
9572handle_hello_for_incoming (void *cls,
9573 const struct GNUNET_PEERSTORE_Record *record,
9574 const char *emsg)
9575{
9576 struct IncomingRequest *ir = cls;
9578 struct GNUNET_MessageHeader *hello;
9579
9580 if (NULL != emsg)
9581 {
9583 "Got failure from PEERSTORE: %s\n",
9584 emsg);
9585 return;
9586 }
9587 hello = record->value;
9588 if (0 == GNUNET_memcmp (&record->peer, GST_my_identity))
9589 {
9591 return;
9592 }
9596 NULL);
9597 GNUNET_HELLO_parser_free (parser);
9598}
9599
9600
9601static void
9603{
9605 "Error in PEERSTORE monitoring\n");
9606}
9607
9608
9609static void
9611{
9613 "Done with initial PEERSTORE iteration during monitoring\n");
9614}
9615
9616
9617struct SignTValidationCls
9618{
9621 struct PilsRequest *pr;
9622};
9623
9624
9625static void
9626sign_t_validation_cb (void *cls,
9627 const struct GNUNET_PeerIdentity *pid,
9628 const struct GNUNET_CRYPTO_EddsaSignature *sig)
9629{
9630 struct SignTValidationCls *sign_t_validation_cls = cls;
9631 struct CommunicatorMessageContext *cmc = sign_t_validation_cls->cmc;
9632 struct TransportValidationResponseMessage tvr = sign_t_validation_cls->tvr;
9633 struct VirtualLink *vl;
9634 struct Neighbour *n;
9635 struct IncomingRequest *ir;
9636 struct GNUNET_PeerIdentity sender;
9637
9638 sign_t_validation_cls->pr->op = NULL;
9641 sign_t_validation_cls->pr);
9642 GNUNET_free (sign_t_validation_cls->pr);
9643 tvr.signature = *sig;
9644 sender = cmc->im.sender;
9645 vl = lookup_virtual_link (&sender);
9646 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9647 {
9648 // route_control_message_without_fc (&cmc->im.sender,
9650 &tvr.header,
9652 }
9653 else
9654 {
9655 /* Use route via neighbour */
9656 n = lookup_neighbour (&sender);
9657 if (NULL != n)
9658 route_via_neighbour (n, &tvr.header,
9661 }
9662
9663 finish_cmc_handling (cmc);
9664 if (NULL != vl)
9665 return;
9666
9667 /* For us, the link is still down, but we need bi-directional
9668 connections (for flow-control and for this to be useful for
9669 CORE), so we must try to bring the link up! */
9670
9671 /* (1) Check existing queues, if any, we may be lucky! */
9672 n = lookup_neighbour (&sender);
9673 if (NULL != n)
9674 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
9675 start_address_validation (&sender, q->address);
9676 /* (2) Also try to see if we have addresses in PEERSTORE for this peer
9677 we could use */
9678 for (ir = ir_head; NULL != ir; ir = ir->next)
9679 if (0 == GNUNET_memcmp (&ir->pid, &sender))
9680 return;
9681 /* we are already trying */
9682 ir = GNUNET_new (struct IncomingRequest);
9683 ir->pid = sender;
9685
9687 GNUNET_YES,
9688 "peerstore",
9689 NULL,
9692 NULL,
9694 NULL,
9696 ir);
9697 ir_total++;
9698 /* Bound attempts we do in parallel here, might otherwise get excessive */
9701};
9702
9703
9712static void
9714 void *cls,
9715 const struct TransportValidationChallengeMessage *tvc)
9716{
9717 struct CommunicatorMessageContext *cmc = cls;
9719 struct GNUNET_TIME_RelativeNBO validity_duration;
9720
9721 /* DV-routed messages are not allowed for validation challenges */
9722 if (cmc->total_hops > 0)
9723 {
9724 GNUNET_break_op (0);
9725 finish_cmc_handling (cmc);
9726 return;
9727 }
9728 validity_duration = cmc->im.expected_address_validity;
9730 "Received address validation challenge %s\n",
9731 GNUNET_sh2s (&tvc->challenge.value));
9732 /* If we have a virtual link, we use this mechanism to signal the
9733 size of the flow control window, and to allow the sender
9734 to ask for increases. If for us the virtual link is still down,
9735 we will always give a window size of zero. */
9736 tvr.header.type =
9738 tvr.header.size = htons (sizeof(tvr));
9739 tvr.reserved = htonl (0);
9740 tvr.challenge = tvc->challenge;
9741 tvr.origin_time = tvc->sender_time;
9742 tvr.validity_duration = validity_duration;
9743 {
9744 /* create signature */
9745 struct TransportValidationPS tvp = {
9747 .purpose.size = htonl (sizeof(tvp)),
9748 .validity_duration = validity_duration,
9749 .challenge = tvc->challenge
9750 };
9751 struct SignTValidationCls *sign_t_validation_cls;
9752
9753 sign_t_validation_cls = GNUNET_new (struct SignTValidationCls);
9754 sign_t_validation_cls->cmc = cmc;
9755 sign_t_validation_cls->tvr = tvr;
9756 sign_t_validation_cls->pr = GNUNET_new (struct PilsRequest);
9759 sign_t_validation_cls->pr);
9760 sign_t_validation_cls->pr->op =
9762 &tvp.purpose,
9764 sign_t_validation_cls);
9765 }
9766}
9767
9768
9773{
9778
9782 struct ValidationState *vs;
9783};
9784
9785
9795static int
9796check_known_challenge (void *cls,
9797 const struct GNUNET_PeerIdentity *pid,
9798 void *value)
9799{
9800 struct CheckKnownChallengeContext *ckac = cls;
9801 struct ValidationState *vs = value;
9802
9803 (void) pid;
9804 if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
9805 return GNUNET_OK;
9806 ckac->vs = vs;
9807 return GNUNET_NO;
9808}
9809
9810
9818static void
9819peerstore_store_validation_cb (void *cls, int success)
9820{
9821 struct ValidationState *vs = cls;
9822
9823 vs->sc = NULL;
9824 if (GNUNET_YES == success)
9825 return;
9827 "# Peerstore failed to store foreign address",
9828 1,
9829 GNUNET_NO);
9830}
9831
9832
9840static struct Queue *
9841find_queue (const struct GNUNET_PeerIdentity *pid, const char *address)
9842{
9843 struct Neighbour *n;
9844
9845 n = lookup_neighbour (pid);
9846 if (NULL == n)
9847 return NULL;
9848 for (struct Queue *pos = n->queue_head; NULL != pos;
9849 pos = pos->next_neighbour)
9850 {
9851 if (0 == strcmp (pos->address, address))
9852 return pos;
9853 }
9854 return NULL;
9855}
9856
9857
9858static void
9860
9861static void
9862revalidation_start_cb (void *cls)
9863{
9864 struct ValidationState *vs = cls;
9865 struct Queue *q;
9866 struct GNUNET_TIME_Absolute now;
9867
9868 vs->revalidation_task = NULL;
9869 q = find_queue (&vs->pid, vs->address);
9870 if (NULL == q)
9871 {
9872 now = GNUNET_TIME_absolute_get ();
9873 vs->awaiting_queue = GNUNET_YES;
9874 suggest_to_connect (&vs->pid, vs->address);
9876 }
9877 else
9879}
9880
9881
9882static enum GNUNET_GenericReturnValue
9884 void *cls,
9885 const struct GNUNET_HashCode *key,
9886 void *value)
9887{
9888 (void) cls;
9890 "Key in revalidate map %s \n",
9891 GNUNET_h2s (key));
9892 return GNUNET_YES;
9893}
9894
9895
9904static void
9906 void *cls,
9907 const struct TransportValidationResponseMessage *tvr)
9908{
9909 struct CommunicatorMessageContext *cmc = cls;
9910 struct ValidationState *vs;
9911 struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
9912 .vs = NULL};
9913 struct GNUNET_TIME_Absolute origin_time;
9914 struct Queue *q;
9915 struct Neighbour *n;
9916 struct VirtualLink *vl;
9918 GST_cfg);
9919
9920 /* check this is one of our challenges */
9922 &cmc->im.sender,
9924 &ckac);
9925 if (NULL == (vs = ckac.vs))
9926 {
9927 /* This can happen simply if we 'forgot' the challenge by now,
9928 i.e. because we received the validation response twice */
9930 "# Validations dropped, challenge unknown",
9931 1,
9932 GNUNET_NO);
9934 "Validation response %s dropped, challenge unknown\n",
9935 GNUNET_sh2s (&tvr->challenge.value));
9936 finish_cmc_handling (cmc);
9937 return;
9938 }
9939
9940 /* sanity check on origin time */
9941 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
9942 if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
9943 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
9944 {
9946 "Diff first use %" PRIu64 " and last use %" PRIu64 "\n",
9947 vs->first_challenge_use.abs_value_us - origin_time.abs_value_us,
9948 origin_time.abs_value_us - vs->last_challenge_use.abs_value_us);
9949 GNUNET_break_op (0);
9950 finish_cmc_handling (cmc);
9951 return;
9952 }
9953
9954 {
9955 /* check signature */
9956 struct TransportValidationPS tvp = {
9958 .purpose.size = htonl (sizeof(tvp)),
9959 .validity_duration = tvr->validity_duration,
9960 .challenge = tvr->challenge
9961 };
9962
9963 if (
9964 GNUNET_OK !=
9966 &tvp,
9967 &tvr->signature,
9968 &cmc->im.sender.public_key))
9969 {
9970 GNUNET_break_op (0);
9971 finish_cmc_handling (cmc);
9972 return;
9973 }
9974 }
9975
9976 /* validity is capped by our willingness to keep track of the
9977 validation entry and the maximum the other peer allows */
9980 tvr->validity_duration),
9982 vs->validated_until =
9986 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
9987 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
9989 &vs->challenge,
9990 sizeof(vs->challenge));
9991 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
9992 vs->validated_until,
9993 GNUNET_TIME_relative_multiply (vs->validation_rtt,
9995 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, <, now))
9996 {
9998 "First challenge use is now %" PRIu64 " %s \n",
9999 vs->first_challenge_use.abs_value_us,
10000 GNUNET_sh2s (&vs->challenge.value));
10001 vs->first_challenge_use = now;
10002 }
10003 else
10005 "First challenge use is later %" PRIu64 " %s \n",
10006 vs->first_challenge_use.abs_value_us,
10007 GNUNET_sh2s (&vs->challenge.value));
10008 vs->last_challenge_use =
10009 GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
10010 update_next_challenge_time (vs, vs->first_challenge_use);
10012 "Validation response %s from %s accepted, address valid until %s\n",
10013 GNUNET_sh2s (&tvr->challenge.value),
10014 GNUNET_i2s (&cmc->im.sender),
10016 /*memcpy (&hkey,
10017 &hc,
10018 sizeof (hkey));*/
10020 "Key %s for address %s map size %u contains %u\n",
10021 GNUNET_h2s (&vs->hc),
10022 vs->address,
10025 &vs->hc));
10029 &vs->hc,
10030 vs,
10034 NULL);
10035 vs->revalidation_task =
10040 "transport",
10041 &cmc->im.sender,
10043 vs->address,
10044 strlen (vs->address) + 1,
10045 vs->valid_until,
10048 vs);
10049 finish_cmc_handling (cmc);
10050
10051 /* Finally, we now possibly have a confirmed (!) working queue,
10052 update queue status (if queue still is around) */
10053 q = find_queue (&vs->pid, vs->address);
10054 if (NULL == q)
10055 {
10057 "# Queues lost at time of successful validation",
10058 1,
10059 GNUNET_NO);
10060 return;
10061 }
10062 q->validated_until = vs->validated_until;
10063 q->pd.aged_rtt = vs->validation_rtt;
10064 n = q->neighbour;
10065 vl = lookup_virtual_link (&vs->pid);
10066 if (NULL == vl)
10067 {
10068 vl = GNUNET_new (struct VirtualLink);
10070 "Creating new virtual link %p to %s using direct neighbour!\n",
10071 vl,
10072 GNUNET_i2s (&vs->pid));
10073 vl->burst_addr = NULL;
10074 vl->confirmed = GNUNET_YES;
10075 vl->message_uuid_ctr =
10077 vl->target = n->pid;
10083 links,
10084 &vl->target,
10085 vl,
10087 vl->n = n;
10088 n->vl = vl;
10089 q->idle = GNUNET_YES;
10090 vl->visibility_task =
10091 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
10093 /* We lacked a confirmed connection to the target
10094 before, so tell CORE about it (finally!) */
10097 }
10098 else
10099 {
10100 /* Link was already up, remember n is also now available and we are done */
10101 if (NULL == vl->n)
10102 {
10103 vl->n = n;
10104 n->vl = vl;
10105 if (GNUNET_YES == vl->confirmed)
10107 "Virtual link to %s could now also use direct neighbour!\n",
10108 GNUNET_i2s (&vs->pid));
10109 }
10110 else
10111 {
10112 GNUNET_assert (n == vl->n);
10113 }
10114 if (GNUNET_NO == vl->confirmed)
10115 {
10116 vl->confirmed = GNUNET_YES;
10117 q->idle = GNUNET_YES;
10118 vl->visibility_task =
10119 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
10121 /* We lacked a confirmed connection to the target
10122 before, so tell CORE about it (finally!) */
10125 }
10126 }
10127}
10128
10129
10135static void
10136handle_incoming_msg (void *cls,
10137 const struct GNUNET_TRANSPORT_IncomingMessage *im)
10138{
10139 struct TransportClient *tc = cls;
10140 struct CommunicatorMessageContext *cmc =
10142
10143 cmc->tc = tc;
10144 cmc->im = *im;
10146 "Received message with size %u and flow control id %" PRIu64
10147 " via communicator from peer %s\n",
10148 ntohs (im->header.size),
10149 im->fc_id,
10150 GNUNET_i2s (&im->sender));
10151 cmc->im.neighbour_sender = cmc->im.sender;
10152 cmc->mh = (const struct GNUNET_MessageHeader *) &im[1];
10154}
10155
10156
10165static int
10166check_flow_control (void *cls, const struct TransportFlowControlMessage *fc)
10167{
10168 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10169 (void) cls;
10170
10172 "Flow control header size %u size of addresses %u number of addresses %u size of message struct %lu second struct %lu\n",
10173 ntohs (fc->header.size),
10174 ntohl (fc->size_of_addresses),
10175 ntohl (fc->number_of_addresses),
10176 sizeof(struct TransportFlowControlMessage),
10177 sizeof (struct TransportGlobalNattedAddress));
10178
10179 if (0 == number_of_addresses || ntohs (fc->header.size) == sizeof(struct
10181 + ntohl (fc->number_of_addresses) * sizeof (struct
10183 + ntohl (fc->size_of_addresses))
10184 return GNUNET_OK;
10185 else
10186 {
10187 GNUNET_break_op (0);
10188 return GNUNET_SYSERR;
10189 }
10190}
10191
10192
10193static struct GNUNET_TIME_Relative
10194calculate_rtt (struct DistanceVector *dv)
10195{
10197 unsigned int n_hops = 0;
10198
10200 "calculate_rtt\n");
10201 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
10202 pos = pos->next_dv)
10203 {
10205 "calculate_rtt %lu\n",
10206 (unsigned long) pos->pd.aged_rtt.rel_value_us);
10207 n_hops++;
10209 aged_rtt, pos
10210 ->distance
10211 + 2), ret);
10212 }
10213
10214 GNUNET_assert (0 != n_hops);
10215
10216 return ret;
10217}
10218
10219
10220static void
10222 const struct GNUNET_PeerIdentity *pid,
10223 const char *uri)
10224{
10225 struct VirtualLink *vl = cls;
10226 const char *slash;
10227 char *address_uri;
10228 char *prefix;
10229 char *uri_without_port;
10230
10231 slash = strrchr (uri, '/');
10232 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
10233 GNUNET_assert (NULL != slash);
10234 slash++;
10235 GNUNET_asprintf (&address_uri,
10236 "%s-%s",
10237 prefix,
10238 slash);
10239
10240 uri_without_port = get_address_without_port (address_uri);
10242 "iterate_address_start_burst %s %s %s %s\n",
10243 uri_without_port,
10244 uri,
10245 address_uri,
10246 slash);
10247 if (0 == strcmp (uri_without_port, slash))
10248 {
10249 vl->burst_addr = GNUNET_strndup (uri_without_port, strlen (uri_without_port)
10250 );
10251 }
10252 else
10253 vl->burst_addr = NULL;
10254
10256 GNUNET_free (uri_without_port);
10257}
10258
10259
10260static void
10261check_for_burst_address (void *cls,
10262 const struct GNUNET_PEERSTORE_Record *record,
10263 const char *emsg)
10264{
10265 struct GNUNET_StartBurstCls *sb_cls = cls;
10266 struct VirtualLink *vl = sb_cls->vl;
10267 struct GNUNET_MessageHeader *hello;
10269
10270 if (NULL != emsg)
10271 {
10273 "Got failure from PEERSTORE: %s\n",
10274 emsg);
10275 return;
10276 }
10277 if (NULL == record)
10278 {
10280 "Hello iteration end for %s\n",
10281 GNUNET_i2s (&vl->target));
10282 vl->ic = NULL;
10283 GNUNET_free (sb_cls);
10284 return;
10285 }
10286
10288 "check_for_burst_address\n");
10289 hello = record->value;
10293 vl);
10294 GNUNET_HELLO_parser_free (parser);
10295
10297 GNUNET_free (sb_cls);
10298}
10299
10300
10301static void
10302burst_timeout (void *cls)
10303{
10305}
10306
10307
10308static void
10309start_burst (void *cls)
10310{
10311 struct GNUNET_StartBurstCls *sb_cls = cls;
10312 struct VirtualLink *vl = sb_cls->vl;
10313 struct GNUNET_TRANSPORT_StartBurst *sb;
10314 struct GNUNET_MQ_Envelope *env;
10315 char *uri_without_port = vl->burst_addr;
10316
10317 burst_task = NULL;
10318 /*char buf[strlen (uri_without_port) + 1];
10319
10320 GNUNET_memcpy (buf, uri_without_port, strlen (uri_without_port));
10321 buf[strlen (uri_without_port)] = '\0';*/
10322 env =
10324 strlen (uri_without_port) + 1,
10326 sb->rtt = GNUNET_TIME_relative_hton (sb_cls->rtt);
10327 sb->pid = vl->target;
10328 memcpy (&sb[1], uri_without_port, strlen (uri_without_port) + 1);
10329 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
10330 {
10332 "iterate_address_start_burst client tc prefix %s\n",
10333 tc->details.communicator.address_prefix);
10334 if (CT_COMMUNICATOR != tc->type)
10335 continue;
10336 if (GNUNET_YES == tc->details.communicator.can_burst)
10337 {
10339 "iterate_address_start_burst %s call %lu %u rtt %lu\n",
10340 uri_without_port,
10341 strlen (uri_without_port),
10342 ntohs (sb->header.size),
10343 (unsigned long) sb_cls->rtt.rel_value_us);
10344 GNUNET_MQ_send (tc->mq, env);
10348 60),
10350 NULL);
10351 // TODO We need some algo to choose from available communicators. Can we run two bursts at once? Atm we only implemented udp burst.
10352 break;
10353 }
10354 }
10355 GNUNET_free (env);
10356 GNUNET_free (sb_cls);
10357}
10358
10359
10360static void
10361queue_burst (void *cls)
10362{
10363 struct GNUNET_StartBurstCls *sb_cls = cls;
10364 struct VirtualLink *vl = sb_cls->vl;
10365
10366 if (GNUNET_YES != use_burst)
10367 return;
10369 "burst_task %p ready %s burst addr %s (%p)\n",
10370 burst_task,
10371 sb_cls->sync_ready ? "yes" : "no",
10372 vl->burst_addr,
10373 vl->burst_addr);
10374 if (NULL != burst_task && GNUNET_NO == sb_cls->sync_ready)
10375 {
10377 burst_task = NULL;
10379 return;
10380 }
10381 if (GNUNET_NO == burst_running && NULL != vl->burst_addr && NULL == burst_task
10382 )
10383 {
10385 &start_burst,
10386 sb_cls);
10387 }
10388 else if (NULL == vl->burst_addr)
10389 {
10391 "peerstore",
10392 &vl->target,
10395 sb_cls);
10396 }
10397}
10398
10399
10408static void
10409handle_flow_control (void *cls, const struct TransportFlowControlMessage *fc)
10410{
10411 struct CommunicatorMessageContext *cmc = cls;
10412 struct VirtualLink *vl;
10414 uint32_t seq;
10415 struct GNUNET_TIME_Absolute st;
10416 uint64_t os;
10417 uint64_t wnd;
10418 uint32_t random;
10419
10421 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
10422 vl = lookup_virtual_link (&cmc->im.sender);
10423 if (NULL == vl)
10424 {
10425 vl = GNUNET_new (struct VirtualLink);
10427 "No virtual link for %p FC creating new unconfirmed virtual link to %s!\n",
10428 vl,
10429 GNUNET_i2s (&cmc->im.sender));
10430 vl->burst_addr = NULL;
10431 vl->confirmed = GNUNET_NO;
10432 vl->message_uuid_ctr =
10434 vl->target = cmc->im.sender;
10440 links,
10441 &vl->target,
10442 vl,
10444 }
10445 if (NULL != vl->n)
10446 {
10447 for (struct Queue *q = vl->n->queue_head; NULL != q; q = q->next_neighbour)
10448 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
10449 }
10450
10452 "remaining %lu timeout for neighbour %p\n",
10453 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout).
10454 rel_value_us,
10455 vl->n);
10456 if (NULL == vl->n ||
10457 0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
10458 {
10459 struct GNUNET_TIME_Relative rtt;
10460 struct GNUNET_BurstSync burst_sync;
10461 struct GNUNET_StartBurstCls *bcls;
10462
10463 bcls = GNUNET_new (struct GNUNET_StartBurstCls);
10464 bcls->vl = vl;
10465 vl->sb_cls = bcls;
10466 if (NULL != vl->dv)
10467 rtt = calculate_rtt (vl->dv);
10468 else
10470 burst_sync.rtt_average = fc->rtt;
10471 bcls->rtt = GNUNET_TIME_relative_ntoh (burst_sync.rtt_average);
10472 burst_sync.sync_ready = fc->sync_ready;
10473
10475 &burst_sync,
10476 &queue_burst,
10477 bcls);
10478 }
10479 if (0 != ntohl (fc->number_of_addresses))
10480 {
10481 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10482 const char *tgnas;
10483 unsigned int off = 0;
10484
10485 tgnas = (const char *) &fc[1];
10486
10487 for (int i = 1; i <= number_of_addresses; i++)
10488 {
10489 struct TransportGlobalNattedAddress *tgna;
10490 char *addr;
10491 unsigned int address_length;
10492
10493 tgna = (struct TransportGlobalNattedAddress*) &tgnas[off];
10494 addr = (char *) &tgna[1];
10495 address_length = ntohl (tgna->address_length);
10496 off += sizeof(struct TransportGlobalNattedAddress) + address_length;
10497
10499 "received address %s length %u\n",
10500 addr,
10501 ntohl (tgna->address_length));
10502
10503 GNUNET_NAT_add_global_address (nh, addr, ntohl (tgna->address_length));
10504 }
10505 }
10507 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
10508 {
10510 "FC dropped: Message out of order\n");
10511 /* out of order, drop */
10513 "# FC dropped: message out of order",
10514 1,
10515 GNUNET_NO);
10516 finish_cmc_handling (cmc);
10517 return;
10518 }
10519 seq = ntohl (fc->seq);
10520 if (seq < vl->last_fc_seq)
10521 {
10522 /* Wrap-around/reset of other peer; start all counters from zero */
10524 }
10525 vl->last_fc_seq = seq;
10526 vl->last_fc_timestamp = st;
10528 os = GNUNET_ntohll (fc->outbound_sent);
10530 (int64_t) (os - vl->incoming_fc_window_size_used);
10532 "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
10533 GNUNET_i2s (&vl->target),
10534 (unsigned int) seq,
10535 (unsigned long long) vl->outbound_fc_window_size,
10536 (long long) vl->incoming_fc_window_size_loss);
10539 UINT32_MAX);
10540 if ((GNUNET_YES == vl->confirmed) && ((wnd < vl->incoming_fc_window_size
10544 != wnd) ||
10545 (0 == random
10547 {
10549 "Consider re-sending our FC message, as clearly the other peer's idea of the window is not up-to-date (%llu vs %llu) or %llu last received differs, or random reply %u\n",
10550 (unsigned long long) wnd,
10551 (unsigned long long) vl->incoming_fc_window_size,
10552 (unsigned long long) vl->last_outbound_window_size_received,
10555 }
10556 if ((wnd == vl->incoming_fc_window_size
10560 (NULL != vl->fc_retransmit_task))
10561 {
10563 "Stopping FC retransmission to %s: peer is current at window %llu\n",
10564 GNUNET_i2s (&vl->target),
10565 (unsigned long long) wnd);
10567 vl->fc_retransmit_task = NULL;
10568 vl->fc_retransmit_count = 0;
10569 }
10571 /* FC window likely increased, check transmission possibilities! */
10573 finish_cmc_handling (cmc);
10574}
10575
10576
10584static void
10586{
10588 { GNUNET_MQ_hd_var_size (fragment_box,
10591 cmc),
10592 GNUNET_MQ_hd_var_size (reliability_box,
10595 cmc),
10596 GNUNET_MQ_hd_var_size (reliability_ack,
10599 cmc),
10600 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
10603 cmc),
10604 GNUNET_MQ_hd_var_size (dv_learn,
10607 cmc),
10608 GNUNET_MQ_hd_var_size (dv_box,
10610 struct TransportDVBoxMessage,
10611 cmc),
10612 GNUNET_MQ_hd_var_size (flow_control,
10615 cmc),
10617 validation_challenge,
10620 cmc),
10622 validation_response,
10625 cmc),
10627 int ret;
10628 const struct GNUNET_MessageHeader *msg = cmc->mh;
10629
10631 "Handling message of type %u with %u bytes\n",
10632 (unsigned int) ntohs (msg->type),
10633 (unsigned int) ntohs (msg->size));
10635 if (GNUNET_SYSERR == ret)
10636 {
10637 GNUNET_break (0);
10639 GNUNET_free (cmc);
10640 return;
10641 }
10642 if (GNUNET_NO == ret)
10643 {
10644 /* unencapsulated 'raw' message */
10645 handle_raw_message (cmc, msg);
10646 }
10647}
10648
10649
10656static int
10657check_add_queue_message (void *cls,
10658 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
10659{
10660 struct TransportClient *tc = cls;
10661
10662 if (CT_COMMUNICATOR != tc->type)
10663 {
10664 GNUNET_break (0);
10665 return GNUNET_SYSERR;
10666 }
10668 return GNUNET_OK;
10669}
10670
10671
10677static void
10679{
10680 if (pm->msg_uuid_set)
10681 return;
10682 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
10683 pm->msg_uuid_set = GNUNET_YES;
10684}
10685
10686
10695static struct PendingAcknowledgement *
10697 struct DistanceVectorHop *dvh,
10698 struct PendingMessage *pm)
10699{
10700 struct PendingAcknowledgement *pa;
10701
10702 pa = GNUNET_new (struct PendingAcknowledgement);
10703 pa->queue = queue;
10704 pa->dvh = dvh;
10705 pa->pm = pm;
10706 do
10707 {
10709 &pa->ack_uuid,
10710 sizeof(pa->ack_uuid));
10711 }
10714 &pa->ack_uuid.value,
10715 pa,
10717 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
10718 GNUNET_CONTAINER_MDLL_insert (pm, pm->pa_head, pm->pa_tail, pa);
10719 if (NULL != dvh)
10722 pa->message_size = pm->bytes_msg;
10724 "Waiting for ACKnowledgment `%s' for <%" PRIu64 ">\n",
10726 pm->logging_uuid);
10727 return pa;
10728}
10729
10730
10742static struct PendingMessage *
10744 struct DistanceVectorHop *dvh,
10745 struct PendingMessage *pm)
10746{
10747 struct PendingAcknowledgement *pa;
10748 struct PendingMessage *ff;
10749 uint16_t mtu;
10750 uint16_t msize;
10751
10752 mtu = (UINT16_MAX == queue->mtu)
10753 ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
10754 : queue->mtu;
10756 "Fragmenting message <%" PRIu64
10757 "> with size %u to %s for MTU %u\n",
10758 pm->logging_uuid,
10759 pm->bytes_msg,
10760 GNUNET_i2s (&pm->vl->target),
10761 (unsigned int) mtu);
10764 "Fragmenting message %" PRIu64 " <%" PRIu64
10765 "> with size %u to %s for MTU %u\n",
10766 pm->msg_uuid.uuid,
10767 pm->logging_uuid,
10768 pm->bytes_msg,
10769 GNUNET_i2s (&pm->vl->target),
10770 (unsigned int) mtu);
10771
10772 /* This invariant is established in #handle_add_queue_message() */
10773 GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
10774
10775 /* select fragment for transmission, descending the tree if it has
10776 been expanded until we are at a leaf or at a fragment that is small
10777 enough
10778 */
10779 ff = pm;
10780 msize = ff->bytes_msg;
10781
10782 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
10783 (ff->frag_off == msize) && (NULL != ff->head_frag))
10784 {
10785 ff = ff->head_frag; /* descent into fragmented fragments */
10786 msize = ff->bytes_msg - sizeof(struct TransportFragmentBoxMessage);
10787 }
10788
10789 if (((ff->bytes_msg > mtu) || (pm == ff)) && (ff->frag_off < msize))
10790 {
10791 /* Did not yet calculate all fragments, calculate next fragment */
10792 struct PendingMessage *frag;
10793 struct TransportFragmentBoxMessage tfb;
10794 const char *orig;
10795 char *msg;
10796 uint16_t fragmax;
10797 uint16_t fragsize;
10798 uint16_t msize_ff;
10799 uint16_t xoff = 0;
10800 pm->frag_count++;
10801
10802 orig = (const char *) &ff[1];
10803 msize_ff = ff->bytes_msg;
10804 if (pm != ff)
10805 {
10806 const struct TransportFragmentBoxMessage *tfbo;
10807
10808 tfbo = (const struct TransportFragmentBoxMessage *) orig;
10809 orig += sizeof(struct TransportFragmentBoxMessage);
10810 msize_ff -= sizeof(struct TransportFragmentBoxMessage);
10811 xoff = ntohs (tfbo->frag_off);
10812 }
10813 fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
10814 fragsize = GNUNET_MIN (msize_ff - ff->frag_off, fragmax);
10815 frag =
10816 GNUNET_malloc (sizeof(struct PendingMessage)
10817 + sizeof(struct TransportFragmentBoxMessage) + fragsize);
10819 "3 created pm %p from pm %p storing vl %p from pm %p\n",
10820 frag,
10821 ff,
10822 pm->vl,
10823 pm);
10825 frag->vl = pm->vl;
10826 frag->frag_parent = ff;
10827 frag->timeout = pm->timeout;
10828 frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
10829 frag->pmt = PMT_FRAGMENT_BOX;
10830 msg = (char *) &frag[1];
10831 tfb.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT);
10832 tfb.header.size =
10833 htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
10834 pa = prepare_pending_acknowledgement (queue, dvh, frag);
10835 tfb.ack_uuid = pa->ack_uuid;
10836 tfb.msg_uuid = pm->msg_uuid;
10837 tfb.frag_off = htons (ff->frag_off + xoff);
10838 tfb.msg_size = htons (pm->bytes_msg);
10839 memcpy (msg, &tfb, sizeof(tfb));
10840 memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
10842 ff->tail_frag, frag);
10843 ff->frag_off += fragsize;
10844 ff = frag;
10845 }
10846
10847 /* Move head to the tail and return it */
10851 ff);
10855 ff);
10856
10857 return ff;
10858}
10859
10860
10873static struct PendingMessage *
10875 struct DistanceVectorHop *dvh,
10876 struct PendingMessage *pm)
10877{
10879 struct PendingAcknowledgement *pa;
10880 struct PendingMessage *bpm;
10881 char *msg;
10882
10883 if ((PMT_CORE != pm->pmt) && (PMT_DV_BOX != pm->pmt))
10884 return pm; /* already fragmented or reliability boxed, or control message:
10885 do nothing */
10886 if (NULL != pm->bpm)
10887 return pm->bpm; /* already computed earlier: do nothing */
10888 // TODO I guess we do not need this assertion. We might have a DLL with
10889 // fragments, because the MTU changed, and we do not need to fragment anymore.
10890 // But we should keep the fragments until message was completed, because
10891 // the MTU might change again.
10892 // GNUNET_assert (NULL == pm->head_frag);
10893 if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
10894 {
10895 /* failed hard */
10896 GNUNET_break (0);
10898 return NULL;
10899 }
10900
10902
10903 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
10904 + pm->bytes_msg);
10906 "4 created pm %p storing vl %p from pm %p\n",
10907 bpm,
10908 pm->vl,
10909 pm);
10911 bpm->vl = pm->vl;
10912 bpm->frag_parent = pm;
10913 // Why was this needed?
10914 // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
10915 bpm->timeout = pm->timeout;
10917 bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
10919 rbox.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX);
10920 rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
10921 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
10922
10923 rbox.ack_uuid = pa->ack_uuid;
10924 msg = (char *) &bpm[1];
10925 memcpy (msg, &rbox, sizeof(rbox));
10926 memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
10927 pm->bpm = bpm;
10929 "Preparing reliability box for message <%" PRIu64
10930 "> of size %d (%d) to %s on queue %s\n",
10931 pm->logging_uuid,
10932 pm->bytes_msg,
10933 ntohs (((const struct GNUNET_MessageHeader *) &pm[1])->size),
10934 GNUNET_i2s (&pm->vl->target),
10935 queue->address);
10936 return bpm;
10937}
10938
10939
10940static void
10943{
10944 struct VirtualLink *vl = pm->vl;
10945 struct PendingMessage *pos;
10946
10947 /* re-insert sort in neighbour list */
10951 pm);
10952 pos = vl->pending_msg_tail;
10953 while ((NULL != pos) &&
10955 pos = pos->prev_vl;
10959 pos,
10960 pm);
10961}
10962
10963
10964static unsigned int
10966{
10967 struct PendingMessage *pos;
10969
10970 pos = pm->head_frag;
10971 while (NULL != pos)
10972 {
10973 if (pos->frags_in_flight_round == pm->frags_in_flight_round ||
10974 GNUNET_NO == check_next_attempt_tree (pos, root))
10976 else
10977 {
10979 break;
10980 }
10981 pos = pos->next_frag;
10982 }
10983
10984 return frags_in_flight;
10985}
10986
10987
10988static void
10990{
10991 struct PendingMessage *pos;
10992
10993 pos = pm->head_frag;
10994 while (NULL != pos)
10995 {
10996 pos->frags_in_flight_round = pm->frags_in_flight_round;
10998 pos = pos->next_frag;
10999 }
11000}
11001
11002
11011static void
11014{
11015 if (NULL == pm->frag_parent)
11016 {
11019 "Next attempt for message <%" PRIu64 "> set to %" PRIu64 "\n",
11020 pm->logging_uuid,
11023 }
11024 else if ((PMT_RELIABILITY_BOX == pm->pmt) || (PMT_DV_BOX == pm->pmt))// || (PMT_FRAGMENT_BOX == pm->pmt))
11025 {
11026 struct PendingMessage *root = pm->frag_parent;
11027
11028 while (NULL != root->frag_parent)
11029 root = root->frag_parent;
11031 "Next attempt for root message <%" PRIu64 "> set to %s\n",
11032 root->logging_uuid,
11034 root->next_attempt = next_attempt;
11036 }
11037 else
11038 {
11039 struct PendingMessage *root = pm->frag_parent;
11040
11041 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11042 root = root->frag_parent;
11043
11045 "frag_count next attempt %u\n",
11046 root->frag_count);
11047
11048 if (GNUNET_NO == root->frags_in_flight)
11049 {
11050 root->next_attempt = next_attempt;
11052 root->frags_in_flight_round++;
11054 "Next attempt for fragmented message <%" PRIu64 "> (<%" PRIu64
11055 ">)set to %" PRIu64 "\n",
11056 pm->logging_uuid,
11057 root->logging_uuid,
11059 }
11060
11061 pm->next_attempt = root->next_attempt;
11062 pm->frags_in_flight_round = root->frags_in_flight_round;
11064
11065 if (root->bytes_msg == root->frag_off)
11066 root->frags_in_flight = check_next_attempt_tree (root, root);
11067 else
11069
11070 if (GNUNET_NO == root->frags_in_flight)
11071 {
11073 "We have no fragments in flight for message %" PRIu64
11074 ", reorder root! Next attempt is %" PRIu64 "\n",
11075 root->logging_uuid,
11077 if (PMT_DV_BOX == root->pmt)
11078 root = root->frag_parent;
11079 reorder_root_pm (root, root->next_attempt);
11080 // root->next_attempt = GNUNET_TIME_UNIT_ZERO_ABS;
11081 }
11082 else
11083 {
11084 double factor = ((double) root->frag_count - 1)
11085 / (double) root->frag_count;
11086 struct GNUNET_TIME_Relative s1;
11087 struct GNUNET_TIME_Relative s2;
11088 struct GNUNET_TIME_Relative plus_mean =
11091 next_attempt);
11092
11094 "frag_count %u after factor\n",
11095 root->frag_count);
11097 factor);
11098 s2 = GNUNET_TIME_relative_divide (plus,
11099 root->frag_count);
11100 plus_mean = GNUNET_TIME_relative_add (s1, s2);
11103 "We have fragments in flight for message %" PRIu64
11104 ", do not reorder root! Actual next attempt %" PRIu64 "\n",
11105 root->logging_uuid,
11107 }
11108 }
11109}
11110
11111
11116{
11120 struct PendingMessage *best;
11121
11125 struct DistanceVectorHop *dvh;
11126
11130 size_t real_overhead;
11131
11135 unsigned int consideration_counter;
11136
11140 int frag;
11141
11145 int relb;
11146
11150 int to_early;
11151
11155 unsigned int frags_in_flight;
11156
11161};
11162
11163
11175static void
11177 struct Queue *queue,
11178 struct VirtualLink *vl,
11179 struct DistanceVectorHop *dvh,
11180 size_t overhead)
11181{
11182 struct GNUNET_TIME_Absolute now;
11183
11184 now = GNUNET_TIME_absolute_get ();
11185 sc->to_early = GNUNET_NO;
11186 sc->frags_in_flight = GNUNET_NO;
11187 for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
11188 pos = pos->next_vl)
11189 {
11190 size_t real_overhead = overhead;
11191 int frag;
11192 int relb;
11193
11194 if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
11195 {
11197 "DV messages must not be DV-routed to next hop!\n");
11198 continue; /* DV messages must not be DV-routed to next hop! */
11199 }
11200 if (pos->next_attempt.abs_value_us > now.abs_value_us)
11201 {
11202 if (GNUNET_YES == pos->frags_in_flight)
11203 {
11204 sc->frags_in_flight = GNUNET_YES;
11206 "Fragments in flight for message %" PRIu64 "\n",
11207 pos->logging_uuid);
11208 }
11209 else
11210 {
11212 "Maybe too early, because message are sorted by next_attempt, if there are no fragments in flight.Checked message %"
11213 PRIu64 "\n",
11214 pos->logging_uuid);
11215 sc->to_early = GNUNET_YES;
11216 sc->to_early_retry_delay = GNUNET_TIME_absolute_get_remaining (
11217 pos->next_attempt);
11218 continue;
11219 }
11220 // break; /* too early for all messages, they are sorted by next_attempt */
11221 }
11222 if (NULL != pos->qe)
11223 {
11225 "not eligible\n");
11226 continue; /* not eligible */
11227 }
11228 sc->consideration_counter++;
11229 /* determine if we have to fragment, if so add fragmentation
11230 overhead! */
11232 "check %" PRIu64 " for sc->best\n",
11233 pos->logging_uuid);
11234 frag = GNUNET_NO;
11235 if (((0 != queue->mtu) &&
11236 (pos->bytes_msg + real_overhead > queue->mtu)) ||
11237 (pos->bytes_msg > UINT16_MAX - sizeof(struct
11239 ||
11240 (NULL != pos->head_frag /* fragments already exist, should
11241 respect that even if MTU is UINT16_MAX for
11242 this queue */))
11243 {
11245 "fragment msg with size %u, realoverhead is %lu\n",
11246 pos->bytes_msg,
11247 real_overhead);
11248 frag = GNUNET_YES;
11249 if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
11250 {
11251 /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
11252 header without the ACK UUID when using a *reliable* channel! */
11253 }
11254 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11255 }
11256 /* determine if we have to reliability-box, if so add reliability box
11257 overhead */
11258 relb = GNUNET_NO;
11259 if ((GNUNET_NO == frag) &&
11260 (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
11261 (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
11262 {
11263 real_overhead += sizeof(struct TransportReliabilityBoxMessage);
11264
11265 if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu))
11266 {
11267 frag = GNUNET_YES;
11268 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11269 }
11270 else
11271 {
11272 relb = GNUNET_YES;
11273 }
11275 "Create reliability box of msg with size %u, realoverhead is %lu %u %u %u\n",
11276 pos->bytes_msg,
11277 real_overhead,
11278 queue->mtu,
11279 frag,
11280 relb);
11281 }
11282
11283 /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
11284 message would beat it! */
11285 if (GNUNET_NO == sc->frags_in_flight && NULL != sc->best)
11286 {
11287 /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
11288 OPTIMIZE-ME: This is a heuristic, which so far has NOT been
11289 experimentally validated. There may be some huge potential for
11290 improvement here. Also, we right now only compare how well the
11291 given message fits _this_ queue, and do not consider how well other
11292 queues might suit the message. Taking other queues into consideration
11293 may further improve the result, but could also be expensive
11294 in terms of CPU time. */
11295 long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
11296 long long pm_score = frag * 40 + relb * 20 + real_overhead;
11297 long long time_delta =
11298 (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
11299 / 1000LL;
11300
11301 /* "time_delta" considers which message has been 'ready' for transmission
11302 for longer, if a message has a preference for low latency, increase
11303 the weight of the time_delta by 10x if it is favorable for that message */
11304 if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11305 (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
11306 time_delta *= 10; /* increase weight (always, both are low latency) */
11307 else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11308 (time_delta > 0))
11309 time_delta *= 10; /* increase weight, favors 'pos', which is low latency */
11310 else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11311 (time_delta < 0))
11312 time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */
11313 if (0 != queue->mtu)
11314 {
11315 /* Grant bonus if we are below MTU, larger bonus the closer we will
11316 be to the MTU */
11317 if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
11318 sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
11319 if (queue->mtu > real_overhead + pos->bytes_msg)
11320 pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
11321 }
11322 if (sc_score + time_delta > pm_score)
11323 {
11325 "sc_score of %" PRIu64 " larger, keep sc->best %" PRIu64
11326 "\n",
11327 pos->logging_uuid,
11328 sc->best->logging_uuid);
11329 continue; /* sc_score larger, keep sc->best */
11330 }
11331 }
11332 sc->best = pos;
11333 sc->dvh = dvh;
11334 sc->frag = frag;
11335 sc->relb = relb;
11336 sc->real_overhead = real_overhead;
11337 }
11338}
11339
11340
11351static void
11352extract_box_cb (void *cls,
11353 struct Neighbour *next_hop,
11354 const struct GNUNET_MessageHeader *hdr,
11356{
11357 struct PendingMessageScoreContext *sc = cls;
11358 struct PendingMessage *pm = sc->best;
11359 struct PendingMessage *bpm;
11360 uint16_t bsize = ntohs (hdr->size);
11361
11362 GNUNET_assert (NULL == pm->bpm);
11363 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
11365 "5 created pm %p storing vl %p from pm %p\n",
11366 bpm,
11367 pm->vl,
11368 pm);
11370 bpm->pmt = PMT_DV_BOX;
11371 bpm->vl = pm->vl;
11372 bpm->timeout = pm->timeout;
11373 bpm->bytes_msg = bsize;
11374 bpm->frag_parent = pm;
11377 "Creating DV Box %" PRIu64 " for original message %" PRIu64
11378 " (next hop is %s)\n",
11380 pm->logging_uuid,
11381 GNUNET_i2s (&next_hop->pid));
11382 memcpy (&bpm[1], hdr, bsize);
11383 pm->bpm = bpm;
11384}
11385
11386
11402static void
11403transmit_on_queue (void *cls)
11404{
11405 struct Queue *queue = cls;
11406 struct Neighbour *n = queue->neighbour;
11408 struct PendingMessage *pm;
11409
11410 queue->transmit_task = NULL;
11411 if (NULL == n->vl)
11412 {
11414 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
11415 GNUNET_i2s (&n->pid),
11416 queue->address);
11417 queue->idle = GNUNET_YES;
11418 return;
11419 }
11420 memset (&sc, 0, sizeof(sc));
11421 select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
11422 if (NULL == sc.best)
11423 {
11424 /* Also look at DVH that have the n as first hop! */
11425 for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
11426 dvh = dvh->next_neighbour)
11427 {
11429 queue,
11430 dvh->dv->vl,
11431 dvh,
11432 sizeof(struct GNUNET_PeerIdentity)
11433 * (1 + dvh->distance)
11434 + sizeof(struct TransportDVBoxMessage)
11435 + sizeof(struct TransportDVBoxPayloadP));
11436 }
11437 }
11438 if (NULL == sc.best)
11439 {
11440 /* no message pending, nothing to do here! */
11442 "No pending messages, queue `%s' to %s now idle\n",
11443 queue->address,
11444 GNUNET_i2s (&n->pid));
11445 if (GNUNET_YES == sc.to_early)
11446 schedule_transmit_on_queue (sc.to_early_retry_delay,
11447 queue,
11449 queue->idle = GNUNET_YES;
11450 return;
11451 }
11452 /* There is a message pending, we are certainly not idle */
11453 queue->idle = GNUNET_NO;
11454
11455 /* Given selection in `sc`, do transmission */
11456 pm = sc.best;
11458 "Selected message <%" PRIu64 ">\n",
11459 pm->logging_uuid);
11460 if (NULL != sc.dvh)
11461 {
11463 "Is this %u a DV box?\n",
11464 pm->pmt);
11465 GNUNET_assert (PMT_DV_BOX != pm->pmt);
11466 if ((NULL != sc.best->bpm) && (sc.best->bpm->used_dvh != sc.dvh))
11467 {
11469 "Discard old box, because we have a new DV path.\n");
11470 free_pending_message (sc.best->bpm);
11471 sc.best->bpm = NULL;
11472 }
11473
11474 if (NULL == sc.best->bpm)
11475 {
11477 "encapsulate_for_dv 2\n");
11478 encapsulate_for_dv (sc.dvh->dv,
11479 1,
11480 &sc.dvh,
11481 (const struct GNUNET_MessageHeader *) &sc.best[1],
11483 &sc,
11484 RMO_NONE,
11485 GNUNET_NO);
11486 GNUNET_assert (NULL != sc.best->bpm);
11488 "%lu %lu %lu %lu %u\n",
11489 sizeof(struct GNUNET_PeerIdentity),
11490 sizeof(struct TransportDVBoxMessage),
11491 sizeof(struct TransportDVBoxPayloadP),
11492 sizeof(struct TransportFragmentBoxMessage),
11493 ((const struct GNUNET_MessageHeader *) &sc.best[1])->size);
11494 sc.best->bpm->used_dvh = sc.dvh;
11495 }
11496 pm = sc.best->bpm;
11497 }
11498 if (GNUNET_YES == sc.frag)
11499 {
11500 pm = fragment_message (queue, sc.dvh, pm);
11501 if (NULL == pm)
11502 {
11504 "Fragmentation failed queue %s to %s for <%" PRIu64
11505 ">, trying again\n",
11506 queue->address,
11507 GNUNET_i2s (&n->pid),
11508 sc.best->logging_uuid);
11510 queue,
11512 return;
11513 }
11514 }
11515 else if (GNUNET_YES == sc.relb)
11516 {
11518 if (NULL == pm)
11519 {
11520 /* Reliability boxing failed, try next message... */
11521 GNUNET_log (
11523 "Reliability boxing failed queue %s to %s for <%" PRIu64
11524 ">, trying again\n",
11525 queue->address,
11526 GNUNET_i2s (&n->pid),
11527 sc.best->logging_uuid);
11529 queue,
11531 return;
11532 }
11533 }
11534
11535 /* Pass 'pm' for transission to the communicator */
11536 GNUNET_log (
11538 "Passing message <%" PRIu64
11539 "> to queue %s for peer %s (considered %u others)\n",
11540 pm->logging_uuid,
11541 queue->address,
11542 GNUNET_i2s (&n->pid),
11543 sc.consideration_counter);
11544
11545 /* Flow control: increment amount of traffic sent; if we are routing
11546 via DV (and thus the ultimate target of the pending message is for
11547 a different virtual link than the one of the queue), then we need
11548 to use up not only the window of the direct link but also the
11549 flow control window for the DV link! */
11550 pm->vl->outbound_fc_window_size_used += pm->bytes_msg;
11551
11552 if (pm->vl != queue->neighbour->vl)
11553 {
11554 /* If the virtual link of the queue differs, this better be distance
11555 vector routing! */
11556 GNUNET_assert (NULL != sc.dvh);
11557 /* If we do distance vector routing, we better not do this for a
11558 message that was itself DV-routed */
11559 GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
11560 /* We use the size of the unboxed message here, to avoid counting
11561 the DV-Box header which is eaten up on the way by intermediaries */
11562 queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
11563 }
11564 else
11565 {
11566 GNUNET_assert (NULL == sc.dvh);
11567 }
11568
11569 queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
11570
11571 /* Check if this transmission somehow conclusively finished handing 'pm'
11572 even without any explicit ACKs */
11573 if ((PMT_CORE == pm->pmt) ||
11574 (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
11575 {
11577 }
11578 else
11579 {
11580 struct GNUNET_TIME_Relative wait_duration;
11581 unsigned int wait_multiplier;
11582
11583 if (PMT_FRAGMENT_BOX == pm->pmt)
11584 {
11585 struct PendingMessage *root;
11586
11587 root = pm->frag_parent;
11588 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11589 root = root->frag_parent;
11590
11591 wait_multiplier = (unsigned int) ceil ((double) root->bytes_msg
11592 / ((double) root->frag_off
11593 / (double) root->frag_count))
11594 * 4;
11595 }
11596 else
11597 {
11598 // No fragments, we use 4 RTT before retransmitting.
11599 wait_multiplier = 4;
11600 }
11601
11602 // Depending on how much pending message the VirtualLink is queueing, we wait longer.
11603 // wait_multiplier = wait_multiplier * pm->vl->pending_msg_num;
11604
11606 "Wait multiplier %u\n",
11607 wait_multiplier);
11608
11609 /* Message not finished, waiting for acknowledgement.
11610 Update time by which we might retransmit 's' based on queue
11611 characteristics (i.e. RTT); it takes one RTT for the message to
11612 arrive and the ACK to come back in the best case; but the other
11613 side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
11614 retransmitting.
11615
11616 OPTIMIZE: Note that in the future this heuristic should likely
11617 be improved further (measure RTT stability, consider message
11618 urgency and size when delaying ACKs, etc.) */
11619
11620 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
11621 queue->pd.aged_rtt.rel_value_us)
11622 wait_duration = queue->pd.aged_rtt;
11623 else
11624 {
11625 wait_duration = DEFAULT_ACK_WAIT_DURATION;
11626 wait_multiplier = 4;
11627 }
11628 {
11631 wait_duration, wait_multiplier));
11633 wait_duration, wait_multiplier);
11635 "Waiting %s for ACK until %s\n",
11640 GNUNET_TIME_relative_multiply (wait_duration,
11641 wait_multiplier))
11642 );
11643 }
11644 }
11645 /* finally, re-schedule queue transmission task itself */
11647 queue,
11649}
11650
11651
11658static void
11659handle_del_queue_message (void *cls,
11660 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
11661{
11662 struct TransportClient *tc = cls;
11663
11664 if (CT_COMMUNICATOR != tc->type)
11665 {
11666 GNUNET_break (0);
11668 return;
11669 }
11670 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11671 queue = queue->next_client)
11672 {
11673 struct Neighbour *neighbour = queue->neighbour;
11674
11675 if ((ntohl (dqm->qid) != queue->qid) ||
11676 (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
11677 continue;
11679 "Dropped queue %s to peer %s\n",
11680 queue->address,
11681 GNUNET_i2s (&neighbour->pid));
11682 free_queue (queue);
11684 return;
11685 }
11686 GNUNET_break (0);
11688}
11689
11690
11691static void
11693 struct TransportClient *tc)
11694{
11695 struct PendingMessage *pm;
11696
11697 GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
11698 qe->queue->queue_tail,
11699 qe);
11700 qe->queue->queue_length--;
11701 tc->details.communicator.total_queue_length--;
11703 "Received ACK on queue %s (QID %u) to peer %s (new length: %u/%u)\n",
11704 qe->queue->address,
11705 qe->queue->qid,
11706 GNUNET_i2s (&qe->queue->neighbour->pid),
11707 qe->queue->queue_length,
11708 tc->details.communicator.total_queue_length);
11709
11710 /* if applicable, resume transmissions that waited on ACK */
11712 tc->details.communicator.total_queue_length)
11713 {
11714 /* Communicator dropped below threshold, resume all queues
11715 incident with this client! */
11717 GST_stats,
11718 "# Transmission throttled due to communicator queue limit",
11719 -1,
11720 GNUNET_NO);
11721 for (struct Queue *queue = tc->details.communicator.queue_head;
11722 NULL != queue;
11723 queue = queue->next_client)
11724 {
11726 queue,
11728 }
11729 }
11730 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
11731 {
11732 /* queue dropped below threshold; only resume this one queue */
11734 "# Transmission throttled due to queue queue limit",
11735 -1,
11736 GNUNET_NO);
11738 qe->queue,
11740 }
11741 else if (1 == qe->queue->q_capacity)
11742 {
11743 // TODO I guess this will never happen, because the communicator triggers this by updating its queue length itself.
11745 "Transmission rescheduled due to communicator message queue with qid %u has capacity %"
11746 PRIu64 ".\n",
11747 qe->queue->qid,
11748 qe->queue->q_capacity);
11749 /* message queue has capacity; only resume this one queue */
11750 /* queue dropped below threshold; only resume this one queue */
11752 "# Transmission throttled due to message queue capacity",
11753 -1,
11754 GNUNET_NO);
11756 qe->queue,
11758 }
11759
11760 if (NULL != (pm = qe->pm))
11761 {
11762 struct VirtualLink *vl;
11763
11764 // GNUNET_assert (qe == pm->qe);
11765 pm->qe = NULL;
11766 /* If waiting for this communicator may have blocked transmission
11767 of pm on other queues for this neighbour, force schedule
11768 transmit on queue for queues of the neighbour */
11769 if (NULL == pm->frag_parent)
11770 {
11771 vl = pm->vl;
11772 if ((NULL != vl) &&
11773 (NULL != vl->pending_msg_head) &&
11774 (vl->pending_msg_head == pm))
11776 }
11777 }
11778 GNUNET_free (qe);
11779}
11780
11781
11788static void
11789handle_send_message_ack (void *cls,
11790 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
11791{
11792 struct TransportClient *tc = cls;
11793 struct QueueEntry *qe;
11794
11795 if (CT_COMMUNICATOR != tc->type)
11796 {
11797 GNUNET_break (0);
11799 return;
11800 }
11801
11802 /* find our queue entry matching the ACK */
11803 qe = NULL;
11805 "Looking for queue for PID %s\n",
11806 GNUNET_i2s (&sma->receiver));
11807 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11808 queue = queue->next_client)
11809 {
11810 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
11811 continue;
11813 "Found PID %s\n",
11814 GNUNET_i2s (&queue->neighbour->pid));
11815
11816
11817 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
11818 qep = qep->next)
11819 {
11820 if (qep->mid != GNUNET_ntohll (sma->mid) || queue->qid != ntohl (
11821 sma->qid))
11822 continue;
11824 "QueueEntry MID: %" PRIu64 " on queue QID: %u, Ack MID: %"
11825 PRIu64 " Ack QID %u\n",
11826 qep->mid,
11827 queue->qid,
11828 GNUNET_ntohll (sma->mid),
11829 ntohl (sma->qid));
11830 qe = qep;
11831 if ((NULL != qe->pm) && (qe->pm->qe != qe))
11833 "For pending message %" PRIu64 " we had retransmissions.\n",
11834 qe->pm->logging_uuid);
11835 break;
11836 }
11837 }
11838 if (NULL == qe)
11839 {
11841 "No QueueEntry found for Ack MID %" PRIu64 " QID: %u\n",
11842 GNUNET_ntohll (sma->mid),
11843 ntohl (sma->qid));
11844 // TODO I guess this can happen, if the Ack from the peer comes before the Ack from the queue.
11845 // Update: Maybe QueueEntry was accidentally freed during freeing PendingMessage.
11846 /* this should never happen */
11847 // GNUNET_break (0);
11848 // GNUNET_SERVICE_client_drop (tc->client);
11850 return;
11851 }
11854}
11855
11856
11862static void
11863handle_burst_finished (void *cls,
11864 const struct GNUNET_TRANSPORT_BurstFinished *bf)
11865{
11867}
11868
11869
11879static int
11880notify_client_queues (void *cls,
11881 const struct GNUNET_PeerIdentity *pid,
11882 void *value)
11883{
11884 struct TransportClient *tc = cls;
11885 struct Neighbour *neighbour = value;
11886
11887 GNUNET_assert (CT_MONITOR == tc->type);
11888 for (struct Queue *q = neighbour->queue_head; NULL != q;
11889 q = q->next_neighbour)
11890 {
11891 struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
11892 .cs = q->cs,
11893 .num_msg_pending = q->num_msg_pending,
11894 .num_bytes_pending = q->num_bytes_pending };
11895
11896 notify_monitor (tc, pid, q->address, q->nt, &me);
11897 }
11898 return GNUNET_OK;
11899}
11900
11901
11908static void
11909handle_monitor_start (void *cls,
11911{
11912 struct TransportClient *tc = cls;
11913
11914 if (CT_NONE != tc->type)
11915 {
11916 GNUNET_break (0);
11918 return;
11919 }
11920 tc->type = CT_MONITOR;
11921 tc->details.monitor.peer = start->peer;
11922 tc->details.monitor.one_shot = ntohl (start->one_shot);
11926}
11927
11928
11936static struct TransportClient *
11937lookup_communicator (const char *prefix)
11938{
11939 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
11940 {
11941 if (CT_COMMUNICATOR != tc->type)
11942 continue;
11943 if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
11944 return tc;
11945 }
11946 GNUNET_log (
11948 "Someone suggested use of communicator for `%s', but we do not have such a communicator!\n",
11949 prefix);
11950 return NULL;
11951}
11952
11953
11961static void
11962suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address)
11963{
11964 static uint32_t idgen = 0;
11965 struct TransportClient *tc;
11966 char *prefix;
11967 struct GNUNET_TRANSPORT_CreateQueue *cqm;
11968 struct GNUNET_MQ_Envelope *env;
11969 size_t alen;
11970
11972 if (NULL == prefix)
11973 {
11974 GNUNET_break (0); /* We got an invalid address!? */
11975 return;
11976 }
11978 if (NULL == tc)
11979 {
11981 "# Suggestions ignored due to missing communicator",
11982 1,
11983 GNUNET_NO);
11985 "Cannot connect to %s at `%s', no matching communicator present\n",
11986 GNUNET_i2s (pid),
11987 address);
11989 return;
11990 }
11991 /* forward suggestion for queue creation to communicator */
11993 "Request #%u for `%s' communicator to create queue to `%s' at `%s'\n",
11994 (unsigned int) idgen,
11995 prefix,
11996 GNUNET_i2s (pid),
11997 address);
11999 alen = strlen (address) + 1;
12000 env =
12002 cqm->request_id = htonl (idgen++);
12003 cqm->receiver = *pid;
12004 memcpy (&cqm[1], address, alen);
12005 GNUNET_MQ_send (tc->mq, env);
12006}
12007
12008
12016static void
12018{
12020 struct GNUNET_TIME_Absolute monotonic_time;
12021
12022 if (NULL != vs->revalidation_task)
12023 {
12024 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
12025 vs->revalidation_task = NULL;
12026 }
12027 /*memcpy (&hkey,
12028 &hc,
12029 sizeof (hkey));*/
12031 "Remove key %s for address %s map size %u contains %u\n",
12032 GNUNET_h2s (&vs->hc),
12033 vs->address,
12036 &vs->hc));
12038
12040 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
12041 vs->last_challenge_use.abs_value_us)
12042 {
12043 vs->first_challenge_use = monotonic_time;
12044 }
12045 vs->last_challenge_use = monotonic_time;
12046 tvc.header.type =
12048 tvc.header.size = htons (sizeof(tvc));
12049 tvc.reserved = htonl (0);
12050 tvc.challenge = vs->challenge;
12051 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
12053 "Sending address validation challenge %s to %s\n",
12055 GNUNET_i2s (&q->neighbour->pid));
12056 queue_send_msg (q, NULL, &tvc, sizeof(tvc));
12057}
12058
12059
12065static void
12066validation_start_cb (void *cls)
12067{
12068 struct ValidationState *vs;
12069 struct Queue *q;
12071 GST_cfg);
12072
12073 (void) cls;
12074 validation_task = NULL;
12076 /* drop validations past their expiration */
12077 while (
12078 (NULL != vs) &&
12080 {
12082 "Validation response %s cleaned up\n",
12083 GNUNET_sh2s (&vs->challenge.value));
12086 }
12087 if (NULL == vs)
12088 {
12090 "Address validation task not scheduled anymore, nothing to do\n");
12091 return; /* woopsie, no more addresses known, should only
12092 happen if we're really a lonely peer */
12093 }
12094 q = find_queue (&vs->pid, vs->address);
12095 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
12096 {
12098 "To early to start next address validation for challenge %s\n",
12099 GNUNET_sh2s (&vs->challenge.value));
12100 return;
12101 }
12102 if (NULL == q)
12103 {
12104 vs->awaiting_queue = GNUNET_YES;
12105 suggest_to_connect (&vs->pid, vs->address);
12106 }
12107 else
12109 /* Finally, reschedule next attempt */
12110 vs->challenge_backoff =
12111 GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
12114 "Address validation task will run again in %s\n",
12115 GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
12116 GNUNET_YES));
12119 vs->challenge_backoff));
12120}
12121
12122
12127{
12131 struct Queue *q;
12132
12136 unsigned int quality_count;
12137
12141 unsigned int num_queues;
12142
12147 unsigned int k;
12148};
12149
12150
12162static int
12163check_connection_quality (void *cls,
12164 const struct GNUNET_PeerIdentity *pid,
12165 void *value)
12166{
12167 struct QueueQualityContext *ctx = cls;
12168 struct Neighbour *n = value;
12169 int do_inc;
12170
12171 (void) pid;
12172 do_inc = GNUNET_NO;
12173 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
12174 {
12175 ctx->num_queues++;
12176 if (0 == ctx->k--)
12177 ctx->q = q;
12178 /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
12179 statistics and consider those as well here? */
12180 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
12181 do_inc = GNUNET_YES;
12182 }
12183 if (GNUNET_YES == do_inc)
12184 ctx->quality_count++;
12185 return GNUNET_OK;
12186}
12187
12188
12200static void
12201start_dv_learn (void *cls);
12202
12203
12204struct SignDvInitCls
12205{
12207 struct LearnLaunchEntry *lle;
12208 struct QueueQualityContext qqc;
12209 struct PilsRequest *pr;
12210};
12211
12212
12213static void
12214sign_dv_init_cb (void *cls,
12215 const struct GNUNET_PeerIdentity *pid,
12216 const struct GNUNET_CRYPTO_EddsaSignature *sig)
12217{
12218 struct SignDvInitCls *sign_dv_init_cls = cls;
12219 struct TransportDVLearnMessage dvl = sign_dv_init_cls->dvl;
12220 struct LearnLaunchEntry *lle = sign_dv_init_cls->lle;
12221 struct QueueQualityContext qqc = sign_dv_init_cls->qqc;
12222
12223 sign_dv_init_cls->pr->op = NULL;
12226 sign_dv_init_cls->pr);
12227 GNUNET_free (sign_dv_init_cls->pr);
12228
12229 dvl.init_sig = *sig;
12231 dvl.challenge = lle->challenge;
12232
12233 qqc.quality_count = 0;
12235 qqc.num_queues = 0;
12236 qqc.q = NULL;
12239 &qqc);
12240 GNUNET_assert (NULL != qqc.q);
12241
12242 /* Do this as close to transmission time as possible! */
12244
12245 queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
12246 /* reschedule this job, randomizing the time it runs (but no
12247 actual backoff!) */
12251 NULL);
12252}
12253
12254
12266static void
12267start_dv_learn (void *cls)
12268{
12269 struct LearnLaunchEntry *lle;
12270 struct QueueQualityContext qqc;
12271 struct TransportDVLearnMessage dvl;
12272
12273 (void) cls;
12274 dvlearn_task = NULL;
12276 return; /* lost all connectivity, cannot do learning */
12277 qqc.quality_count = 0;
12278 qqc.num_queues = 0;
12282 &qqc);
12284 {
12285 struct GNUNET_TIME_Relative delay;
12286 unsigned int factor;
12287
12288 /* scale our retries by how far we are above the threshold */
12292 "At connection quality %u, will launch DV learn in %s\n",
12293 qqc.quality_count,
12296 return;
12297 }
12298 /* remove old entries in #dvlearn_map if it has grown too big */
12299 while (MAX_DV_LEARN_PENDING <=
12301 {
12302 lle = lle_tail;
12305 &lle->challenge.value,
12306 lle));
12308 GNUNET_free (lle);
12309 }
12310 /* setup data structure for learning */
12311 lle = GNUNET_new (struct LearnLaunchEntry);
12313 &lle->challenge,
12314 sizeof(lle->challenge));
12316 "Starting launch DV learn with challenge %s\n",
12317 GNUNET_sh2s (&lle->challenge.value));
12322 &lle->challenge.value,
12323 lle,
12326 dvl.header.size = htons (sizeof(dvl));
12327 dvl.num_hops = htons (0);
12328 dvl.bidirectional = htons (0);
12330 dvl.monotonic_time =
12332 {
12333 struct DvInitPS dvip = {
12334 .purpose.purpose = htonl (
12336 .purpose.size = htonl (sizeof(dvip)),
12337 .monotonic_time = dvl.monotonic_time,
12338 .challenge = lle->challenge
12339 };
12340 struct SignDvInitCls *sign_dv_init_cls;
12341
12342 sign_dv_init_cls = GNUNET_new (struct SignDvInitCls);
12343 sign_dv_init_cls->dvl = dvl;
12344 sign_dv_init_cls->lle = lle;
12345 sign_dv_init_cls->qqc = qqc;
12346 sign_dv_init_cls->pr = GNUNET_new (struct PilsRequest);
12349 sign_dv_init_cls->pr);
12350 sign_dv_init_cls->pr->op =
12352 &dvip.purpose,
12354 sign_dv_init_cls);
12355 }
12356}
12357
12358
12366static char *
12368{
12369 const char *colon;
12370 char *colon_rest;
12371 size_t colon_rest_length;
12372 char *address_without_port;
12373
12374 colon = strchr (address,':');
12375 colon_rest = GNUNET_strndup (address, colon - address);
12376 colon_rest_length = strlen (colon_rest);
12377 address_without_port = GNUNET_strndup (&colon_rest[4], colon_rest_length - 4);
12378 GNUNET_free (colon_rest);
12379
12380 return address_without_port;
12381}
12382
12383
12393static int
12395 const struct GNUNET_PeerIdentity *pid,
12396 void *value)
12397{
12398 struct Queue *q = cls;
12399 struct ValidationState *vs = value;
12400 char *address_without_port_vs;
12401 char *address_without_port_q;
12402 int success = GNUNET_YES;
12403
12404 // TODO Check if this is really necessary.
12405 address_without_port_vs = get_address_without_port (vs->address);
12406 address_without_port_q = get_address_without_port (q->address);
12407
12409 "Check validation request pending for `%s' at `%s'/`%s' (vs)/(q)\n",
12410 GNUNET_i2s (pid),
12411 address_without_port_vs,
12412 address_without_port_q);
12413 (void) pid;
12414 if ((GNUNET_YES == vs->awaiting_queue) &&
12415 (0 == strcmp (address_without_port_vs, address_without_port_q)))
12416 {
12417
12418 vs->awaiting_queue = GNUNET_NO;
12420 success = GNUNET_NO;
12421 }
12422
12423 GNUNET_free (address_without_port_vs);
12424 GNUNET_free (address_without_port_q);
12425 return success;
12426}
12427
12428
12437static void
12438neighbour_dv_monotime_cb (void *cls,
12439 const struct GNUNET_PEERSTORE_Record *record,
12440 const char *emsg)
12441{
12442 struct Neighbour *n = cls;
12443 struct GNUNET_TIME_AbsoluteNBO *mtbe;
12444
12445 (void) emsg;
12446 if (NULL == record)
12447 {
12448 /* we're done with #neighbour_dv_monotime_cb() invocations,
12449 continue normal processing */
12450 n->get = NULL;
12452 return;
12453 }
12454 if (0 == record->value_size)
12455 {
12457 GNUNET_break (0);
12458 return;
12459 }
12460 mtbe = record->value;
12465}
12466
12467
12468static void
12470 const struct GNUNET_PeerIdentity *pid,
12471 const char *uri)
12472{
12473 struct Queue *queue = cls;
12474 struct sockaddr_in v4;
12475 const char *slash;
12476 char *address_uri;
12477 char *prefix;
12478 char *uri_without_port;
12479 char *address_uri_without_port;
12480
12481 slash = strrchr (uri, '/');
12482 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
12483 GNUNET_assert (NULL != slash);
12484 slash++;
12485 GNUNET_asprintf (&address_uri,
12486 "%s-%s",
12487 prefix,
12488 slash);
12489
12491 "1 not global natted_address %u %s %s %s\n",
12492 queue->is_global_natted,
12493 uri,
12494 queue->address,
12495 slash);
12496
12497 uri_without_port = get_address_without_port (address_uri);
12498 if (1 != inet_pton (AF_INET, uri_without_port, &v4.sin_addr))
12499 {
12501 GNUNET_free (address_uri);
12502 GNUNET_free (uri_without_port);
12503 return;
12504 }
12505
12507 "2 not global natted_address %u %s %s\n",
12508 queue->is_global_natted,
12509 uri,
12510 queue->address);
12511
12512 if (GNUNET_NO == queue->is_global_natted)
12513 {
12515 GNUNET_free (address_uri);
12516 GNUNET_free (uri_without_port);
12517 return;
12518 }
12519
12521 "3 not global natted_address %u %s %s\n",
12522 queue->is_global_natted,
12523 uri,
12524 queue->address);
12525
12526 if (0 == strcmp (uri_without_port, address_uri))
12527 {
12529 GNUNET_free (address_uri);
12530 GNUNET_free (uri_without_port);
12531 return;
12532 }
12533
12535 "4 not global natted_address %u %s %s\n",
12536 queue->is_global_natted,
12537 uri,
12538 queue->address);
12539
12540 address_uri_without_port = get_address_without_port (queue->address);
12541 if (0 == strcmp (uri_without_port, address_uri_without_port))
12542 {
12543 queue->is_global_natted = GNUNET_NO;
12544 }
12545
12547 "not global natted_address %u %s %s %s %s %s %u\n",
12548 queue->is_global_natted,
12549 uri,
12550 queue->address,
12551 uri_without_port,
12552 address_uri_without_port,
12553 prefix,
12554 GNUNET_NO);
12556 GNUNET_free (address_uri);
12557 GNUNET_free (address_uri_without_port);
12558 GNUNET_free (uri_without_port);
12559}
12560
12561
12563{
12567 char *addr;
12568
12573};
12574
12575
12576static enum GNUNET_GenericReturnValue
12577contains_address (void *cls,
12578 const struct GNUNET_PeerIdentity *pid,
12579 void *value)
12580{
12581 struct TransportGlobalNattedAddressClosure *tgna_cls = cls;
12582 struct TransportGlobalNattedAddress *tgna = value;
12583 char *addr = (char *) &tgna[1];
12584
12586 "Checking tgna %p with addr %s and length %u compare length %lu\n",
12587 tgna,
12588 addr,
12589 ntohl (tgna->address_length),
12590 strlen (tgna_cls->addr));
12591 if (strlen (tgna_cls->addr) == ntohl (tgna->address_length)
12592 && 0 == strncmp (addr, tgna_cls->addr, ntohl (tgna->address_length)))
12593 {
12594 tgna_cls->tgna = tgna;
12595 return GNUNET_NO;
12596 }
12597 return GNUNET_YES;
12598}
12599
12600
12601static void
12603{
12605 "Error in PEERSTORE monitoring for checking global natted\n");
12606}
12607
12608
12609static void
12611{
12613 "Done with initial PEERSTORE iteration during monitoring for checking global natted\n");
12614}
12615
12616
12617static void
12618check_for_global_natted (void *cls,
12619 const struct GNUNET_PEERSTORE_Record *record,
12620 const char *emsg)
12621{
12622 struct Queue *queue = cls;
12623 struct Neighbour *neighbour = queue->neighbour;
12625 struct GNUNET_MessageHeader *hello;
12627 size_t address_len_without_port;
12628
12629 if (NULL != emsg)
12630 {
12632 "Got failure from PEERSTORE: %s\n",
12633 emsg);
12634 return;
12635 }
12636 if (0 == record->value_size)
12637 {
12639 GNUNET_break (0);
12640 return;
12641 }
12642 queue->is_global_natted = GNUNET_YES;
12643 hello = record->value;
12646 "before not global natted %u\n",
12647 queue->is_global_natted);
12650 queue);
12652 "after not global natted %u\n",
12653 queue->is_global_natted);
12654 GNUNET_HELLO_parser_free (parser);
12655
12656 tgna_cls.addr = get_address_without_port (queue->address);
12657 address_len_without_port = strlen (tgna_cls.addr);
12658 /*{
12659 char buf[address_len_without_port + 1];
12660
12661 GNUNET_memcpy (&buf, addr, address_len_without_port);
12662 buf[address_len_without_port] = '\0';
12663 GNUNET_free (addr);
12664 GNUNET_memcpy (tgna_cls.addr, buf, address_len_without_port + 1);
12665 }*/
12666 tgna_cls.tgna = NULL;
12668 &neighbour->pid,
12670 &tgna_cls);
12671 if (NULL != tgna_cls.tgna)
12673 " tgna_cls.tgna tgna %p %lu %u %u\n",
12674 tgna_cls.tgna,
12675 neighbour->size_of_global_addresses,
12676 ntohl (tgna_cls.tgna->address_length),
12677 neighbour->number_of_addresses);
12678 if (NULL == tgna_cls.tgna && GNUNET_YES == queue->is_global_natted)
12679 {
12680 struct TransportGlobalNattedAddress *tgna;
12681
12682 tgna = GNUNET_malloc (sizeof (struct TransportGlobalNattedAddress)
12683 + address_len_without_port);
12684 tgna->address_length = htonl (address_len_without_port);
12685 GNUNET_memcpy (&tgna[1], tgna_cls.addr, address_len_without_port);
12687 &neighbour->pid,
12688 tgna,
12690 neighbour->number_of_addresses++;
12691 neighbour->size_of_global_addresses += address_len_without_port + 1;
12693 "Created tgna %p with address %s and length %lu\n",
12694 tgna,
12695 tgna_cls.addr,
12696 address_len_without_port + 1);
12697 }
12698 else if (NULL != tgna_cls.tgna && GNUNET_NO == queue->is_global_natted)
12699 {
12701 &neighbour->pid,
12702 tgna_cls.tgna);
12703 GNUNET_assert (neighbour->size_of_global_addresses >= ntohl (tgna_cls.tgna->
12705 );
12706 neighbour->size_of_global_addresses -= ntohl (tgna_cls.tgna->address_length)
12707 ;
12708 GNUNET_assert (0 < neighbour->number_of_addresses);
12709 neighbour->number_of_addresses--;
12711 "removed tgna %p\n",
12712 tgna_cls.tgna);
12713 GNUNET_free (tgna_cls.tgna);
12714 }
12716 GNUNET_free (tgna_cls.addr);
12717}
12718
12719
12726static void
12727handle_add_queue_message (void *cls,
12728 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
12729{
12730 struct TransportClient *tc = cls;
12731 struct Queue *queue;
12732 struct Neighbour *neighbour;
12733 const char *addr;
12734 uint16_t addr_len;
12735
12736 if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
12737 {
12738 /* MTU so small as to be useless for transmissions,
12739 required for #fragment_message()! */
12740 GNUNET_break_op (0);
12742 return;
12743 }
12744 /* This may simply be a queue update */
12745 for (queue = tc->details.communicator.queue_head;
12746 NULL != queue;
12747 queue = queue->next_client)
12748 {
12749 if (queue->qid != ntohl (aqm->qid))
12750 continue;
12751 break;
12752 }
12753
12754 if (NULL != queue)
12755 {
12756 neighbour = queue->neighbour;
12757 }
12758 else
12759 {
12760 struct GNUNET_TIME_Absolute validated_until = GNUNET_TIME_UNIT_ZERO_ABS;
12761
12762 neighbour = lookup_neighbour (&aqm->receiver);
12763 if (NULL == neighbour)
12764 {
12765 neighbour = GNUNET_new (struct Neighbour);
12767 GNUNET_YES);
12768 neighbour->pid = aqm->receiver;
12771 neighbours,
12772 &neighbour->pid,
12773 neighbour,
12775 neighbour->get =
12777 "transport",
12778 &neighbour->pid,
12781 neighbour);
12782 }
12783 addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
12784 addr = (const char *) &aqm[1];
12786 "New queue %s to %s available with QID %u and q_len %" PRIu64
12787 " and mtu %u\n",
12788 addr,
12789 GNUNET_i2s (&aqm->receiver),
12790 ntohl (aqm->qid),
12791 GNUNET_ntohll (aqm->q_len),
12792 ntohl (aqm->mtu));
12793 queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
12794 queue->tc = tc;
12795 for (struct Queue *q = neighbour->queue_head; NULL != q; q = q->
12796 next_neighbour)
12797 validated_until = GNUNET_TIME_absolute_max (validated_until, q->
12798 validated_until);
12799 if (0 == GNUNET_TIME_absolute_get_remaining (validated_until).rel_value_us)
12800 {
12802 "New queue with QID %u inherit validated until\n",
12803 ntohl (aqm->qid));
12804 queue->validated_until = validated_until;
12805 }
12806 queue->address = (const char *) &queue[1];
12807 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
12808 queue->qid = ntohl (aqm->qid);
12809 queue->neighbour = neighbour;
12811 queue->unlimited_length = GNUNET_YES;
12812 queue->q_capacity = GNUNET_ntohll (aqm->q_len);
12813 memcpy (&queue[1], addr, addr_len);
12814 /* notify monitors about new queue */
12815 {
12816 struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
12817
12818 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
12819 }
12821 neighbour->queue_head,
12822 neighbour->queue_tail,
12823 queue);
12825 tc->details.communicator.queue_head,
12826 tc->details.communicator.queue_tail,
12827 queue);
12828
12829 }
12830 queue->mtu = ntohl (aqm->mtu);
12831 queue->nt = ntohl (aqm->nt);
12832 queue->cs = ntohl (aqm->cs);
12833 queue->idle = GNUNET_YES;
12834
12835 {
12836 struct sockaddr_in v4;
12837 char *addr_without = get_address_without_port (queue->address);
12838 if (1 == inet_pton (AF_INET, addr_without, &v4.sin_addr))
12839 {
12841 "start not global natted\n");
12843 GNUNET_YES,
12844 "peerstore",
12845 &neighbour->pid,
12847 &
12849 NULL,
12850 &
12852 NULL,
12854 queue);
12855 }
12856 GNUNET_free (addr_without);
12857 }
12858 /* check if valdiations are waiting for the queue */
12860 &aqm->receiver))
12861 {
12864 &aqm->
12865 receiver,
12866 &
12868 queue))
12869 start_address_validation (&aqm->receiver, queue->address);
12870 }
12871 else
12872 start_address_validation (&aqm->receiver, queue->address);
12873 /* look for traffic for this queue */
12874 // TODO Check whether this makes any sense at all.
12875 /*schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
12876 queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);*/
12877 /* might be our first queue, try launching DV learning */
12878 if (NULL == dvlearn_task)
12881}
12882
12883
12890static void
12892 const struct
12894{
12895 struct TransportClient *tc = cls;
12896 struct Queue *target_queue = NULL;
12897
12899 "Received queue update message for %u with q_len %llu and mtu %u\n",
12900 ntohl (msg->qid),
12901 (unsigned long long) GNUNET_ntohll (msg->q_len),
12902 ntohl (msg->mtu));
12903 for (target_queue = tc->details.communicator.queue_head;
12904 NULL != target_queue;
12905 target_queue = target_queue->next_client)
12906 {
12907 if (ntohl (msg->qid) == target_queue->qid)
12908 break;
12909 }
12910 if (NULL == target_queue)
12911 {
12913 "Queue to update no longer exists! Discarding update.\n");
12914 return;
12915 }
12916
12917 target_queue->nt = msg->nt;
12918 target_queue->mtu = ntohl (msg->mtu);
12919 target_queue->cs = msg->cs;
12920 target_queue->priority = ntohl (msg->priority);
12921 /* The update message indicates how many messages
12922 * the queue should be able to handle.
12923 */
12925 target_queue->unlimited_length = GNUNET_YES;
12926 else
12927 target_queue->unlimited_length = GNUNET_NO;
12928 target_queue->q_capacity += GNUNET_ntohll (msg->q_len);
12929 if (0 < target_queue->q_capacity)
12931 target_queue,
12934}
12935
12936
12944static void
12945handle_queue_create_ok (void *cls,
12946 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
12947{
12948 struct TransportClient *tc = cls;
12949
12950 if (CT_COMMUNICATOR != tc->type)
12951 {
12952 GNUNET_break (0);
12954 return;
12955 }
12957 "# Suggestions succeeded at communicator",
12958 1,
12959 GNUNET_NO);
12961 "Request #%u for communicator to create queue succeeded\n",
12962 (unsigned int) ntohs (cqr->request_id));
12964}
12965
12966
12975static void
12977 void *cls,
12978 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
12979{
12980 struct TransportClient *tc = cls;
12981
12982 if (CT_COMMUNICATOR != tc->type)
12983 {
12984 GNUNET_break (0);
12986 return;
12987 }
12989 "Request #%u for communicator to create queue failed\n",
12990 (unsigned int) ntohl (cqr->request_id));
12992 "# Suggestions failed in queue creation at communicator",
12993 1,
12994 GNUNET_NO);
12996}
12997
12998
13006static void
13007handle_suggest_cancel (void *cls, const struct ExpressPreferenceMessage *msg)
13008{
13009 struct TransportClient *tc = cls;
13010 struct PeerRequest *pr;
13011
13012 if (CT_APPLICATION != tc->type)
13013 {
13014 GNUNET_break (0);
13016 return;
13017 }
13018 pr = GNUNET_CONTAINER_multipeermap_get (tc->details.application.requests,
13019 &msg->peer);
13020 if (NULL == pr)
13021 {
13022 GNUNET_break (0);
13024 return;
13025 }
13026 (void) stop_peer_request (tc, &pr->pid, pr);
13028}
13029
13030
13031static void
13032hello_for_client_cb (void *cls,
13033 const struct GNUNET_PeerIdentity *pid,
13034 const char *uri)
13035{
13036 struct Queue *q;
13037 int pfx_len;
13038 const char *eou;
13039 char *address;
13040 (void) cls;
13041
13042 eou = strstr (uri,
13043 "://");
13044 pfx_len = eou - uri;
13045 eou += 3;
13047 "%.*s-%s",
13048 pfx_len,
13049 uri,
13050 eou);
13051
13053 "hello for client %s\n",
13054 address);
13055
13056 q = find_queue (pid, address);
13057 if (NULL == q)
13058 {
13060 }
13061 else
13064}
13065
13066
13074static void
13075handle_hello_for_client (void *cls,
13076 const struct GNUNET_PEERSTORE_Record *record,
13077 const char *emsg)
13078{
13079 struct PeerRequest *pr = cls;
13081 struct GNUNET_MessageHeader *hello;
13082
13083 if (NULL != emsg)
13084 {
13086 "Got failure from PEERSTORE: %s\n",
13087 emsg);
13088 return;
13089 }
13090 if (NULL == GST_my_identity)
13091 {
13093 "No identity given yet!\n");
13094 return;
13095 }
13096 hello = record->value;
13097 if (0 == GNUNET_memcmp (&record->peer, GST_my_identity))
13098 {
13100 return;
13101 }
13103 if (NULL == parser)
13104 {
13106 "HELLO cannot be parsed!\n");
13107 return;
13108 }
13110 "HELLO for `%s' could be parsed, iterating addresses...!\n",
13114 NULL);
13115 GNUNET_HELLO_parser_free (parser);
13116}
13117
13118
13119static void
13120hello_for_client_error_cb (void *cls)
13121{
13123 "Error in PEERSTORE monitoring\n");
13124}
13125
13126
13127static void
13128hello_for_client_sync_cb (void *cls)
13129{
13131 "Done with initial PEERSTORE iteration during monitoring\n");
13132}
13133
13134
13142static void
13143handle_suggest (void *cls, const struct ExpressPreferenceMessage *msg)
13144{
13145 struct TransportClient *tc = cls;
13146 struct PeerRequest *pr;
13147
13148 if (CT_NONE == tc->type)
13149 {
13150 tc->type = CT_APPLICATION;
13151 tc->details.application.requests =
13153 }
13154 if (CT_APPLICATION != tc->type)
13155 {
13156 GNUNET_break (0);
13158 return;
13159 }
13161 "Client suggested we talk to %s with preference %d at rate %u\n",
13162 GNUNET_i2s (&msg->peer),
13163 (int) ntohl (msg->pk),
13164 (int) ntohl (msg->bw.value__));
13165 if (0 == GNUNET_memcmp (GST_my_identity, &msg->peer))
13166 {
13168 "Client suggested connection to ourselves, ignoring...\n");
13169 return;
13170 }
13171 pr = GNUNET_new (struct PeerRequest);
13172 pr->tc = tc;
13173 pr->pid = msg->peer;
13174 pr->bw = msg->bw;
13175 pr->pk = ntohl (msg->pk);
13177 tc->details.application.requests,
13178 &pr->pid,
13179 pr,
13181 {
13182 GNUNET_break (0);
13183 GNUNET_free (pr);
13185 return;
13186 }
13187 pr->nc =
13189 GNUNET_YES,
13190 "peerstore",
13191 NULL,
13194 NULL,
13196 NULL,
13198 pr);
13200}
13201
13202
13211static int
13213 const struct RequestHelloValidationMessage *m)
13214{
13215 (void) cls;
13217 return GNUNET_OK;
13218}
13219
13220
13228static void
13230 const struct RequestHelloValidationMessage *m)
13231{
13232 struct TransportClient *tc = cls;
13233 struct Queue *q;
13234
13235 q = find_queue (&m->peer, (const char *) &m[1]);
13236 if (NULL == q)
13237 {
13238 suggest_to_connect (&m->peer, (const char *) &m[1]);
13239 }
13240 else
13241 start_address_validation (&m->peer, (const char *) &m[1]);
13243}
13244
13245
13254static int
13255free_neighbour_cb (void *cls,
13256 const struct GNUNET_PeerIdentity *pid,
13257 void *value)
13258{
13259 struct Neighbour *neighbour = value;
13260
13261 (void) cls;
13262 (void) pid;
13263 GNUNET_break (0); // should this ever happen?
13264 free_neighbour (neighbour, GNUNET_YES);
13265
13266 return GNUNET_OK;
13267}
13268
13269
13278static int
13279free_dv_routes_cb (void *cls,
13280 const struct GNUNET_PeerIdentity *pid,
13281 void *value)
13282{
13283 struct DistanceVector *dv = value;
13284
13285 (void) cls;
13286 (void) pid;
13287 free_dv_route (dv);
13288
13289 return GNUNET_OK;
13290}
13291
13292
13301static int
13302free_validation_state_cb (void *cls,
13303 const struct GNUNET_PeerIdentity *pid,
13304 void *value)
13305{
13306 struct ValidationState *vs = value;
13307
13308 (void) cls;
13309 (void) pid;
13311 return GNUNET_OK;
13312}
13313
13314
13323static int
13324free_pending_ack_cb (void *cls, const struct GNUNET_Uuid *key, void *value)
13325{
13326 struct PendingAcknowledgement *pa = value;
13327
13328 (void) cls;
13329 (void) key;
13331 return GNUNET_OK;
13332}
13333
13334
13343static int
13344free_ack_cummulator_cb (void *cls,
13345 const struct GNUNET_PeerIdentity *pid,
13346 void *value)
13347{
13348 struct AcknowledgementCummulator *ac = value;
13349
13350 (void) cls;
13351 (void) pid;
13353 GNUNET_free (ac);
13354 return GNUNET_OK;
13355}
13356
13357
13364static void
13365do_shutdown (void *cls)
13366{
13367 struct LearnLaunchEntry *lle;
13368 struct PilsRequest *pr;
13369 (void) cls;
13370
13372 "shutdown logic\n");
13375 &free_neighbour_cb, NULL);
13376 if (NULL != validation_task)
13377 {
13379 validation_task = NULL;
13380 }
13381 if (NULL != dvlearn_task)
13382 {
13384 dvlearn_task = NULL;
13385 }
13387 dvlearn_map = NULL;
13390 dv_routes = NULL;
13391 if (NULL != GST_stats)
13392 {
13394 GST_stats = NULL;
13395 }
13396 if (NULL != GST_my_hello)
13397 {
13399 GST_my_hello = NULL;
13400 }
13401 if (NULL != GST_my_identity)
13402 {
13404 GST_my_identity = NULL;
13405 }
13408 NULL);
13410 ack_cummulators = NULL;
13413 NULL);
13415 pending_acks = NULL;
13418 neighbours = NULL;
13421 links = NULL;
13424 NULL);
13426 backtalkers = NULL;
13429 NULL);
13431 validation_map = NULL;
13433 validation_heap = NULL;
13435 revalidation_map = NULL;
13436 while (NULL != ir_head)
13438 GNUNET_assert (0 == ir_total);
13439 while (NULL != (lle = lle_head))
13440 {
13442 GNUNET_free (lle);
13443 }
13444 while (NULL != (pr = pils_requests_head))
13445 {
13448 pr);
13449 if (NULL != pr->op)
13450 GNUNET_PILS_cancel (pr->op);
13451 GNUNET_free (pr);
13452 }
13453 if (NULL != pils_feed_task)
13454 {
13456 pils_feed_task = NULL;
13457 }
13458 if (NULL != pils)
13459 {
13461 pils = NULL;
13462 }
13463 if (NULL != peerstore)
13464 {
13466 "Disconnecting from PEERSTORE service\n");
13468 peerstore = NULL;
13469 }
13471}
13472
13473
13474static void
13475shutdown_task (void *cls)
13476{
13478
13480 "Shutdown task executed\n");
13481 if (NULL != clients_head)
13482 {
13483 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
13484 {
13486 "client still connected: %u\n",
13487 tc->type);
13488 }
13489 }
13490 else
13491 do_shutdown (cls);
13492
13493}
13494
13495
13497{
13499};
13500
13501static void
13502update_hello_from_pid_change_cb (void *cls, int success)
13503{
13504 struct UpdateHelloFromPidCtx *pc = cls;
13505
13506 if (GNUNET_OK != success)
13507 {
13509 "Failed to store our new hello with peerstore\n");
13510 }
13511 GNUNET_free (pc);
13513 "Stored our new hello with peerstore\n");
13514}
13515
13516
13517void
13518print_address_list (void *cls,
13519 const struct GNUNET_PeerIdentity *pid,
13520 const char *uri)
13521{
13523 "%s\n", uri);
13524}
13525
13526
13536static void
13537pils_pid_change_cb (void *cls,
13538 const struct GNUNET_HELLO_Parser *parser,
13539 const struct GNUNET_HashCode *hash)
13540{
13541 struct GNUNET_MQ_Envelope *env;
13542 const struct GNUNET_MessageHeader *msg;
13543 struct UpdateHelloFromPidCtx *sc;
13544 struct GNUNET_HELLO_Builder *nbuilder;
13545 struct GNUNET_PeerIdentity npid;
13546
13547 if (NULL == GST_my_identity)
13549 if (NULL == GST_my_hello)
13552 "My current identity is `%s'\n",
13564 nbuilder = GNUNET_HELLO_builder_from_parser (parser,
13565 &npid);
13566 if (GNUNET_NO ==
13568 {
13570 "New PID from PILS is derived from address list inconsistend with ours. Ignoring...\n");
13572 "Proposed address list:\n");
13575 "Current address list:\n");
13577 GNUNET_HELLO_builder_free (nbuilder);
13578 return;
13579 }
13580 GST_my_hello = nbuilder;
13581 memcpy (GST_my_identity, &npid, sizeof npid);
13583 "My new identity is `%s'\n",
13589 msg,
13591 sc);
13592 GNUNET_free (env);
13593}
13594
13595
13603static void
13604run (void *cls,
13605 const struct GNUNET_CONFIGURATION_Handle *c,
13607{
13608 (void) cls;
13609 (void) service;
13610 /* setup globals */
13613 GST_cfg = c;
13621 GNUNET_YES);
13626 // TODO check for all uses of GST_my_hello that it is not used uninitialized
13628 "transport",
13629 "USE_BURST_NAT");
13630 if (GNUNET_SYSERR == use_burst)
13632 "Could not configure burst nat use. Default to no.\n");
13638 "transport",
13639 0,
13640 0,
13641 NULL,
13642 0,
13643 NULL,
13644 NULL,
13645 NULL);
13646 if (NULL == peerstore)
13647 {
13648 GNUNET_break (0);
13650 return;
13651 }
13652 GST_my_identity = NULL;
13655 NULL); // FIXME we need to wait for
13656 // our first peer id before
13657 // we can start the service
13658 // completely - PILS in turn
13659 // waits for the first
13660 // addresses from the
13661 // communicators in order to
13662 // be able to generate a
13663 // peer id
13664 if (NULL == pils)
13665 {
13666 GNUNET_break (0);
13668 return;
13669 }
13670}
13671
13672
13678 "transport",
13680 &run,
13683 NULL,
13684 /* communication with applications */
13685 GNUNET_MQ_hd_fixed_size (suggest,
13688 NULL),
13689 GNUNET_MQ_hd_fixed_size (suggest_cancel,
13692 NULL),
13693 GNUNET_MQ_hd_var_size (request_hello_validation,
13696 NULL),
13697 /* communication with core */
13698 GNUNET_MQ_hd_fixed_size (client_start,
13700 struct StartMessage,
13701 NULL),
13702 GNUNET_MQ_hd_var_size (client_send,
13704 struct OutboundMessage,
13705 NULL),
13706 GNUNET_MQ_hd_fixed_size (client_recv_ok,
13708 struct RecvOkMessage,
13709 NULL),
13710 /* communication with communicators */
13711 GNUNET_MQ_hd_var_size (communicator_available,
13714 NULL),
13715 GNUNET_MQ_hd_var_size (communicator_backchannel,
13718 NULL),
13719 GNUNET_MQ_hd_var_size (add_address,
13722 NULL),
13723 GNUNET_MQ_hd_fixed_size (del_address,
13726 NULL),
13727 GNUNET_MQ_hd_var_size (incoming_msg,
13730 NULL),
13731 GNUNET_MQ_hd_fixed_size (queue_create_ok,
13734 NULL),
13735 GNUNET_MQ_hd_fixed_size (queue_create_fail,
13738 NULL),
13739 GNUNET_MQ_hd_var_size (add_queue_message,
13742 NULL),
13743 GNUNET_MQ_hd_fixed_size (update_queue_message,
13746 NULL),
13747 GNUNET_MQ_hd_fixed_size (del_queue_message,
13750 NULL),
13751 GNUNET_MQ_hd_fixed_size (send_message_ack,
13754 NULL),
13755 GNUNET_MQ_hd_fixed_size (burst_finished,
13758 NULL),
13759 /* communication with monitors */
13760 GNUNET_MQ_hd_fixed_size (monitor_start,
13763 NULL),
13765
13766
13767/* end of file gnunet-service-transport.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition 002.c:5
struct GNUNET_MQ_MessageHandlers handlers[]
Definition 003.c:1
struct GNUNET_MessageHeader * msg
Definition 005.c:2
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition gnunet-arm.c:103
static int start
Set if we are to start default services (including ARM).
Definition gnunet-arm.c:38
static int ret
Final status code.
Definition gnunet-arm.c:93
static char * init
Set to the name of a service to start.
Definition gnunet-arm.c:73
static int do_shutdown
Set to GNUNET_YES if we are shutting down.
static struct GNUNET_CADET_Handle * mh
Cadet handle.
static struct GNUNET_TESTING_Interpreter * is
static struct Queue * queue_head
Head of queue of messages to transmit.
static int prefix
If printing the value of PREFIX has been requested.
static struct GNUNET_SCHEDULER_Task * st
The shutdown task.
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
static char * address
GNS address for this phone.
static GNUNET_NETWORK_STRUCT_END struct GNUNET_PeerIdentity me
Our own peer identity.
static struct GNUNET_DATASTORE_QueueEntry * qe
Current operation.
static char * data
The data to insert into the dht.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_TIME_Relative expiration
User supplied expiration value.
static struct GNUNET_FS_Handle * ctx
static OpusEncoder * enc
OPUS encoder.
struct GNUNET_SCHEDULER_Task * shutdown_task
static char * res
Currently read line or NULL on EOF.
static char * value
Value of the record to add/remove.
static uint32_t type
Type string converted to DNS type value.
static size_t data_size
Number of bytes in data.
static struct GNUNET_NAT_AUTO_Test * nt
Handle to a NAT test operation.
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
static struct GNUNET_FS_PublishContext * pc
Handle to FS-publishing operation.
static int result
Global testing status.
static struct GNUNET_REVOCATION_Query * q
Handle for revocation query.
static struct GNUNET_FS_SearchContext * sc
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static unsigned long long payload
How much data are we currently storing in the database?
static unsigned int ring_buffer_dv_head
Head of the ring buffer.
static void peerstore_store_validation_cb(void *cls, int success)
Function called when peerstore is done storing a validated address.
static void handle_dv_box(void *cls, const struct TransportDVBoxMessage *dvb)
Communicator gave us a DV box.
#define DV_PATH_DISCOVERY_FREQUENCY
How long before paths expire would we like to (re)discover DV paths? Should be below DV_PATH_VALIDITY...
static struct PendingMessage * ring_buffer_dv[RING_BUFFER_SIZE]
Ring buffer for a forwarded DVBox message we did not deliver to the next hop, because of missing virt...
static enum GNUNET_GenericReturnValue dv_decrypt(struct DVKeyState *key, void *out, const void *ciph, size_t out_size)
Perform backchannel encryption using symmetric secret in key to encrypt data from in to dst.
static int dv_neighbour_transmission(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Function called for each neighbour during handle_dv_learn.
static void reassembly_cleanup_task(void *cls)
Task run to clean up reassembly context of a neighbour that have expired.
static void pils_sign_addr_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
static enum GNUNET_GenericReturnValue remove_global_addresses(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
static void backtalker_timeout_cb(void *cls)
Function called when it is time to clean up a backtalker.
static void handle_add_address(void *cls, const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
Address of our peer added.
static unsigned int calculate_fork_degree(unsigned int hops_taken, unsigned int neighbour_count, unsigned int eligible_count)
Computes the number of neighbours we should forward a DVInit message to given that it has so far take...
static void dv_key_clean(struct DVKeyState *key)
Clean up key material in key.
static struct GNUNET_SCHEDULER_Task * dvlearn_task
Task run to initiate DV learning.
static int check_reliability_box(void *cls, const struct TransportReliabilityBoxMessage *rb)
Communicator gave us a reliability box.
static void handle_communicator_available(void *cls, const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
Communicator started.
static int check_fragment_box(void *cls, const struct TransportFragmentBoxMessage *fb)
Communicator gave us a fragment box.
static unsigned int get_age()
Get an offset into the transmission history buffer for struct PerformanceData.
static void free_validation_state(struct ValidationState *vs)
Free validation state.
static struct PendingAcknowledgement * prepare_pending_acknowledgement(struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
Setup data structure waiting for acknowledgements.
static int check_request_hello_validation(void *cls, const struct RequestHelloValidationMessage *m)
Check GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION messages.
static void hello_for_incoming_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
#define MAX_DV_DISCOVERY_SELECTION
Maximum number of peers we select for forwarding DVInit messages at the same time (excluding initiato...
#define QUEUE_ENTRY_TIMEOUT
static struct LearnLaunchEntry * lle_tail
Tail of a DLL sorted by launch time.
static struct GNUNET_CONTAINER_Heap * validation_heap
MIN Heap sorted by "next_challenge" to struct ValidationState entries sorting addresses we are aware ...
static void core_send_connect_info(struct TransportClient *tc, const struct GNUNET_PeerIdentity *pid)
Send message to CORE clients that we lost a connection.
static void send_dv_to_neighbour(void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Wrapper around route_via_neighbour() that matches the DVMessageHandler structure.
static void harmonize_flight_round(struct PendingMessage *pm)
#define ACK_CUMMULATOR_TIMEOUT
How long until we forget about historic accumulators and thus reset the ACK counter?...
void pils_sign_address(struct AddressListEntry *ale, struct GNUNET_TIME_Absolute mono_time)
Build address record by signing raw information with private key of the peer identity.
static void free_queue(struct Queue *queue)
Free queue.
static void handle_del_address(void *cls, const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
Address of our peer deleted.
static struct LearnLaunchEntry * lle_head
Head of a DLL sorted by launch time.
#define EPHEMERAL_VALIDITY
How long are ephemeral keys valid?
static void free_fragment_tree(struct PendingMessage *root)
Free fragment tree below root, excluding root itself.
static unsigned int is_ring_buffer_full
Is the ring buffer filled up to RING_BUFFER_SIZE.
static struct IncomingRequest * ir_tail
Tail of DLL starting at ir_head.
static void pils_pid_change_cb(void *cls, const struct GNUNET_HELLO_Parser *parser, const struct GNUNET_HashCode *hash)
Callback called when pils service updates us with our new peer identity.
static int free_pending_ack_cb(void *cls, const struct GNUNET_Uuid *key, void *value)
Free pending acknowledgement.
static int check_dv_box(void *cls, const struct TransportDVBoxMessage *dvb)
Communicator gave us a DV box.
static void completed_pending_message(struct PendingMessage *pm)
We have completed transmission of pm, remove it from the transmission queues (and if it is a fragment...
static void update_dvh_performance(struct DistanceVectorHop *dvh, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
We have successfully transmitted data via dvh, update metrics.
struct GNUNET_NAT_Handle * nh
Handle for connect to the NAT service.
static int check_add_queue_message(void *cls, const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
New queue became available.
static struct GNUNET_SCHEDULER_Task * pils_feed_task
Task to feed addresses to PILS.
static void client_send_response(struct PendingMessage *pm)
Send a response to the pm that we have processed a "send" request.
static void start_dv_learn(void *cls)
Task run when we CONSIDER initiating a DV learn process.
static int dv_neighbour_selection(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Function called for each neighbour during handle_dv_learn.
static void start_address_validation(const struct GNUNET_PeerIdentity *pid, const char *address)
Start address validation.
static void handle_del_queue_message(void *cls, const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
Queue to a peer went down.
#define QUEUE_LENGTH_LIMIT
How many messages can we have pending for a given queue (queue to a particular peer via a communicato...
static void update_backtalker_monotime(struct Backtalker *b)
The backtalker b monotonic time changed.
#define MAX_CUMMULATIVE_ACKS
Maximum number of messages we acknowledge together in one cumulative ACK.
#define MAX_DV_HOPS_ALLOWED
Maximum DV distance allowed ever.
static void burst_timeout(void *cls)
#define BACKCHANNEL_INACTIVITY_TIMEOUT
How long do we cache backchannel (struct Backtalker) information after a backchannel goes inactive?
static struct GNUNET_TIME_Relative get_network_latency(const struct TransportDVLearnMessage *dvl)
static void hello_for_client_error_cb(void *cls)
static void check_for_global_natted(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
#define ADDRESS_VALIDATION_LIFETIME
How long do we consider an address valid if we just checked?
static void free_distance_vector_hop(struct DistanceVectorHop *dvh)
Free a dvh.
#define MAX_FC_RETRANSMIT_COUNT
Maximum number of FC retransmissions for a running retransmission task.
static void sign_ephemeral(struct DistanceVector *dv)
Sign ephemeral keys in our dv are current.
static void handle_fragment_box(void *cls, const struct TransportFragmentBoxMessage *fb)
Communicator gave us a fragment.
static struct PendingMessage * fragment_message(struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
Fragment the given pm to the given mtu.
static void update_hello_from_pid_change_cb(void *cls, int success)
static struct GNUNET_SCHEDULER_Task * validation_task
Task to run address validation.
static void handle_suggest(void *cls, const struct ExpressPreferenceMessage *msg)
We have received a struct ExpressPreferenceMessage from an application client.
static void cores_send_connect_info(const struct GNUNET_PeerIdentity *pid)
Send message to CORE clients that we gained a connection.
static void cummulative_ack(const struct GNUNET_PeerIdentity *pid, const struct AcknowledgementUUIDP *ack_uuid, struct GNUNET_TIME_Absolute max_delay)
Transmit an acknowledgement for ack_uuid to pid delaying transmission by at most ack_delay.
static void task_consider_sending_fc(void *cls)
Something changed on the virtual link with respect to flow control.
#define DV_LEARN_QUALITY_THRESHOLD
How many good connections (confirmed, bi-directional, not DV) do we need to have to suppress initiati...
static void free_neighbour(struct Neighbour *neighbour, enum GNUNET_GenericReturnValue drop_link)
Release memory used by neighbour.
PendingMessageType
Types of different pending messages.
@ PMT_FRAGMENT_BOX
Fragment box.
@ PMT_DV_BOX
Pending message created during forward_dv_box().
@ PMT_CORE
Ordinary message received from the CORE service.
@ PMT_RELIABILITY_BOX
Reliability box.
static struct GNUNET_TIME_Relative calculate_rtt(struct DistanceVector *dv)
static int check_flow_control(void *cls, const struct TransportFlowControlMessage *fc)
Communicator gave us a transport address validation response.
static int stop_peer_request(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Stop the peer request in value.
static void handle_update_queue_message(void *cls, const struct GNUNET_TRANSPORT_UpdateQueueMessage *msg)
Handle updates to queues.
static void cores_send_disconnect_info(const struct GNUNET_PeerIdentity *pid)
Send message to CORE clients that we lost a connection.
static void handle_client_start(void *cls, const struct StartMessage *start)
Initialize a "CORE" client.
#define MAX_DV_PATHS_TO_TARGET
Maximum number of DV paths we keep simultaneously to the same target.
static void free_virtual_link(struct VirtualLink *vl)
Free virtual link.
RouteMessageOptions
Which transmission options are allowable for transmission? Interpreted bit-wise!
@ RMO_UNCONFIRMED_ALLOWED
We are allowed to use unconfirmed queues or DV routes for this message.
@ RMO_DV_ALLOWED
We are allowed to use DV routing for this hdr.
@ RMO_REDUNDANT
If we have multiple choices, it is OK to send this message over multiple channels at the same time to...
@ RMO_NONE
Only confirmed, non-DV direct neighbours.
@ RMO_ANYTHING_GOES
Reliable and unreliable, DV and non-DV are all acceptable.
static int notify_client_queues(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Iterator telling new MONITOR client about all existing queues to peers.
static struct AddressListEntry * create_address_entry(struct TransportClient *tc, struct GNUNET_TIME_Relative expiration, enum GNUNET_NetworkType nt, const char *address, uint32_t aid, size_t slen)
static void extract_box_cb(void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Function to call to further operate on the now DV encapsulated message hdr, forwarding it via next_ho...
static void backtalker_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called with the monotonic time of a backtalker by PEERSTORE.
static void queue_burst(void *cls)
static void handle_monitor_start(void *cls, const struct GNUNET_TRANSPORT_MonitorStart *start)
Initialize a monitor client.
static struct GNUNET_PEERSTORE_Handle * peerstore
Database for peer's HELLOs.
static void finish_cmc_handling(struct CommunicatorMessageContext *cmc)
static int learn_dv_path(const struct GNUNET_PeerIdentity *path, unsigned int path_len, struct GNUNET_TIME_Relative network_latency, struct GNUNET_TIME_Absolute path_valid_until)
We have learned a path through the network to some other peer, add it to our DV data structure (retur...
static void store_pi(void *cls)
Ask peerstore to store our address.
#define FC_NO_CHANGE_REPLY_PROBABILITY
What is the 1:n chance that we send a Flow control response when receiving a flow control message tha...
static void notify_monitors(const struct GNUNET_PeerIdentity *peer, const char *address, enum GNUNET_NetworkType nt, const struct MonitorEvent *me)
Send information in me about a peer's status with respect to some address to all monitors that care.
static struct GNUNET_TIME_Relative route_via_neighbour(const struct Neighbour *n, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Pick a queue of n under constraints options and schedule transmission of hdr.
#define RECV_WINDOW_SIZE
Window size.
static int check_known_challenge(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Test if the validation state in value matches the challenge from cls.
static unsigned int check_for_queue_with_higher_prio(struct Queue *queue, struct Queue *queue_head)
Check if the communicator has another queue with higher prio ready for sending.
#define GOODPUT_AGING_SLOTS
Number of slots we keep of historic data for computation of goodput / message loss ratio.
static int free_validation_state_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free validation state.
static int free_neighbour_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free neighbour entry.
static void handle_client_send(void *cls, const struct OutboundMessage *obm)
Client asked for transmission to a peer.
static void sign_dv_init_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
static enum GNUNET_GenericReturnValue burst_running
Is there a burst running?
struct GNUNET_HELLO_Builder * GST_my_hello
Our HELLO.
static void start_burst(void *cls)
#define DV_QUALITY_RTT_THRESHOLD
We only consider queues as "quality" connections when suppressing the generation of DV initiation mes...
static struct TransportClient * clients_head
Head of linked list of all clients to this service.
static void handle_validation_challenge(void *cls, const struct TransportValidationChallengeMessage *tvc)
Communicator gave us a transport address validation challenge.
static void dv_hmac(const struct DVKeyState *key, struct GNUNET_HashCode *hmac, const void *data, size_t data_size)
Do HMAC calculation for backchannel messages over data using key material from key.
static struct PilsRequest * pils_requests_head
PILS Operation DLL.
#define COMMUNICATOR_TOTAL_QUEUE_LIMIT
How many messages can we have pending for a given communicator process before we start to throttle th...
static void free_reassembly_context(struct ReassemblyContext *rc)
Free rc.
static struct VirtualLink * lookup_virtual_link(const struct GNUNET_PeerIdentity *pid)
Lookup virtual link for peer pid.
static int check_connection_quality(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Check whether any queue to the given neighbour is of a good "quality" and if so, increment the counte...
static void reorder_root_pm(struct PendingMessage *pm, struct GNUNET_TIME_Absolute next_attempt)
static void core_env_sent_cb(void *cls)
Function called when we are done giving a message of a certain size to CORE and should thus decrement...
static unsigned int ir_total
Length of the DLL starting at ir_head.
static int in_shutdown
Indication if we have received a shutdown signal and are in the process of cleaning up.
static void select_best_pending_from_link(struct PendingMessageScoreContext *sc, struct Queue *queue, struct VirtualLink *vl, struct DistanceVectorHop *dvh, size_t overhead)
Select the best pending message from vl for transmission via queue.
static void suggest_to_connect(const struct GNUNET_PeerIdentity *pid, const char *address)
Signature of a function called with a communicator address of a peer pid that an application wants us...
static void free_timedout_queue_entry(void *cls)
static void sign_t_validation_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
static void handle_send_message_ack(void *cls, const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
Message was transmitted.
static void update_pd_age(struct PerformanceData *pd, unsigned int age)
Check if we have advanced to another age since the last time.
#define DV_LEARN_BASE_FREQUENCY
What is the non-randomized base frequency at which we would initiate DV learn messages?
struct GNUNET_SCHEDULER_Task * burst_timeout_task
static void free_pending_acknowledgement(struct PendingAcknowledgement *pa)
Release pa data structure.
static struct GNUNET_CONTAINER_MultiUuidmap * pending_acks
Map of pending acknowledgements, mapping struct AcknowledgementUUID to a struct PendingAcknowledgemen...
static struct GNUNET_CONTAINER_MultiShortmap * dvlearn_map
Map from challenges to struct LearnLaunchEntry values.
#define DV_FORWARD_TIMEOUT
If a DVBox could not be forwarded after this number of seconds we drop it.
static void finish_handling_raw_message(struct VirtualLink *vl, const struct GNUNET_MessageHeader *mh, struct CommunicatorMessageContext *cmc, unsigned int free_cmc)
static void handle_add_queue_message(void *cls, const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
New queue became available.
static void update_queue_performance(struct Queue *q, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
We have successfully transmitted data via q, update metrics.
static void schedule_transmit_on_queue(struct GNUNET_TIME_Relative delay, struct Queue *queue, enum GNUNET_SCHEDULER_Priority p)
Called whenever something changed that might effect when we try to do the next transmission on queue ...
static void set_pending_message_uuid(struct PendingMessage *pm)
If necessary, generates the UUID for a pm.
static void free_pending_message(struct PendingMessage *pm)
Release memory associated with pm and remove pm from associated data structures.
static void revalidation_start_cb(void *cls)
static void backtalker_monotime_store_cb(void *cls, int success)
Function called by PEERSTORE when the store operation of a backtalker's monotonic time is complete.
static int free_reassembly_cb(void *cls, uint32_t key, void *value)
function called to free_reassembly_context().
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
Called whenever a client connects.
#define DV_PATH_VALIDITY_TIMEOUT
How long do we consider a DV path valid if we see no further updates on it? Note: the value chosen he...
#define RING_BUFFER_SIZE
Size of ring buffer to cache CORE and forwarded DVBox messages.
static struct GNUNET_PeerIdentity * GST_my_identity
Our public key.
static void check_vl_transmission(struct VirtualLink *vl)
There is a message at the head of the pending messages for vl which may be ready for transmission.
static int find_by_message_uuid(void *cls, uint32_t key, void *value)
Iterator called to find a reassembly context by the message UUID in the multihashmap32.
static struct TransportClient * lookup_communicator(const char *prefix)
Find transport client providing communication service for the protocol prefix.
static unsigned int ring_buffer_head
Head of the ring buffer.
#define MAX_ADDRESS_VALID_UNTIL
When do we forget an invalid address for sure?
static void handle_hello_for_client(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called by PEERSTORE for each matching record.
static void sign_dhp_cp(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
static void handle_suggest_cancel(void *cls, const struct ExpressPreferenceMessage *msg)
We have received a struct ExpressPreferenceMessage from an application client.
static void update_performance_data(struct PerformanceData *pd, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
Update pd based on the latest rtt and the number of bytes that were confirmed to be successfully tran...
static void forward_dv_box(struct Neighbour *next_hop, struct TransportDVBoxMessage *hdr, uint16_t total_hops, uint16_t num_hops, const struct GNUNET_PeerIdentity *hops, const void *enc_payload, uint16_t enc_payload_size)
Create a DV Box message and queue it for transmission to next_hop.
static void handle_validation_response(void *cls, const struct TransportValidationResponseMessage *tvr)
Communicator gave us a transport address validation response.
static void handle_reliability_ack(void *cls, const struct TransportReliabilityAckMessage *ra)
Communicator gave us a reliability ack.
static void send_msg_from_cache(struct VirtualLink *vl)
static void free_address_list_entry(struct AddressListEntry *ale)
Free ale.
static unsigned int pick_random_dv_hops(const struct DistanceVector *dv, enum RouteMessageOptions options, struct DistanceVectorHop **hops_array, unsigned int hops_array_length)
Pick hops_array_length random DV paths satisfying options.
static void handle_burst_finished(void *cls, const struct GNUNET_TRANSPORT_BurstFinished *bf)
The burst finished.
static void hello_for_incoming_sync_cb(void *cls)
static enum GNUNET_GenericReturnValue resume_communicators(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
static struct PilsRequest * pils_requests_tail
PILS Operation DLL.
static struct GNUNET_CONTAINER_MultiPeerMap * neighbours
Map from PIDs to struct Neighbour entries.
static void transmit_on_queue(void *cls)
We believe we are ready to transmit a message on a queue.
static void handle_dv_learn(void *cls, const struct TransportDVLearnMessage *dvl)
Communicator gave us a DV learn message.
static void iterate_address_start_burst(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static struct Queue * find_queue(const struct GNUNET_PeerIdentity *pid, const char *address)
Find the queue matching pid and address.
static void activate_core_visible_dv_path(struct DistanceVectorHop *hop)
The hop is a validated path to the respective target peer and we should tell core about it – and sche...
static void free_dv_route(struct DistanceVector *dv)
Free entry in dv_routes.
static unsigned int is_ring_buffer_dv_full
Is the ring buffer filled up to RING_BUFFER_SIZE.
static int check_communicator_backchannel(void *cls, const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
Communicator requests backchannel transmission.
#define DEFAULT_WINDOW_SIZE
How big is the flow control window size by default; limits per-neighbour RAM utilization.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Initiate transport service.
#define MAX_VALIDATION_CHALLENGE_FREQ
What is the slowest rate at which we send challenges?
static void handle_queue_create_ok(void *cls, const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
Communicator tells us that our request to create a queue "worked", that is setting up the queue is no...
static int notify_client_connect_info(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Iterator telling new CORE client about all existing connections to peers.
static void shc_cont(void *cls, int success)
static void handle_raw_message(void *cls, const struct GNUNET_MessageHeader *mh)
Communicator gave us an unencapsulated message to pass as-is to CORE.
static void handle_communicator_backchannel(void *cls, const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
Communicator requests backchannel transmission.
static unsigned long long logging_uuid_gen
Generator of logging_uuid in struct PendingMessage.
static int check_incoming_msg(void *cls, const struct GNUNET_TRANSPORT_IncomingMessage *im)
Client notified us about transmission from a peer.
#define REASSEMBLY_EXPIRATION
How long do we keep partially reassembled messages around before giving up?
static void update_next_challenge_time(struct ValidationState *vs, struct GNUNET_TIME_Absolute new_time)
Set the time for next_challenge of vs to new_time.
static struct Neighbour * lookup_neighbour(const struct GNUNET_PeerIdentity *pid)
Lookup neighbour for peer pid.
static void peerstore_store_own_cb(void *cls, int success)
Function called when peerstore is done storing our address.
static struct RingBufferEntry * ring_buffer[RING_BUFFER_SIZE]
Ring buffer for a CORE message we did not deliver to CORE, because of missing virtual link to sender.
#define MIN_DELAY_ADDRESS_VALIDATION
What is the maximum frequency at which we do address validation? A random value between 0 and this va...
static void handle_acknowledged(struct PendingAcknowledgement *pa, struct GNUNET_TIME_Relative ack_delay)
The pa was acknowledged, process the acknowledgement.
static struct GNUNET_CONTAINER_MultiPeerMap * backtalkers
Map from PIDs to struct Backtalker entries.
static struct GNUNET_TIME_Absolute hello_mono_time
Monotonic time we use for HELLOs generated at this time.
static int check_communicator_available(void *cls, const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
Communicator started.
static void handle_backchannel_encapsulation(void *cls, const struct TransportBackchannelEncapsulationMessage *be)
Communicator gave us a backchannel encapsulation.
static struct GNUNET_CONTAINER_MultiHashMap * revalidation_map
Map from addresses to struct ValidationState entries describing addresses we are aware of and their v...
static const struct GNUNET_CONFIGURATION_Handle * GST_cfg
Configuration handle.
static enum GNUNET_GenericReturnValue revalidate_map_it(void *cls, const struct GNUNET_HashCode *key, void *value)
#define DEFAULT_ACK_WAIT_DURATION
Default value for how long we wait for reliability ack.
static struct PendingMessage * reliability_box_message(struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
Reliability-box the given pm.
static int free_backtalker_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Callback to free backtalker records.
static enum GNUNET_GenericReturnValue contains_address(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
static void path_cleanup_cb(void *cls)
Task called when we should check if any of the DV paths we have learned to a target are due for garba...
#define FAST_VALIDATION_CHALLENGE_FREQ
What is the fastest rate at which we send challenges if we keep learning an address (gossip,...
static int check_add_address(void *cls, const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
Address of our peer added.
static void demultiplex_with_cmc(struct CommunicatorMessageContext *cmc)
Given an inbound message msg from a communicator cmc, demultiplex it based on the type calling the ri...
#define MAX_DV_LEARN_PENDING
Maximum number of DV learning activities we may have pending at the same time.
static void hello_for_client_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static void validation_start_cb(void *cls)
Task run periodically to validate some address based on validation_heap.
#define VALIDATION_RTT_BUFFER_FACTOR
How many network RTTs before an address validation expires should we begin trying to revalidate?...
static void handle_client_recv_ok(void *cls, const struct RecvOkMessage *rom)
Client confirms that it is done handling message(s) to a particular peer.
static void feed_addresses_to_pils(void *cls)
static struct GNUNET_CONTAINER_MultiPeerMap * links
Map from PIDs to struct VirtualLink entries describing links CORE knows to exist.
static int check_client_send(void *cls, const struct OutboundMessage *obm)
Client asked for transmission to a peer.
static int check_backchannel_encapsulation(void *cls, const struct TransportBackchannelEncapsulationMessage *be)
Communicator gave us a backchannel encapsulation.
static struct TransportClient * clients_tail
Tail of linked list of all clients to this service.
static struct GNUNET_CONTAINER_MultiPeerMap * ack_cummulators
Map from PIDs to struct AcknowledgementCummulators.
static void transmit_cummulative_ack_cb(void *cls)
Do the transmission of a cumulative acknowledgement now.
static int check_validation_request_pending(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
A new queue has been created, check if any address validation requests have been waiting for it.
static struct GNUNET_STATISTICS_Handle * GST_stats
Statistics handle.
static struct GNUNET_SCHEDULER_Task * burst_task
The task to start the burst.
void print_address_list(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static struct GNUNET_TIME_Relative encapsulate_for_dv(struct DistanceVector *dv, unsigned int num_dvhs, struct DistanceVectorHop **dvhs, const struct GNUNET_MessageHeader *hdr, DVMessageHandler use, void *use_cls, enum RouteMessageOptions options, enum GNUNET_GenericReturnValue without_fc)
Pick a path of dv under constraints options and schedule transmission of hdr.
static void neighbour_store_dvmono_cb(void *cls, int success)
Function called when peerstore is done storing a DV monotonic time.
static void handle_request_hello_validation(void *cls, const struct RequestHelloValidationMessage *m)
A client encountered an address of another peer.
static void free_queue_entry(struct QueueEntry *qe, struct TransportClient *tc)
static void pils_sign_hello_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
Get HELLO signature and create message to store in PEERSTORE.
static void check_for_global_natted_sync_cb(void *cls)
static void handle_reliability_box(void *cls, const struct TransportReliabilityBoxMessage *rb)
Communicator gave us a reliability box.
static void notify_monitor(struct TransportClient *tc, const struct GNUNET_PeerIdentity *peer, const char *address, enum GNUNET_NetworkType nt, const struct MonitorEvent *me)
Notify monitor tc about an event.
static void check_for_burst_address(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
static unsigned int check_next_attempt_tree(struct PendingMessage *pm, struct PendingMessage *root)
static void hello_for_incoming_error_cb(void *cls)
static void queue_send_msg(struct Queue *queue, struct PendingMessage *pm, const void *payload, size_t payload_size)
Send the message payload on queue.
static void dv_setup_key_state_from_km(const struct GNUNET_ShortHashCode *km, const struct GNUNET_ShortHashCode *iv, struct DVKeyState *key)
Given the key material in km and the initialization vector iv, setup the key material for the backcha...
static void handle_flow_control(void *cls, const struct TransportFlowControlMessage *fc)
Communicator gave us a transport address validation response.
static int check_dv_learn(void *cls, const struct TransportDVLearnMessage *dvl)
Communicator gave us a DV learn message.
static void handle_hello_for_incoming(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called by PEERSTORE for each matching record.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
Called whenever a client is disconnected.
static int check_reliability_ack(void *cls, const struct TransportReliabilityAckMessage *ra)
Communicator gave us a reliability ack.
static void sign_dv_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
static void dv_encrypt(struct DVKeyState *key, const void *in, void *dst, size_t in_size)
Perform backchannel encryption using symmetric secret in key to encrypt data from in to dst.
static void iterate_address_and_compare_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static struct GNUNET_CONTAINER_MultiPeerMap * validation_map
Map from PIDs to struct ValidationState entries describing addresses we are aware of and their validi...
static int free_dv_routes_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free DV route entry.
static enum GNUNET_GenericReturnValue add_global_addresses(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
#define MIN_DV_PATH_LENGTH_FOR_INITIATOR
Minimum number of hops we should forward DV learn messages even if they are NOT useful for us in hope...
static void handle_queue_create_fail(void *cls, const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
Communicator tells us that our request to create a queue failed.
static void check_link_down(void *cls)
Task run to check whether the hops of the cls still are validated, or if we need to core about discon...
static void check_for_global_natted_error_cb(void *cls)
static void finish_cmc_handling_with_continue(struct CommunicatorMessageContext *cmc, unsigned int free_cmc)
Send ACK to communicator (if requested) and free cmc.
static void forward_dv_learn(const struct GNUNET_PeerIdentity *next_hop, const struct TransportDVLearnMessage *msg, uint16_t bi_history, uint16_t nhops, const struct DVPathEntryP *hops, struct GNUNET_TIME_Absolute in_time)
Build and forward a DV learn message to next_hop.
static void handle_incoming_msg(void *cls, const struct GNUNET_TRANSPORT_IncomingMessage *im)
Incoming message.
static void validation_transmit_on_queue(struct Queue *q, struct ValidationState *vs)
The queue q (which matches the peer and address in vs) is ready for queueing.
static int free_ack_cummulator_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free acknowledgement cummulator.
static void update_pm_next_attempt(struct PendingMessage *pm, struct GNUNET_TIME_Absolute next_attempt)
Change the value of the next_attempt field of pm to next_attempt and re-order pm in the transmission ...
#define PILS_FEED_ADDRESSES_DELAY
Delay between added/removed addresses and PILS feed call.
static int check_known_address(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Test if the validation state in value matches the address from cls.
enum GNUNET_GenericReturnValue use_burst
static struct GNUNET_CONTAINER_MultiPeerMap * dv_routes
Map from PIDs to struct DistanceVector entries describing known paths to the peer.
static struct GNUNET_TIME_Relative route_control_message_without_fc(struct VirtualLink *vl, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
We need to transmit hdr to target.
static void free_incoming_request(struct IncomingRequest *ir)
Release ir data structure.
#define MAX_INCOMING_REQUEST
For how many incoming connections do we try to create a virtual link for (at the same time!...
static void neighbour_dv_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called with the monotonic time of a DV initiator by PEERSTORE.
static struct GNUNET_PILS_Handle * pils
Service that manages our peer id.
void(* DVMessageHandler)(void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Function to call to further operate on the now DV encapsulated message hdr, forwarding it via next_ho...
static void decaps_dv_box_cb(void *cls, const struct GNUNET_ShortHashCode *km)
static char * get_address_without_port(const char *address)
Get the IP address without the port number.
ClientType
What type of client is the struct TransportClient about?
@ CT_APPLICATION
"Application" telling us where to connect (i.e.
@ CT_MONITOR
It is a monitor, forward monitor data.
@ CT_NONE
We do not know yet (client is fresh).
@ CT_CORE
Is the CORE service, we need to forward traffic to it.
@ CT_COMMUNICATOR
It is a communicator, use for communication.
static int validate_dv_initiator_signature(struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time, const struct GNUNET_PeerIdentity *init, const struct GNUNET_CRYPTO_ChallengeNonceP *challenge, const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
Check signature of type GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
static struct IncomingRequest * ir_head
List of incoming connections where we are trying to get a connection back established.
static void free_backtalker(struct Backtalker *b)
Free data structures associated with b.
static void hello_for_client_sync_cb(void *cls)
static void destroy_ack_cummulator(void *cls)
Clean up an idle cumulative acknowledgement data structure.
static void consider_sending_fc(void *cls)
Something changed on the virtual link with respect to flow control.
static unsigned int bsize
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
static struct GNUNET_TRANSPORT_PluginMonitor * pm
Handle if we are monitoring plugin session activity.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition gnunet-uri.c:38
static struct GNUNET_TIME_Relative duration
Option '-d': duration of the mapping.
Definition gnunet-vpn.c:90
static void queue(const char *hostname)
Add hostname to the list of requests to be made.
struct GNUNET_PILS_Handle * GNUNET_PILS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_PILS_PidChangeCallback pid_change_cb, void *cls)
Connect to the PILS service.
Definition pils_api.c:367
void GNUNET_PILS_disconnect(struct GNUNET_PILS_Handle *handle)
Disconnect from the PILS service.
Definition pils_api.c:390
struct GNUNET_PILS_Operation * GNUNET_PILS_sign_hello(struct GNUNET_PILS_Handle *handle, const struct GNUNET_HELLO_Builder *builder, struct GNUNET_TIME_Absolute et, GNUNET_PILS_SignResultCallback cb, void *cb_cls)
Create HELLO signature.
Definition pils_api.c:576
void GNUNET_PILS_cancel(struct GNUNET_PILS_Operation *op)
Cancel request.
Definition pils_api.c:495
struct GNUNET_PILS_Operation * GNUNET_PILS_kem_decaps(struct GNUNET_PILS_Handle *handle, const struct GNUNET_CRYPTO_HpkeEncapsulation *c, GNUNET_PILS_DecapsResultCallback cb, void *cb_cls)
Decaps an encapsulated key with our private key.
Definition pils_api.c:468
struct GNUNET_PILS_Operation * GNUNET_PILS_sign_by_peer_identity(struct GNUNET_PILS_Handle *handle, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, GNUNET_PILS_SignResultCallback cb, void *cb_cls)
Sign data with the peer id.
Definition pils_api.c:428
void GNUNET_PILS_feed_addresses(struct GNUNET_PILS_Handle *handle, const struct GNUNET_HELLO_Builder *addresses_builder)
Feed a set of addresses to pils so that it will generate a new peer id based on the given set of addr...
Definition pils_api.c:542
uint32_t dim
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE
Signature by a peer affirming that it received a challenge (and stating how long it expects the addre...
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL
Signature by a peer affirming that the given ephemeral key is currently in use by that peer's transpo...
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR
Signature by a peer affirming that it originated the DV path.
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP
Signature by a peer affirming that it is on a DV path.
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS
Signature by a peer affirming that this is one of its addresses for the given time period.
#define GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED
Queue length.
GNUNET_TRANSPORT_CommunicatorCharacteristics
What characteristics does this communicator have?
GNUNET_TRANSPORT_ConnectionStatus
Possible states of a connection.
@ GNUNET_TRANSPORT_CC_RELIABLE
Transmission is reliabile (with ACKs), e.g.
@ GNUNET_TRANSPORT_CS_DOWN
Connection is down.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Generate a random unsigned 64-bit value.
void GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_encaps(const struct GNUNET_CRYPTO_EddsaPublicKey *pub, struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Encapsulate key material for a EdDSA public key.
#define GNUNET_CRYPTO_eddsa_verify(purp, ps, sig, pub)
Verify EdDSA signature.
void GNUNET_CRYPTO_zero_keys(void *buffer, size_t length)
Zero out buffer, securely against compiler optimizations.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
#define GNUNET_CONTAINER_MDLL_remove(mdll, head, tail, element)
Remove an element from a MDLL.
#define GNUNET_CONTAINER_MDLL_insert_tail(mdll, head, tail, element)
Insert an element at the tail of a MDLL.
#define GNUNET_CONTAINER_MDLL_insert_after(mdll, head, tail, other, element)
Insert an element into a MDLL after the given other element.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_MDLL_insert(mdll, head, tail, element)
Insert an element at the head of a MDLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:41
void GNUNET_CRYPTO_hmac(const struct GNUNET_CRYPTO_AuthKey *key, const void *plaintext, size_t plaintext_len, struct GNUNET_HashCode *hmac)
Calculate HMAC of a message (RFC 2104)
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hkdf_expand(void *result, size_t out_len, const struct GNUNET_ShortHashCode *prk,...)
HKDF-Expand using SHA256.
struct GNUNET_CONTAINER_MultiUuidmap * GNUNET_CONTAINER_multiuuidmap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL).
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
int GNUNET_CONTAINER_multihashmap32_get_multiple(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, GNUNET_CONTAINER_MultiHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map that match a particular key.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap32_put(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multipeermap_contains(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Check if the map contains any value under the given key (including values that are NULL).
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap32 * GNUNET_CONTAINER_multihashmap32_create(unsigned int len)
Create a 32-bit key multi hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap32_remove(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
struct GNUNET_CONTAINER_MultiShortmap * GNUNET_CONTAINER_multishortmap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multishortmap_put(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multiuuidmap_remove(struct GNUNET_CONTAINER_MultiUuidmap *map, const struct GNUNET_Uuid *key, const void *value)
Remove the given key-value pair from the map.
void GNUNET_CONTAINER_multiuuidmap_destroy(struct GNUNET_CONTAINER_MultiUuidmap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
void GNUNET_CONTAINER_multishortmap_destroy(struct GNUNET_CONTAINER_MultiShortmap *map)
Destroy a hash map.
void GNUNET_CONTAINER_multihashmap32_destroy(struct GNUNET_CONTAINER_MultiHashMap32 *map)
Destroy a 32-bit key hash map.
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
unsigned int GNUNET_CONTAINER_multishortmap_size(const struct GNUNET_CONTAINER_MultiShortmap *map)
Get the number of key-value pairs in the map.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
int GNUNET_CONTAINER_multihashmap32_iterate(struct GNUNET_CONTAINER_MultiHashMap32 *map, GNUNET_CONTAINER_MultiHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map.
int GNUNET_CONTAINER_multishortmap_remove(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multiuuidmap_iterate(struct GNUNET_CONTAINER_MultiUuidmap *map, GNUNET_CONTAINER_MultiUuidmapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multiuuidmap_put(struct GNUNET_CONTAINER_MultiUuidmap *map, const struct GNUNET_Uuid *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
void * GNUNET_CONTAINER_multiuuidmap_get(const struct GNUNET_CONTAINER_MultiUuidmap *map, const struct GNUNET_Uuid *key)
Given a key find a value in the map matching the key.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
void * GNUNET_CONTAINER_heap_peek(const struct GNUNET_CONTAINER_Heap *heap)
Get element stored at the root of heap.
void GNUNET_CONTAINER_heap_update_cost(struct GNUNET_CONTAINER_HeapNode *node, GNUNET_CONTAINER_HeapCostType new_cost)
Updates the cost of any node in the tree.
struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert(struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost)
Inserts a new element into the heap.
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
@ GNUNET_CONTAINER_HEAP_ORDER_MIN
Heap with the minimum cost at the root.
void GNUNET_HELLO_parser_free(struct GNUNET_HELLO_Parser *parser)
Release resources of a builder.
Definition hello-uri.c:379
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_msg(const struct GNUNET_MessageHeader *msg)
Parse msg.
Definition hello-uri.c:415
void GNUNET_HELLO_builder_free(struct GNUNET_HELLO_Builder *builder)
Release resources of a builder.
Definition hello-uri.c:397
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_new()
Allocate builder.
Definition hello-uri.c:343
void GNUNET_HELLO_builder_iterate(const struct GNUNET_HELLO_Builder *builder, GNUNET_HELLO_UriCallback uc, void *uc_cls)
Iterate over URIs in a builder.
Definition hello-uri.c:956
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_from_parser(const struct GNUNET_HELLO_Parser *parser, struct GNUNET_PeerIdentity *pid)
Allocate builder from parser.
Definition hello-uri.c:360
const struct GNUNET_PeerIdentity * GNUNET_HELLO_parser_iterate(const struct GNUNET_HELLO_Parser *parser, GNUNET_HELLO_UriCallback uc, void *uc_cls)
Iterate over URIs in a parser.
Definition hello-uri.c:975
struct GNUNET_MQ_Envelope * GNUNET_HELLO_parser_to_env(const struct GNUNET_HELLO_Parser *parser)
Generate envelope with GNUnet HELLO message (including peer ID) from a parser.
Definition hello-uri.c:903
enum GNUNET_GenericReturnValue GNUNET_HELLO_builder_address_list_cmp(const struct GNUNET_HELLO_Builder *abuilder, const struct GNUNET_HELLO_Builder *bbuilder)
Compare address lists of two builders.
Definition hello-uri.c:1330
enum GNUNET_GenericReturnValue GNUNET_HELLO_builder_del_address(struct GNUNET_HELLO_Builder *builder, const char *address)
Remove individual address from the builder.
Definition hello-uri.c:932
const struct GNUNET_PeerIdentity * GNUNET_HELLO_parser_get_id(const struct GNUNET_HELLO_Parser *parser)
Get the PeerIdentity for this builder.
Definition hello-uri.c:353
#define GNUNET_HELLO_ADDRESS_EXPIRATION
For how long are HELLO signatures valid?
enum GNUNET_GenericReturnValue GNUNET_HELLO_builder_add_address(struct GNUNET_HELLO_Builder *builder, const char *address)
Add individual address to the builder.
Definition hello-uri.c:624
char * GNUNET_HELLO_address_to_prefix(const char *address)
Given an address as a string, extract the prefix that identifies the communicator offering transmissi...
Definition hello-uri.c:1062
struct GNUNET_MQ_Envelope * GNUNET_HELLO_builder_to_env(const struct GNUNET_HELLO_Builder *builder, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig, struct GNUNET_TIME_Absolute expiration_time)
Generate envelope with GNUnet HELLO message (including peer ID) from a builder.
Definition hello-uri.c:1142
#define GNUNET_is_zero(a)
Check that memory in a is all zeros.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
#define GNUNET_MAX(a, b)
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
GNUNET_SCHEDULER_Priority
Valid task priorities.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
#define GNUNET_MIN(a, b)
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
#define GNUNET_PACKED
gcc-ism to get packed structs.
@ GNUNET_SCHEDULER_PRIORITY_BACKGROUND
Run as background job (higher than idle, lower than default).
@ GNUNET_SCHEDULER_PRIORITY_DEFAULT
Run with the default priority (normal P2P operations).
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
const char * GNUNET_uuid2s(const struct GNUNET_Uuid *uuid)
Convert a UUID to a string (for printing debug messages).
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
const char * GNUNET_sh2s(const struct GNUNET_ShortHashCode *shc)
Convert a short hash value to a string (for printing debug messages).
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
const char * GNUNET_i2s2(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_EXTRA_LOGGING
define GNUNET_EXTRA_LOGGING if using this header outside the GNUnet source tree where gnunet_config....
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition mq.c:305
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_check_zero_termination(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
#define GNUNET_MQ_check_boxed_message(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
GNUNET_MQ_PriorityPreferences
Per envelope preferences and priorities.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
enum GNUNET_GenericReturnValue GNUNET_MQ_handle_message(const struct GNUNET_MQ_MessageHandler *handlers, const struct GNUNET_MessageHeader *mh)
Call the message message handler that was registered for the type of the given message in the given h...
Definition mq.c:205
void GNUNET_MQ_notify_sent(struct GNUNET_MQ_Envelope *ev, GNUNET_SCHEDULER_TaskCallback cb, void *cb_cls)
Call a callback once the envelope has been sent, that is, sending it can not be canceled anymore.
Definition mq.c:655
const struct GNUNET_MessageHeader * GNUNET_MQ_env_get_msg(const struct GNUNET_MQ_Envelope *env)
Obtain message contained in envelope.
Definition mq.c:896
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
@ GNUNET_MQ_PRIO_BACKGROUND
Lowest priority, i.e.
@ GNUNET_MQ_PREF_UNRELIABLE
Flag to indicate that unreliable delivery is acceptable.
@ GNUNET_MQ_PREF_LOW_LATENCY
Flag to indicate that low latency is important.
void GNUNET_is_burst_ready(struct GNUNET_TIME_Relative rtt_average, struct GNUNET_BurstSync *burst_sync, GNUNET_SCHEDULER_TaskCallback task, struct GNUNET_StartBurstCls *task_cls)
Checks if we are ready and starts burst when we and the other peer is ready.
Definition nat.c:89
struct GNUNET_NAT_Handle * GNUNET_NAT_register(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on...
Definition nat_api.c:366
void GNUNET_NAT_unregister(struct GNUNET_NAT_Handle *nh)
Stop port redirection and public IP address detection for the given handle.
Definition nat_api.c:703
void GNUNET_NAT_add_global_address(struct GNUNET_NAT_Handle *nh, char *addr, unsigned int address_length)
Add global address to the list of addresses and notify clients.
Definition nat_api.c:460
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
void GNUNET_PEERSTORE_monitor_stop(struct GNUNET_PEERSTORE_Monitor *zm)
Stop monitoring.
struct GNUNET_PEERSTORE_IterateContext * GNUNET_PEERSTORE_iteration_start(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_PEERSTORE_Processor callback, void *callback_cls)
Iterate over peerstore entries.
void GNUNET_PEERSTORE_iteration_next(struct GNUNET_PEERSTORE_IterateContext *ic, uint64_t limit)
Continue an iteration.
void GNUNET_PEERSTORE_store_cancel(struct GNUNET_PEERSTORE_StoreContext *sc)
Cancel a store request.
#define GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME
Key used to store sender's monotonic time from backchannel messages.
void GNUNET_PEERSTORE_disconnect(struct GNUNET_PEERSTORE_Handle *h)
Disconnect from the PEERSTORE service.
#define GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY
Key used for storing addresses in URL format in the peerstore.
struct GNUNET_PEERSTORE_Monitor * GNUNET_PEERSTORE_monitor_start(const struct GNUNET_CONFIGURATION_Handle *cfg, int iterate_first, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_SCHEDULER_TaskCallback sync_cb, void *sync_cb_cls, GNUNET_PEERSTORE_Processor callback, void *callback_cls)
Request watching a given key The monitoring can be filtered to contain only records matching peer and...
#define GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME
Key used to store sender's monotonic time from DV learn messages.
struct GNUNET_PEERSTORE_Handle * GNUNET_PEERSTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the PEERSTORE service.
void GNUNET_PEERSTORE_monitor_next(struct GNUNET_PEERSTORE_Monitor *zm, uint64_t limit)
Calls the monitor processor specified in GNUNET_PEERSTORE_monitor_start for the next record(s).
struct GNUNET_PEERSTORE_StoreContext * GNUNET_PEERSTORE_store(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, const void *value, size_t size, struct GNUNET_TIME_Absolute expiry, enum GNUNET_PEERSTORE_StoreOption options, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Store a new entry in the PEERSTORE.
#define GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY
Key used for storing HELLOs in the peerstore.
void GNUNET_PEERSTORE_iteration_stop(struct GNUNET_PEERSTORE_IterateContext *ic)
Cancel an iteration.
#define GNUNET_PEERSTORE_HELLO_KEY
Key used for storing HELLO in the peerstore.
struct GNUNET_PEERSTORE_StoreHelloContext * GNUNET_PEERSTORE_hello_add(struct GNUNET_PEERSTORE_Handle *h, const struct GNUNET_MessageHeader *msg, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Add hello to peerstore.
@ GNUNET_PEERSTORE_STOREOPTION_MULTIPLE
Possibly store multiple values under given key.
@ GNUNET_PEERSTORE_STOREOPTION_REPLACE
Delete any previous values for the given key before storing the given value.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE
P2P message: transport requests confirmation that an address works.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK
transport acknowledges processing an incoming message
#define GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT
Message from TRANSPORT notifying about a client that connected to us.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN
inform transport that a queue was torn down
#define GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION
Type of the 'struct RequestHelloValidationMessage' send by clients to TRANSPORT to trigger validation...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_START
Message from the core saying that the transport server should start giving it messages.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA
Message sent to indicate to a monitor about events.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR
Message sent to indicate to the transport which address prefix is supported by a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RECV_OK
Message telling transport to limit its receive rate.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT
Type of a fragment of a CORE message created by transport to adjust message length to a queue's MTU.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL
Response from communicator: address bogus, will not try to create queue.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX
Source-routed transport message based DV information gathered.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX
Wrapper around non-fragmented CORE message used to measure RTT and ensure reliability.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST_CANCEL
Type of the 'struct ExpressPreferenceMessage' send by clients to TRANSPORT to abandon bandwidth prefe...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RECV
Message from TRANSPORT notifying about a message that was received.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION
Message type used between transport services when they internally forward communicator backchannel me...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE
transport tells communicator it wants a queue
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN
Message sent for topology discovery at transport level.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_BURST_FINISHED
Burst message we send to another peer for hole punching.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL
Tell transport that it should assist with exchanging a message between communicators.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT
Message from TRANSPORT notifying about a client that disconnected from us.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG
inform transport about an incoming message
#define GNUNET_MESSAGE_TYPE_TRANSPORT_START_BURST
Burst message we send to another peer for hole punching.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK
Response from communicator: will try to create queue.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING
Transport signalling incoming backchannel message to a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK
communicator tells transports that message was sent
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS
inform transport to add an address of this peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START
Message sent to indicate to the transport that a monitor wants to observe certain events.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS
inform transport to delete an address of this peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE
P2P message: transport proves that an address worked.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL
Transport signalling incoming backchannel message to a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG
transport tells communicator it wants to transmit
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND
Request to TRANSPORT to transmit a message.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK
Confirmation from TRANSPORT that message for transmission has been queued (and that the next message ...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK
Confirmation for a GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP
inform transport that a queue was setup to talk to some peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST
Type of the 'struct ExpressPreferenceMessage' send by clients to TRANSPORT to establish bandwidth pre...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_UPDATE
inform transport that a queue was updated
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition scheduler.c:567
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_at(struct GNUNET_TIME_Absolute at, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run at the specified time.
Definition scheduler.c:1254
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition scheduler.c:1339
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:980
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1304
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1277
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1207
#define GNUNET_SERVICE_MAIN(pd, service_name, service_options, init_cb, connect_cb, disconnect_cb, cls,...)
Creates the "main" function for a GNUnet service.
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the 'monitor' flag on this client.
Definition service.c:2527
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition service.c:2462
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition service.c:2433
@ GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN
Trigger a SOFT server shutdown on signals, allowing active non-monitor clients to complete their tran...
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition strings.c:1618
struct GNUNET_TIME_Relative GNUNET_TIME_relative_min(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the minimum of two relative time values.
Definition time.c:344
const char * GNUNET_TIME_relative2s(struct GNUNET_TIME_Relative delta, bool do_round)
Give relative time in human-readable fancy format.
Definition time.c:264
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_TIME_Relative GNUNET_TIME_relative_ntoh(struct GNUNET_TIME_RelativeNBO a)
Convert relative time from network byte order.
Definition time.c:630
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition time.c:438
#define GNUNET_TIME_relative_cmp(t1, op, t2)
Compare two relative times.
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition time.c:406
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_max(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the maximum of two absolute time values.
Definition time.c:368
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition strings.c:599
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
struct GNUNET_TIME_Relative GNUNET_TIME_randomized_backoff(struct GNUNET_TIME_Relative rt, struct GNUNET_TIME_Relative threshold)
Randomized exponential back-off, starting at 1 ms and going up by a factor of 2+r,...
Definition time.c:834
struct GNUNET_TIME_Relative GNUNET_TIME_relative_subtract(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Subtract relative timestamp from the other.
Definition time.c:605
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition time.c:111
#define GNUNET_TIME_UNIT_MINUTES
One minute.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply_double(struct GNUNET_TIME_Relative rel, double factor)
Multiply relative time by a given factor.
Definition time.c:506
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition time.c:741
struct GNUNET_TIME_Relative GNUNET_TIME_relative_add(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Add relative times together.
Definition time.c:587
struct GNUNET_TIME_Relative GNUNET_TIME_randomize(struct GNUNET_TIME_Relative r)
Return a random time value between 0.5*r and 1.5*r.
Definition time.c:855
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_subtract(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Subtract a given relative duration from the given start time.
Definition time.c:471
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition time.c:316
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition time.c:486
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_min(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the minimum of two absolute time values.
Definition time.c:360
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
struct GNUNET_TIME_RelativeNBO GNUNET_TIME_relative_hton(struct GNUNET_TIME_Relative a)
Convert relative time to network byte order.
Definition time.c:620
#define GNUNET_TIME_absolute_cmp(t1, op, t2)
Compare two absolute times.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Add a given relative duration to the given start time.
Definition time.c:452
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get_monotonic(const struct GNUNET_CONFIGURATION_Handle *cfg)
Obtain the current time and make sure it is monotonically increasing.
Definition time.c:864
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition time.c:552
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_difference(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end)
Compute the time difference between the given start and end times.
Definition time.c:423
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition time.c:640
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition strings.c:660
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
static unsigned int size
Size of the "table".
Definition peer.c:68
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition scheduler.c:431
void receiver(void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode)
Callback to read from the SOCKS5 proxy.
Definition socks.c:330
static struct GNUNET_TIME_Relative delta
Definition speedup.c:36
Data structure in which we track acknowledgements still to be sent to the.
struct GNUNET_SCHEDULER_Task * task
Task scheduled either to transmit the cumulative ACK message, or to clean up this data structure afte...
struct GNUNET_TIME_Absolute min_transmission_time
When is task run (only used if num_acks is non-zero)?
struct TransportCummulativeAckPayload ack_uuids[64]
ACK data being accumulated.
struct GNUNET_PeerIdentity target
Target peer for which we are accumulating ACKs here.
unsigned int num_acks
Number of entries used in ack_uuids.
uint32_t ack_counter
Counter to produce the ack_counter in the struct TransportReliabilityAckMessage.
Unique identifier to map an acknowledgement to a transmission.
struct GNUNET_Uuid value
The UUID value.
One of the addresses of this peer.
struct GNUNET_TIME_Relative expiration
What is a typical lifetime the communicator expects this address to have? (Always from now....
uint32_t aid
Address identifier used by the communicator.
size_t signed_address_len
Signed address length.
enum GNUNET_NetworkType nt
Network type offered by this address.
struct AddressListEntry * prev
Kept in a DLL.
struct TransportClient * tc
Which communicator provides this address?
struct AddressListEntry * next
Kept in a DLL.
struct GNUNET_PEERSTORE_StoreHelloContext * shc
Store hello handle.
void * signed_address
Signed address.
const char * address
The actual address.
struct GNUNET_SCHEDULER_Task * st
Task to periodically do st operation.
struct GNUNET_PEERSTORE_StoreContext * sc
Current context for storing this address in the peerstore.
A Backtalker is a peer sending us backchannel messages.
struct GNUNET_TIME_Absolute timeout
When will this entry time out?
struct CommunicatorMessageContext * cmc
Communicator context waiting on this backchannel's get, or NULL.
struct GNUNET_CRYPTO_HpkeEncapsulation last_ephemeral
Last (valid) ephemeral key received from this sender.
struct GNUNET_PEERSTORE_StoreContext * sc
Handle to a PEERSTORE store operation for this pid's monotonic_time.
struct GNUNET_SCHEDULER_Task * task
Task associated with this backtalker.
size_t body_size
Number of bytes of the original message body that follows after this struct.
struct GNUNET_TIME_Absolute monotonic_time
Last (valid) monotonic time received from this sender.
struct GNUNET_PEERSTORE_IterateContext * get
Handle for an operation to fetch monotonic_time information from the PEERSTORE, or NULL.
struct GNUNET_PeerIdentity pid
Peer this is about.
Closure for check_known_address.
struct ValidationState * vs
Set to a matching validation state, if one was found.
const char * address
Set to the address we are looking for.
Closure for check_known_challenge.
struct ValidationState * vs
Set to a matching validation state, if one was found.
const struct GNUNET_CRYPTO_ChallengeNonceP * challenge
Set to the challenge we are looking for.
Context from handle_incoming_msg().
struct CommunicatorMessageContext * next
Kept in a DLL of struct VirtualLink if waiting for CORE flow control to unchoke.
uint16_t total_hops
Number of hops the message has travelled (if DV-routed).
struct GNUNET_TRANSPORT_IncomingMessage im
Additional information for flow control and about the sender.
unsigned int continue_send
Did we already call GNUNET_SERVICE_client_continue and send ACK to communicator?
const struct GNUNET_MessageHeader * mh
The message to demultiplex.
struct CommunicatorMessageContext * prev
Kept in a DLL of struct VirtualLink if waiting for CORE flow control to unchoke.
struct TransportClient * tc
Which communicator provided us with the message.
Message from the transport service to the library informing about neighbors.
Definition transport.h:89
struct GNUNET_PeerIdentity id
Identity of the new neighbour.
Definition transport.h:112
Closure for core_env_sent_cb.
uint16_t isize
By how much should we increment vl's incoming_fc_window_size_used once we are done sending to CORE?...
struct CoreSentContext * next
Kept in a DLL to clear vl in case vl is lost.
struct VirtualLink * vl
Virtual link this is about.
struct CoreSentContext * prev
Kept in a DLL to clear vl in case vl is lost.
uint16_t size
How big was the message.
Structure of the key material used to encrypt backchannel messages.
struct GNUNET_CRYPTO_AuthKey hmac_key
Key used for HMAC calculations (via GNUNET_CRYPTO_hmac()).
gcry_cipher_hd_t cipher
State of our block cipher.
struct DVKeyState::@65 material
Actual key material.
char aes_key[256/8]
Symmetric key to use for encryption.
char aes_ctr[128/8]
Counter value to use during setup.
An entry describing a peer on a path in a struct TransportDVLearnMessage message.
struct GNUNET_CRYPTO_EddsaSignature hop_sig
Signature of this hop over the path, of purpose GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP.
struct GNUNET_PeerIdentity hop
Identity of a peer on the path.
const struct TransportDVBoxMessage * dvb
struct PilsRequest * pr
struct CommunicatorMessageContext * cmc
Message from the transport service to the library informing about disconnects.
Definition transport.h:121
One possible hop towards a DV target.
struct PerformanceData pd
Performance data for this transmission possibility.
struct PendingAcknowledgement * pa_head
Head of DLL of PAs that used our path.
unsigned int distance
Number of hops in total to the target (excluding next_hop and target itself).
struct DistanceVectorHop * next_neighbour
Kept in a MDLL.
struct Neighbour * next_hop
What would be the next hop to target?
struct GNUNET_TIME_Absolute timeout
At what time do we forget about this path unless we see it again while learning?
struct DistanceVector * dv
Distance vector entry this hop belongs with.
const struct GNUNET_PeerIdentity * path
Array of distance hops to the target, excluding next_hop.
struct DistanceVectorHop * next_dv
Kept in a MDLL, sorted by timeout.
struct GNUNET_TIME_Absolute path_valid_until
For how long is the validation of this path considered valid? Set to ZERO if the path is learned by s...
struct DistanceVectorHop * prev_dv
Kept in a MDLL, sorted by timeout.
struct DistanceVectorHop * prev_neighbour
Kept in a MDLL.
struct PendingAcknowledgement * pa_tail
Tail of DLL of PAs that used our path.
Entry in our dv_routes table, representing a (set of) distance vector routes to a particular peer.
struct DistanceVectorHop * dv_head
Known paths to target.
struct VirtualLink * vl
Do we have a confirmed working queue and are thus visible to CORE? If so, this is the virtual link,...
struct GNUNET_TIME_Absolute monotime
What time was sender_sig created.
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Signature affirming ephemeral_key of type GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct DistanceVectorHop * dv_tail
Known paths to target.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Our ephemeral key.
struct GNUNET_ShortHashCode * km
Master secret for the setup of the Key material for the backchannel.
struct GNUNET_PeerIdentity target
To which peer is this a route?
struct GNUNET_TIME_Absolute ephemeral_validity
How long is sender_sig valid.
struct GNUNET_SCHEDULER_Task * timeout_task
Task scheduled to purge expired paths from dv_head MDLL.
Content signed by each peer during DV learning.
struct GNUNET_PeerIdentity pred
Identity of the previous peer on the path.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP.
struct GNUNET_PeerIdentity succ
Identity of the next peer on the path.
Content signed by the initiator during DV learning.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Time at the initiator when generating the signature.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
Body by which a peer confirms that it is using an ephemeral key.
struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time
How long is this signature over the ephemeral key valid?
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct GNUNET_PeerIdentity target
Target's peer identity.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Ephemeral key setup by the sender for target, used to encrypt the payload.
Application client to TRANSPORT service: we would like to have address suggestions for this peer.
Definition transport.h:807
Closure for find_by_message_uuid.
struct ReassemblyContext * rc
Set to the reassembly context if found.
struct MessageUUIDP message_uuid
UUID to look for.
32-bit bandwidth used for network exchange by GNUnet, in bytes per second.
Wrapper struct with the average RTT of message to some peer and if this peer und us is ready to sync.
Handle to a node in a heap.
Internal representation of the hash map.
Internal representation of the hash map.
Internal representation of the hash map.
Internal representation of the hash map.
Internal representation of the hash map.
type for (message) authentication keys
Type of a nonce used for challenges.
struct GNUNET_ShortHashCode value
The value of the nonce.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
an ECC signature using EdDSA.
HPKE DHKEM encapsulation (X25519) See RFC 9180.
Context for building (or parsing) HELLO URIs.
Definition hello-uri.c:184
Context for parsing HELLOs.
Definition hello-uri.c:232
A 512-bit hashcode.
Handle to a message queue.
Definition mq.c:87
Message handler for a specific message type.
Header for all communications.
Handle for active NAT registrations.
Definition nat_api.c:72
Handle to the PEERSTORE service.
Context for a iterate request.
Context for a store request.
Context for a add hello uri request.
A handle for the PILS service.
Definition pils_api.c:82
The identity of the host (wraps the signing key of the peer).
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Entry in list of pending tasks.
Definition scheduler.c:136
Handle to a client that is connected to a service.
Definition service.c:249
Handle to a service.
Definition service.c:116
Handle for the service.
A 256-bit hashcode.
Struct wrapping information we use for starting the burst.
struct VirtualLink * vl
The VirtualLink of the peer to which we like to burst with.
struct GNUNET_TIME_Relative delay
The delay - calculate from the RTT and which peer was ready to sync first, after we will start the bu...
unsigned int sync_ready
We are ready to start the burst.
struct GNUNET_TIME_Relative rtt
The average RTT between the peers.
Time for absolute time used by GNUnet, in microseconds and in network byte order.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds and in network byte order.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Add address to the list.
Definition transport.h:288
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS.
Definition transport.h:292
struct GNUNET_TIME_RelativeNBO expiration
When does the address expire?
Definition transport.h:302
uint32_t nt
An enum GNUNET_NetworkType in NBO.
Definition transport.h:307
uint32_t aid
Address identifier (used during deletion).
Definition transport.h:297
Add queue to the transport.
Definition transport.h:402
uint32_t nt
An enum GNUNET_NetworkType in NBO.
Definition transport.h:421
uint32_t mtu
Maximum transmission unit, in NBO.
Definition transport.h:426
uint64_t q_len
Queue length, in NBO.
Definition transport.h:432
uint32_t qid
Queue identifier (used to identify the queue).
Definition transport.h:411
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition transport.h:416
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP.
Definition transport.h:406
uint32_t cs
An enum GNUNET_TRANSPORT_ConnectionStatus in NBO.
Definition transport.h:442
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR.
Definition transport.h:268
uint32_t cc
NBO encoding of enum GNUNET_TRANSPORT_CommunicatorCharacteristics
Definition transport.h:273
uint32_t can_burst
The communicator can do burst msgs.
Definition transport.h:278
Message from transport to communicator passing along a backchannel message from the given peer pid.
Definition transport.h:656
struct GNUNET_PeerIdentity pid
Origin peer.
Definition transport.h:671
Message from communicator to transport service asking for transmission of a backchannel message with ...
Definition transport.h:627
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL.
Definition transport.h:631
struct GNUNET_PeerIdentity pid
Target peer.
Definition transport.h:641
Communicator tells transport how queue creation went down.
Definition transport.h:546
uint32_t request_id
Unique ID for the request.
Definition transport.h:556
Transport tells communicator that it wants a new queue.
Definition transport.h:522
uint32_t request_id
Unique ID for the request.
Definition transport.h:531
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition transport.h:536
Remove address from the list.
Definition transport.h:317
uint32_t aid
Address identifier.
Definition transport.h:326
Remove queue, it is no longer available.
Definition transport.h:500
struct GNUNET_PeerIdentity receiver
Receiver that can be addressed via the queue.
Definition transport.h:514
uint32_t qid
Address identifier.
Definition transport.h:509
Transport informs us about being done with an incoming message.
Definition transport.h:375
struct GNUNET_PeerIdentity sender
Sender identifier of the original message.
Definition transport.h:394
uint64_t fc_id
Which message is being ACKed?
Definition transport.h:389
uint32_t reserved
Reserved (0)
Definition transport.h:384
Inform transport about an incoming message.
Definition transport.h:334
struct GNUNET_PeerIdentity neighbour_sender
Direct neighbour sender identifier.
Definition transport.h:364
struct GNUNET_TIME_RelativeNBO expected_address_validity
How long does the communicator believe the address on which the message was received to remain valid?
Definition transport.h:354
struct GNUNET_PeerIdentity sender
Sender identifier.
Definition transport.h:359
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG.
Definition transport.h:338
uint32_t fc_on
Do we use flow control or not?
Definition transport.h:343
uint64_t fc_id
64-bit number to identify the matching ACK.
Definition transport.h:348
uint32_t num_msg_pending
Messages pending (in NBO).
Definition transport.h:767
struct GNUNET_PeerIdentity peer
Target identifier.
Definition transport.h:745
struct GNUNET_TIME_AbsoluteNBO valid_until
Definition transport.h:751
struct GNUNET_TIME_AbsoluteNBO last_validation
Definition transport.h:750
uint32_t num_bytes_pending
Bytes pending (in NBO).
Definition transport.h:772
struct GNUNET_TIME_AbsoluteNBO next_validation
Definition transport.h:752
uint32_t nt
Network type (an enum GNUNET_NetworkType in NBO).
Definition transport.h:740
struct GNUNET_TIME_RelativeNBO rtt
Current round-trip time estimate.
Definition transport.h:757
uint32_t cs
Connection status (in NBO).
Definition transport.h:762
Request to start monitoring.
Definition transport.h:709
Inform transport that message was sent.
Definition transport.h:593
uint64_t mid
Message ID of the original message.
Definition transport.h:607
uint32_t qid
Queue ID for the queue which was used to send the message.
Definition transport.h:612
struct GNUNET_PeerIdentity receiver
Receiver identifier.
Definition transport.h:617
Inform communicator about transport's desire to send a message.
Definition transport.h:564
uint32_t qid
Which queue should we use?
Definition transport.h:573
uint64_t mid
Message ID, used for flow control.
Definition transport.h:578
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG.
Definition transport.h:568
struct GNUNET_PeerIdentity receiver
Receiver identifier.
Definition transport.h:583
Message from transport to communicator to start a burst.
Definition transport.h:681
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_START_BURST.
Definition transport.h:685
struct GNUNET_TIME_RelativeNBO rtt
Definition transport.h:692
struct GNUNET_PeerIdentity pid
Target peer.
Definition transport.h:690
A UUID, a 128 bit "random" value.
Message used to notify the transport API about a message received from the network.
Definition transport.h:144
struct GNUNET_PeerIdentity peer
Which peer sent the message?
Definition transport.h:153
Another peer attempted to talk to us, we should try to establish a connection in the other direction.
struct IncomingRequest * next
Kept in a DLL.
struct IncomingRequest * prev
Kept in a DLL.
struct GNUNET_PEERSTORE_Monitor * nc
Notify context for new HELLOs.
struct GNUNET_PeerIdentity pid
Which peer is this about?
When did we launch this DV learning activity?
struct LearnLaunchEntry * next
Kept (also) in a DLL sorted by launch time.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge that uniquely identifies this activity.
struct LearnLaunchEntry * prev
Kept (also) in a DLL sorted by launch time.
struct GNUNET_TIME_Absolute launch_time
When did we transmit the DV learn message (used to calculate RTT) and determine freshness of paths le...
Unique identifier we attach to a message.
uint64_t uuid
Unique value, generated by incrementing the message_uuid_ctr of struct Neighbour.
Details about what to notify monitors about.
enum GNUNET_TRANSPORT_ConnectionStatus cs
Connection status.
struct GNUNET_TIME_Absolute last_validation
struct GNUNET_TIME_Absolute next_validation
struct GNUNET_TIME_Absolute valid_until
struct GNUNET_TIME_Relative rtt
Current round-trip time estimate.
uint32_t num_msg_pending
Messages pending.
uint32_t num_bytes_pending
Bytes pending.
Closure for dv_neighbour_selection and dv_neighbour_transmission.
const struct TransportDVLearnMessage * dvl
Original message we received.
struct GNUNET_TIME_Absolute in_time
Time we received the message.
const struct DVPathEntryP * hops
The hops taken.
uint16_t bi_history
Bitmap of bidirectional connections encountered.
unsigned int num_eligible
Number of peers eligible for selection.
unsigned int num_selections
Number of peers that were selected for forwarding.
uint32_t selections[MAX_DV_DISCOVERY_SELECTION]
Offsets of the selected peers.
uint16_t nhops
Number of hops in hops.
A neighbour that at least one communicator is connected to.
size_t size_of_global_addresses
Size of all global natted addresses for this neighbour.
struct DistanceVectorHop * dv_tail
Tail of MDLL of DV hops that have this neighbour as next hop.
struct GNUNET_CONTAINER_MultiPeerMap * natted_addresses
Map of struct TransportGlobalNattedAddress for this neighbour.
struct GNUNET_TIME_Absolute last_dv_learn_monotime
Latest DVLearn monotonic time seen from this peer.
int dv_monotime_available
Do we have the latest value for last_dv_learn_monotime from PEERSTORE yet, or are we still waiting fo...
unsigned int number_of_addresses
Number of global natted addresses for this neighbour.
struct Queue * queue_tail
Tail of DLL of queues to this peer.
struct GNUNET_PEERSTORE_StoreContext * sc
Handle to a PEERSTORE store operation to store this pid's last_dv_learn_monotime.
struct DistanceVectorHop * dv_head
Head of MDLL of DV hops that have this neighbour as next hop.
struct VirtualLink * vl
Do we have a confirmed working queue and are thus visible to CORE? If so, this is the virtual link,...
struct Queue * queue_head
Head of DLL of queues to this peer.
struct GNUNET_PeerIdentity pid
Which peer is this about?
enum GNUNET_GenericReturnValue is_global_natted
A queue of this neighbour has a global natted address.
struct GNUNET_PEERSTORE_IterateContext * get
Handle for an operation to fetch last_dv_learn_monotime information from the PEERSTORE,...
Message used to notify the transport service about a message to be transmitted to another peer.
Definition transport.h:230
uint32_t priority
An enum GNUNET_MQ_PriorityPreferences in NBO.
Definition transport.h:239
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_SEND.
Definition transport.h:234
struct GNUNET_PeerIdentity peer
Which peer should receive the message?
Definition transport.h:253
Information per peer and request.
struct GNUNET_BANDWIDTH_Value32NBO bw
How much bandwidth would this tc like to see?
struct TransportClient * tc
Client responsible for the request.
enum GNUNET_MQ_PriorityPreferences pk
What kind of performance preference does this tc have?
struct GSF_PendingRequest * pr
Handle to generic request (generic: from peer or local client).
struct GNUNET_PEERSTORE_Monitor * nc
Notify context for new HELLOs.
struct GNUNET_PeerIdentity pid
Which peer is this about?
Data structure kept when we are waiting for an acknowledgement.
struct AcknowledgementUUIDP ack_uuid
Unique identifier for this transmission operation.
unsigned int num_send
How often the PendingMessage was send via the Queue of this PendingAcknowledgement.
struct PendingAcknowledgement * next_pm
If pm is non-NULL, this is the DLL in which this acknowledgement is kept in relation to its pending m...
struct PendingMessage * pm
Message that was transmitted, may be NULL if the message was ACKed via another channel.
struct PendingAcknowledgement * next_dvh
If dvh is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the DVH that...
struct PendingAcknowledgement * next_pa
Pointers for the DLL of all pending acknowledgements.
struct PendingAcknowledgement * next_queue
If queue is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the queue ...
struct GNUNET_TIME_Absolute transmission_time
Time of the transmission, for RTT calculation.
struct Queue * queue
Queue used for transmission, NULL if the queue has been destroyed (which may happen before we get an ...
struct DistanceVectorHop * dvh
Distance vector path chosen for this transmission, NULL if transmission was to a direct neighbour OR ...
uint16_t message_size
Number of bytes of the original message (to calculate bandwidth).
struct PendingAcknowledgement * prev_pa
Pointers for the DLL of all pending acknowledgements.
struct PendingAcknowledgement * prev_queue
If queue is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the queue ...
struct PendingAcknowledgement * prev_pm
If pm is non-NULL, this is the DLL in which this acknowledgement is kept in relation to its pending m...
struct PendingAcknowledgement * prev_dvh
If dvh is non-NULL, this is the DLL in which this acknowledgement is kept in relation to the DVH that...
Context for select_best_pending_from_link().
struct GNUNET_TIME_Relative to_early_retry_delay
When will we try to transmit the message again for which it was to early to retry.
struct PendingMessage * best
Set to the best message that was found, NULL for none.
int to_early
There are pending messages, but it was to early to send one of them.
unsigned int consideration_counter
Number of pending messages we seriously considered this time.
struct DistanceVectorHop * dvh
DVH that best should take, or NULL for direct transmission.
size_t real_overhead
What is the estimated total overhead for this message?
unsigned int frags_in_flight
There is a pending messages we are sending fragments at the moment.
int frag
Did we have to fragment?
int relb
Did we have to reliability box?
List containing all messages that are yet to be send.
struct PendingMessage * tail_frag
Tail of a MDLL of fragments created for this core message.
struct PendingMessage * frag_parent
Our parent in the fragmentation tree.
enum GNUNET_MQ_PriorityPreferences prefs
Preferences for this message.
struct TransportClient * client
Client that issued the transmission request, if pmt is PMT_CORE.
struct QueueEntry * qe
Set to non-NULL value if this message is currently being given to a communicator and we are awaiting ...
struct MessageUUIDP msg_uuid
UUID to use for this message (used for reassembly of fragments, only initialized if msg_uuid_set is G...
struct PendingMessage * head_frag
Head of a MDLL of fragments created for this core message.
uint16_t bytes_msg
Size of the original message.
enum PendingMessageType pmt
Type of the pending message.
struct PendingMessage * prev_client
Kept in a MDLL of messages from this client (if pmt is PMT_CORE)
struct PendingMessage * prev_vl
Kept in a MDLL of messages for this vl.
struct PendingAcknowledgement * pa_tail
Tail of DLL of PAs for this pending message.
struct PendingMessage * next_vl
Kept in a MDLL of messages for this vl.
struct VirtualLink * vl
Target of the request (always the ultimate destination!).
struct PendingAcknowledgement * pa_head
Head of DLL of PAs for this pending message.
struct DistanceVectorHop * used_dvh
If pmt is of type PMT_DV_BOX we store the used path here.
int16_t msg_uuid_set
GNUNET_YES once msg_uuid was initialized
uint32_t frags_in_flight_round
The round we are (re)-sending fragments.
struct PendingMessage * next_client
Kept in a MDLL of messages from this client (if pmt is PMT_CORE)
uint32_t frags_in_flight
Are we sending fragments at the moment?
uint16_t frag_off
Offset at which we should generate the next fragment.
struct PendingMessage * next_frag
Kept in a MDLL of messages from this cpm (if pmt is #PMT_FRAGMENT_BOx)
uint64_t logging_uuid
UUID we use to identify this message in our logs.
uint16_t frag_count
How many fragments do we have?
struct PendingMessage * prev_frag
Kept in a MDLL of messages from this cpm (if pmt is PMT_FRAGMENT_BOX)
struct PendingMessage * bpm
This message, reliability or DV-boxed.
struct GNUNET_TIME_Absolute next_attempt
What is the earliest time for us to retry transmission of this message?
struct GNUNET_TIME_Absolute timeout
At what time should we give up on the transmission (and no longer retry)?
struct GNUNET_PeerIdentity target
In case of a not validated neighbour, we store the target peer.
Performance data for a transmission possibility.
struct GNUNET_TIME_Relative aged_rtt
Weighted average for the RTT.
struct TransmissionHistoryEntry the[4]
Historic performance data, using a ring buffer of::GOODPUT_AGING_SLOTS entries.
unsigned int last_age
What was the last age when we wrote to the? Used to clear old entries when the age advances.
Helper context struct for HELLO update.
struct GNUNET_TIME_Absolute et
Signature expiration.
struct AddressListEntry * ale
The ale to update.
struct PilsRequest * req
Any pending PILS requests.
struct GNUNET_PILS_Operation * op
The pils operation.
struct PilsRequest * next
DLL.
struct PilsRequest * prev
DLL.
Entry identifying transmission in one of our struct Queue which still awaits an ACK.
struct QueueEntry * next
Kept as a DLL.
struct QueueEntry * prev
Kept as a DLL.
struct GNUNET_TIME_Absolute creation_timestamp
Timestamp this QueueEntry was created.
uint64_t mid
Message ID used for this message with the queue used for transmission.
struct PendingMessage * pm
Pending message this entry is for, or NULL for none.
struct Queue * queue
Queue this entry is queued with.
Closure for check_connection_quality.
unsigned int k
Decremented for each queue, for selection of the k-th queue in q.
struct Queue * q
Set to the k'th queue encountered.
unsigned int num_queues
Set to the total number of queues encountered.
unsigned int quality_count
Set to the number of quality queues encountered.
Handle for a queue.
uint32_t qid
Unique identifier of this queue with the communicator.
struct QueueEntry * queue_tail
End of DLL of unacked transmission requests.
struct Queue * prev_client
Kept in a MDLL.
unsigned int queue_length
Length of the DLL starting at queue_head.
uint32_t num_msg_pending
Messages pending.
struct GNUNET_PEERSTORE_Monitor * mo
Handle for an operation to iterate through all hellos to compare the hello addresses with address whi...
uint64_t q_capacity
Capacity of the queue.
struct Queue * next_neighbour
Kept in a MDLL.
uint32_t num_bytes_pending
Bytes pending.
uint32_t priority
Queue priority.
struct Neighbour * neighbour
Which neighbour is this queue for?
int idle
Set to GNUNET_YES if this queue is idle waiting for some virtual link to give it a pending message.
struct Queue * prev_neighbour
Kept in a MDLL.
struct PerformanceData pd
Performance data for this queue.
enum GNUNET_NetworkType nt
Which network type does this queue use?
struct GNUNET_SCHEDULER_Task * transmit_task
Task scheduled for the time when this queue can (likely) transmit the next message.
struct QueueEntry * queue_head
Head of DLL of unacked transmission requests.
struct PendingAcknowledgement * pa_tail
Tail of DLL of PAs that used this queue.
struct TransportClient * tc
Which communicator offers this queue?
struct Queue * next_client
Kept in a MDLL.
enum GNUNET_GenericReturnValue is_global_natted
Set to GNUNET_YES, if this queues address is a global natted one.
struct GNUNET_TIME_Absolute validated_until
How long do we consider this address to be valid? In the past or zero if we have not yet validated it...
uint32_t mtu
Maximum transmission unit supported by this queue.
unsigned int unlimited_length
Is this queue of unlimited length.
enum GNUNET_TRANSPORT_ConnectionStatus cs
The connection status of this queue.
uint64_t mid_gen
Message ID generator for transmissions on this queue to the communicator.
struct PendingAcknowledgement * pa_head
Head of DLL of PAs that used this queue.
struct sockaddr * address
Address of the other peer.
Information we keep for a message that we are reassembling.
struct GNUNET_CONTAINER_HeapNode * hn
Entry in the reassembly heap (sorted by expiration).
struct GNUNET_TIME_Absolute last_frag
Time we received the last fragment.
struct MessageUUIDP msg_uuid
Original message ID for of the message that all the fragments belong to.
struct VirtualLink * virtual_link
Which neighbour is this context for?
uint8_t * bitfield
Bitfield with msg_size bits representing the positions where we have received fragments.
uint16_t msg_size
How big is the message we are reassembling in total?
struct GNUNET_TIME_Absolute reassembly_timeout
At what time will we give up reassembly of this message?
uint16_t msg_missing
How many bytes of the message are still missing? Defragmentation is complete when msg_missing == 0.
Message used to notify the transport API that it can send another message to the transport service.
Definition transport.h:206
struct GNUNET_PeerIdentity peer
Which peer can CORE handle more from now?
Definition transport.h:221
uint32_t increase_window_delta
Number of messages by which to increase the window, greater or equal to one.
Definition transport.h:216
We got an address of another peer, TRANSPORT service should validate it.
Definition transport.h:838
Entry for the ring buffer caching messages send to core, when virtual link is available.
struct CommunicatorMessageContext * cmc
Communicator context for this ring buffer entry.
struct GNUNET_MessageHeader * mh
The message in this entry.
Message used to notify the transport API that it can send another message to the transport service.
Definition transport.h:162
struct GNUNET_PeerIdentity peer
Which peer can send more now?
Definition transport.h:196
struct DVPathEntryP * dhops
struct PilsRequest * pr
struct TransportDVLearnMessage * fwd
const struct GNUNET_PeerIdentity * next_hop
struct PilsRequest * req
struct DistanceVector * dv
struct PilsRequest * pr
struct QueueQualityContext qqc
struct TransportDVLearnMessage dvl
struct LearnLaunchEntry * lle
struct TransportValidationResponseMessage tvr
struct CommunicatorMessageContext * cmc
Binary block we sign when we sign an address.
struct GNUNET_TIME_AbsoluteNBO mono_time
When was the address generated.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose must be GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS.
struct GNUNET_HashCode addr_hash GNUNET_PACKED
Hash of the address.
Message from the transport service to the library asking to check if both processes agree about this ...
Definition transport.h:62
Information we keep per GOODPUT_AGING_SLOTS about historic (or current) transmission performance.
uint64_t bytes_received
Number of bytes received and acknowledged by the other peer in the interval.
uint64_t bytes_sent
Number of bytes actually sent in the interval.
Outer layer of an encapsulated backchannel message.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION.
Client connected to the transport service.
enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc
Characteristics of this communicator.
struct PendingMessage * pending_msg_head
Head of list of messages pending for this client, sorted by transmission time ("next_attempt" + possi...
enum ClientType type
What type of client is this?
struct AddressListEntry * addr_tail
Tail of list of the addresses of this peer offered by this communicator.
struct TransportClient * next
Kept in a DLL.
struct GNUNET_MQ_Handle * mq
Message queue to the client.
struct GNUNET_SCHEDULER_Task * free_queue_entry_task
Task to check for timed out QueueEntry.
struct PendingMessage * pending_msg_tail
Tail of list of messages pending for this client.
struct TransportClient::@60::@62 monitor
Information for type CT_MONITOR.
struct Queue * queue_head
Head of DLL of queues offered by this communicator.
struct TransportClient::@60::@61 core
Information for type CT_CORE.
struct AddressListEntry * addr_head
Head of list of the addresses of this peer offered by this communicator.
struct GNUNET_CONTAINER_MultiPeerMap * requests
Map of requests for peers the given client application would like to see connections for.
struct TransportClient::@60::@64 application
Information for type CT_APPLICATION.
struct GNUNET_SERVICE_Client * client
Handle to the client.
struct TransportClient * prev
Kept in a DLL.
char * address_prefix
If type is CT_COMMUNICATOR, this communicator supports communicating using these addresses.
struct Queue * queue_tail
Tail of DLL of queues offered by this communicator.
union TransportClient::@60 details
struct TransportClient::@60::@63 communicator
Information for type CT_COMMUNICATOR.
unsigned int total_queue_length
Number of queue entries in all queues to this communicator.
int one_shot
Is this a one-shot monitor?
struct GNUNET_PeerIdentity peer
Peer identity to monitor the addresses of.
enum GNUNET_GenericReturnValue can_burst
Can be used for burst messages.
struct GNUNET_TIME_RelativeNBO ack_delay
How long was the ACK delayed for generating cumulative ACKs? Used to calculate the correct network RT...
struct AcknowledgementUUIDP ack_uuid
UUID of a message being acknowledged.
struct GNUNET_TIME_Absolute receive_time
When did we receive the message we are ACKing? Used to calculate the delay we introduced by cummulati...
struct AcknowledgementUUIDP ack_uuid
UUID of a message being acknowledged.
Outer layer of an encapsulated message send over multiple hops.
struct GNUNET_HashCode hmac
HMAC over the ciphertext of the encrypted, variable-size body that follows.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX.
uint16_t num_hops
Number of hops this messages includes.
uint16_t orig_size
Size this msg had initially.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Ephemeral key setup by the sender for target, used to encrypt the payload.
unsigned int without_fc
Flag if the payload is a control message.
struct GNUNET_ShortHashCode iv
We use an IV here as the ephemeral_key is reused for EPHEMERAL_VALIDITY time to avoid re-signing it a...
uint16_t total_hops
Number of total hops this messages travelled.
Plaintext of the variable-size payload that is encrypted within a struct TransportBackchannelEncapsul...
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Signature of the sender over an GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Current monotonic time of the sending transport service.
struct GNUNET_PeerIdentity sender
Sender's peer identity.
Internal message used by transport for distance vector learning.
struct GNUNET_PeerIdentity initiator
Identity of the peer that started this learning activity.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN.
struct GNUNET_TIME_RelativeNBO non_network_delay
Peers receiving this message and delaying forwarding to other peers for any reason should increment t...
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Time at the initiator when generating the signature.
struct GNUNET_CRYPTO_EddsaSignature init_sig
Signature of this hop over the path, of purpose GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
uint16_t num_hops
Number of hops this messages has travelled, in NBO.
uint16_t bidirectional
Bitmask of the last 16 hops indicating whether they are confirmed available (without DV) in both dire...
Message for Transport-to-Transport Flow control.
uint64_t outbound_window_size
Latest flow control window size we learned from the other peer, in bytes, in NBO.
unsigned int number_of_addresses
Number of TransportGlobalNattedAddress following the struct.
size_t size_of_addresses
Size of all the addresses attached to all TransportGlobalNattedAddress.
uint64_t inbound_window_size
Flow control window size in bytes, in NBO.
struct GNUNET_TIME_AbsoluteNBO sender_time
Timestamp of the sender.
uint32_t seq
Sequence number of the flow control message.
uint64_t outbound_sent
How many bytes has the sender sent that count for flow control at this time.
struct GNUNET_TIME_RelativeNBO rtt
Average RTT for the DistanceVector of the VirtualLink we tell the target.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL.
unsigned int sync_ready
We tell the target, if we are ready to start the burst.
Outer layer of an encapsulated fragmented application message.
uint16_t frag_off
Offset of this fragment in the overall message.
struct MessageUUIDP msg_uuid
Original message ID for of the message that all the fragments belong to.
struct AcknowledgementUUIDP ack_uuid
Unique ID of this fragment (and fragment transmission!).
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT.
uint16_t msg_size
Total size of the message that is being fragmented.
struct TransportGlobalNattedAddress * tgna
The struct TransportGlobalNattedAddress to set.
unsigned int address_length
Length of the address following the struct in NBO.
Confirmation that the receiver got a GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX.
uint32_t ack_counter
Counter of ACKs transmitted by the sender to us.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK.
Outer layer of an encapsulated unfragmented application message sent over an unreliable channel.
uint32_t ack_countdown
Number of messages still to be sent before a commulative ACK is requested.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX.
struct AcknowledgementUUIDP ack_uuid
Unique ID of the message used for signalling receipt of messages sent over possibly unreliable channe...
Message send to another peer to validate that it can indeed receive messages at a particular address.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge to be signed by the receiving peer.
struct GNUNET_TIME_AbsoluteNBO sender_time
Timestamp of the sender, to be copied into the reply to allow sender to calculate RTT.
Message signed by a peer to confirm that it can indeed receive messages at a particular address.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE.
struct GNUNET_TIME_RelativeNBO validity_duration
How long does the sender believe the address on which the challenge was received to remain valid?
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge signed by the receiving peer.
Message send to a peer to respond to a #GNUNET_MESSAGE_TYPE_ADDRESS_VALIDATION_CHALLENGE.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
The challenge that was signed by the receiving peer.
struct GNUNET_CRYPTO_EddsaSignature signature
The peer's signature matching the GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE purpose.
struct GNUNET_PEERSTORE_StoreHelloContext * sc
State we keep for validation activities.
struct GNUNET_TIME_Absolute valid_until
How long did the peer claim this address to be valid? Capped at minimum of MAX_ADDRESS_VALID_UNTIL re...
struct GNUNET_PeerIdentity pid
For which peer is address to be validated (or possibly valid)? Serves as key in the validation_map.
struct GNUNET_TIME_Absolute validated_until
How long do we consider this address to be valid? In the past or zero if we have not yet validated it...

◆ DELAY_WARN_THRESHOLD

#define DELAY_WARN_THRESHOLD    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)

If a queue delays the next message by more than this number of seconds we log a warning.

Note: this is for testing, the value chosen here might be too aggressively low!

Definition at line 199 of file gnunet-service-transport.c.

◆ DV_FORWARD_TIMEOUT

#define DV_FORWARD_TIMEOUT    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)

If a DVBox could not be forwarded after this number of seconds we drop it.

Definition at line 206 of file gnunet-service-transport.c.

◆ DEFAULT_ACK_WAIT_DURATION

#define DEFAULT_ACK_WAIT_DURATION    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)

Default value for how long we wait for reliability ack.

Definition at line 212 of file gnunet-service-transport.c.

◆ DV_QUALITY_RTT_THRESHOLD

#define DV_QUALITY_RTT_THRESHOLD    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)

We only consider queues as "quality" connections when suppressing the generation of DV initiation messages if the latency of the queue is below this threshold.

Definition at line 220 of file gnunet-service-transport.c.

◆ DV_PATH_VALIDITY_TIMEOUT

#define DV_PATH_VALIDITY_TIMEOUT    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)

How long do we consider a DV path valid if we see no further updates on it? Note: the value chosen here might be too low!

Definition at line 227 of file gnunet-service-transport.c.

◆ BACKCHANNEL_INACTIVITY_TIMEOUT

#define BACKCHANNEL_INACTIVITY_TIMEOUT    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)

How long do we cache backchannel (struct Backtalker) information after a backchannel goes inactive?

Definition at line 234 of file gnunet-service-transport.c.

◆ DV_PATH_DISCOVERY_FREQUENCY

#define DV_PATH_DISCOVERY_FREQUENCY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)

How long before paths expire would we like to (re)discover DV paths? Should be below DV_PATH_VALIDITY_TIMEOUT.

Definition at line 241 of file gnunet-service-transport.c.

◆ EPHEMERAL_VALIDITY

#define EPHEMERAL_VALIDITY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)

How long are ephemeral keys valid?

Definition at line 247 of file gnunet-service-transport.c.

◆ REASSEMBLY_EXPIRATION

#define REASSEMBLY_EXPIRATION    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)

How long do we keep partially reassembled messages around before giving up?

Definition at line 253 of file gnunet-service-transport.c.

◆ FAST_VALIDATION_CHALLENGE_FREQ

#define FAST_VALIDATION_CHALLENGE_FREQ    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1)

What is the fastest rate at which we send challenges if we keep learning an address (gossip, DHT, etc.)?

Definition at line 260 of file gnunet-service-transport.c.

◆ MAX_VALIDATION_CHALLENGE_FREQ

#define MAX_VALIDATION_CHALLENGE_FREQ    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_DAYS, 1)

What is the slowest rate at which we send challenges?

Definition at line 266 of file gnunet-service-transport.c.

◆ ACK_CUMMULATOR_TIMEOUT

#define ACK_CUMMULATOR_TIMEOUT    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)

How long until we forget about historic accumulators and thus reset the ACK counter? Should exceed the maximum time an active connection experiences without an ACK.

Definition at line 274 of file gnunet-service-transport.c.

◆ DV_LEARN_BASE_FREQUENCY

#define DV_LEARN_BASE_FREQUENCY   GNUNET_TIME_UNIT_MINUTES

What is the non-randomized base frequency at which we would initiate DV learn messages?

Definition at line 281 of file gnunet-service-transport.c.

◆ DV_LEARN_QUALITY_THRESHOLD

#define DV_LEARN_QUALITY_THRESHOLD   100

How many good connections (confirmed, bi-directional, not DV) do we need to have to suppress initiating DV learn messages?

Definition at line 287 of file gnunet-service-transport.c.

◆ MAX_ADDRESS_VALID_UNTIL

#define MAX_ADDRESS_VALID_UNTIL    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MONTHS, 1)

When do we forget an invalid address for sure?

Definition at line 292 of file gnunet-service-transport.c.

◆ ADDRESS_VALIDATION_LIFETIME

#define ADDRESS_VALIDATION_LIFETIME    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)

How long do we consider an address valid if we just checked?

Definition at line 298 of file gnunet-service-transport.c.

◆ MIN_DELAY_ADDRESS_VALIDATION

#define MIN_DELAY_ADDRESS_VALIDATION   GNUNET_TIME_UNIT_MILLISECONDS

What is the maximum frequency at which we do address validation? A random value between 0 and this value is added when scheduling the validation_task (both to ensure we do not validate too often, and to randomize a bit).

Definition at line 307 of file gnunet-service-transport.c.

◆ VALIDATION_RTT_BUFFER_FACTOR

#define VALIDATION_RTT_BUFFER_FACTOR   3

How many network RTTs before an address validation expires should we begin trying to revalidate? (Note that the RTT used here is the one that we experienced during the last validation, not necessarily the latest RTT observed).

Definition at line 315 of file gnunet-service-transport.c.

◆ COMMUNICATOR_TOTAL_QUEUE_LIMIT

#define COMMUNICATOR_TOTAL_QUEUE_LIMIT   512

How many messages can we have pending for a given communicator process before we start to throttle that communicator?

Used if a communicator might be CPU-bound and cannot handle the traffic.

Definition at line 323 of file gnunet-service-transport.c.

◆ QUEUE_LENGTH_LIMIT

#define QUEUE_LENGTH_LIMIT   32

How many messages can we have pending for a given queue (queue to a particular peer via a communicator) process before we start to throttle that queue?

Definition at line 330 of file gnunet-service-transport.c.

◆ QUEUE_ENTRY_TIMEOUT

#define QUEUE_ENTRY_TIMEOUT    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)

Definition at line 335 of file gnunet-service-transport.c.

◆ RTT_DIFF

Difference of the average RTT for the DistanceVector calculate by us and the target we are willing to accept for starting the burst.

Definition at line 342 of file gnunet-service-transport.c.

Typedef Documentation

◆ DVMessageHandler

typedef void(* DVMessageHandler) (void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)

Function to call to further operate on the now DV encapsulated message hdr, forwarding it via next_hop under respect of options.

Parameters
clsclosure
next_hopnext hop of the DV path
hdrencapsulated message, technically a struct TransportDFBoxMessage
optionsoptions of the original message

Definition at line 5213 of file gnunet-service-transport.c.

Enumeration Type Documentation

◆ ClientType

enum ClientType

What type of client is the struct TransportClient about?

Enumerator
CT_NONE 

We do not know yet (client is fresh).

CT_CORE 

Is the CORE service, we need to forward traffic to it.

CT_MONITOR 

It is a monitor, forward monitor data.

CT_COMMUNICATOR 

It is a communicator, use for communication.

CT_APPLICATION 

"Application" telling us where to connect (i.e.

TOPOLOGY, DHT or CADET).

Definition at line 1032 of file gnunet-service-transport.c.

1033{
1037 CT_NONE = 0,
1038
1042 CT_CORE = 1,
1043
1047 CT_MONITOR = 2,
1048
1052 CT_COMMUNICATOR = 3,
1053
1057 CT_APPLICATION = 4
1058};

◆ RouteMessageOptions

Which transmission options are allowable for transmission? Interpreted bit-wise!

Enumerator
RMO_NONE 

Only confirmed, non-DV direct neighbours.

RMO_DV_ALLOWED 

We are allowed to use DV routing for this hdr.

RMO_UNCONFIRMED_ALLOWED 

We are allowed to use unconfirmed queues or DV routes for this message.

RMO_ANYTHING_GOES 

Reliable and unreliable, DV and non-DV are all acceptable.

RMO_REDUNDANT 

If we have multiple choices, it is OK to send this message over multiple channels at the same time to improve loss tolerance.

(We do at most 2 transmissions.)

Definition at line 1065 of file gnunet-service-transport.c.

1066{
1070 RMO_NONE = 0,
1071
1075 RMO_DV_ALLOWED = 1,
1076
1081
1086
1092 RMO_REDUNDANT = 4
1093};

◆ PendingMessageType

Types of different pending messages.

Enumerator
PMT_CORE 

Ordinary message received from the CORE service.

PMT_FRAGMENT_BOX 

Fragment box.

PMT_RELIABILITY_BOX 

Reliability box.

PMT_DV_BOX 

Pending message created during forward_dv_box().

Definition at line 2215 of file gnunet-service-transport.c.

2216{
2220 PMT_CORE = 0,
2221
2225 PMT_FRAGMENT_BOX = 1,
2226
2231
2235 PMT_DV_BOX = 3
2236};

Function Documentation

◆ get_age()

static unsigned int get_age ( )
static

Get an offset into the transmission history buffer for struct PerformanceData.

Note that the caller must perform the required modulo GOODPUT_AGING_SLOTS operation before indexing into the array!

An 'age' lasts 15 minute slots.

Returns
current age of the world

Definition at line 3127 of file gnunet-service-transport.c.

3128{
3129 struct GNUNET_TIME_Absolute now;
3130
3131 now = GNUNET_TIME_absolute_get ();
3132 return now.abs_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us / 15;
3133}

References GNUNET_TIME_Absolute::abs_value_us, GNUNET_TIME_absolute_get(), and GNUNET_TIME_UNIT_MINUTES.

Referenced by update_performance_data().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_incoming_request()

static void free_incoming_request ( struct IncomingRequest ir)
static

Release ir data structure.

Parameters
irdata structure to release

Definition at line 3142 of file gnunet-service-transport.c.

3143{
3145 GNUNET_assert (ir_total > 0);
3146 ir_total--;
3147 if (NULL != ir->nc)
3149 ir->nc = NULL;
3150 GNUNET_free (ir);
3151}

References GNUNET_assert, GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_PEERSTORE_monitor_stop(), ir_head, ir_tail, ir_total, and IncomingRequest::nc.

Referenced by do_shutdown(), and sign_t_validation_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_pending_acknowledgement()

static void free_pending_acknowledgement ( struct PendingAcknowledgement pa)
static

Release pa data structure.

Parameters
padata structure to release

Definition at line 3160 of file gnunet-service-transport.c.

3161{
3162 struct Queue *q = pa->queue;
3163 struct PendingMessage *pm = pa->pm;
3164 struct DistanceVectorHop *dvh = pa->dvh;
3165
3167 "free_pending_acknowledgement\n");
3168 if (NULL != q)
3169 {
3170 GNUNET_CONTAINER_MDLL_remove (queue, q->pa_head, q->pa_tail, pa);
3171 pa->queue = NULL;
3172 }
3173 if (NULL != pm)
3174 {
3176 "remove pa from message\n");
3178 "remove pa from message %" PRIu64 "\n",
3179 pm->logging_uuid);
3181 "remove pa from message %u\n",
3182 pm->pmt);
3184 "remove pa from message %s\n",
3186 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3187 pa->pm = NULL;
3188 }
3189 if (NULL != dvh)
3190 {
3191 GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
3192 pa->queue = NULL;
3193 }
3196 &pa->ack_uuid.value,
3197 pa));
3198 GNUNET_free (pa);
3199}

References PendingAcknowledgement::ack_uuid, PendingAcknowledgement::dvh, GNUNET_assert, GNUNET_CONTAINER_MDLL_remove, GNUNET_CONTAINER_multiuuidmap_remove(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_uuid2s(), GNUNET_YES, DistanceVectorHop::pa_head, DistanceVectorHop::pa_tail, pending_acks, PendingAcknowledgement::pm, pm, q, queue(), PendingAcknowledgement::queue, and AcknowledgementUUIDP::value.

Referenced by free_pending_ack_cb(), and handle_acknowledged().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_fragment_tree()

static void free_fragment_tree ( struct PendingMessage root)
static

Free fragment tree below root, excluding root itself.

FIXME: this does NOT seem to have the intended semantics based on how this is called. Seems we generally DO expect root to be free'ed itself as well!

Parameters
rootroot of the tree to free

Definition at line 3211 of file gnunet-service-transport.c.

3212{
3213 struct PendingMessage *frag;
3214
3215 while (NULL != (frag = root->head_frag))
3216 {
3217 struct PendingAcknowledgement *pa;
3218
3219 free_fragment_tree (frag);
3220 while (NULL != (pa = frag->pa_head))
3221 {
3222 GNUNET_CONTAINER_MDLL_remove (pm, frag->pa_head, frag->pa_tail, pa);
3223 pa->pm = NULL;
3224 }
3225 GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag);
3226 if (NULL != frag->qe)
3227 {
3228 GNUNET_assert (frag == frag->qe->pm);
3229 frag->qe->pm = NULL;
3230 }
3232 "Free frag %p\n",
3233 frag);
3234 GNUNET_free (frag);
3235 }
3236}

References free_fragment_tree(), GNUNET_assert, GNUNET_CONTAINER_MDLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, PendingMessage::head_frag, PendingMessage::pa_head, PendingMessage::pa_tail, PendingAcknowledgement::pm, QueueEntry::pm, pm, PendingMessage::qe, and PendingMessage::tail_frag.

Referenced by free_fragment_tree(), and free_pending_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_pending_message()

static void free_pending_message ( struct PendingMessage pm)
static

Release memory associated with pm and remove pm from associated data structures.

pm must be a top-level pending message and not a fragment in the tree. The entire tree is freed (if applicable).

Parameters
pmthe pending message to free

Definition at line 3247 of file gnunet-service-transport.c.

3248{
3249 struct TransportClient *tc = pm->client;
3250 struct VirtualLink *vl = pm->vl;
3251 struct PendingAcknowledgement *pa;
3252
3254 "Freeing pm %p\n",
3255 pm);
3256 if (NULL != tc)
3257 {
3259 tc->details.core.pending_msg_head,
3260 tc->details.core.pending_msg_tail,
3261 pm);
3262 }
3263 if ((NULL != vl) && (NULL == pm->frag_parent))
3264 {
3266 "Removing pm %" PRIu64 "\n",
3267 pm->logging_uuid);
3269 vl->pending_msg_head,
3270 vl->pending_msg_tail,
3271 pm);
3272 }
3273 else if (NULL != pm->frag_parent && PMT_DV_BOX != pm->pmt)
3274 {
3275 struct PendingMessage *root = pm->frag_parent;
3276
3277 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
3278 root = root->frag_parent;
3279
3280 root->frag_count--;
3281 }
3282 while (NULL != (pa = pm->pa_head))
3283 {
3284 if (NULL == pa)
3286 "free pending pa null\n");
3287 if (NULL == pm->pa_tail)
3289 "free pending pa_tail null\n");
3290 if (NULL == pa->prev_pa)
3292 "free pending pa prev null\n");
3293 if (NULL == pa->next_pa)
3295 "free pending pa next null\n");
3296 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3297 pa->pm = NULL;
3298 }
3299
3301 if (NULL != pm->qe)
3302 {
3303 GNUNET_assert (pm == pm->qe->pm);
3304 pm->qe->pm = NULL;
3305 }
3306 if (NULL != pm->bpm)
3307 {
3308 free_fragment_tree (pm->bpm);
3309 if (NULL != pm->bpm->qe)
3310 {
3311 struct QueueEntry *qe = pm->bpm->qe;
3312
3313 qe->pm = NULL;
3314 }
3315 GNUNET_free (pm->bpm);
3316 }
3317
3318 GNUNET_free (pm);
3320 "Freeing pm done\n");
3321}

References PendingMessage::frag_count, PendingMessage::frag_parent, free_fragment_tree(), GNUNET_assert, GNUNET_CONTAINER_MDLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, PendingAcknowledgement::next_pa, VirtualLink::pending_msg_head, VirtualLink::pending_msg_tail, PendingAcknowledgement::pm, pm, PendingMessage::pmt, PMT_DV_BOX, PendingAcknowledgement::prev_pa, qe, and tc.

Referenced by client_send_response(), completed_pending_message(), free_virtual_link(), and transmit_on_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_reassembly_context()

static void free_reassembly_context ( struct ReassemblyContext rc)
static

Free rc.

Parameters
rcdata structure to free

Definition at line 3330 of file gnunet-service-transport.c.

3331{
3332 struct VirtualLink *vl = rc->virtual_link;
3333
3337 rc->msg_uuid.uuid,
3338 rc));
3339 GNUNET_free (rc);
3340}

References GNUNET_assert, GNUNET_CONTAINER_heap_remove_node(), GNUNET_CONTAINER_multihashmap32_remove(), GNUNET_free, GNUNET_OK, ReassemblyContext::hn, ReassemblyContext::msg_uuid, VirtualLink::reassembly_map, MessageUUIDP::uuid, and ReassemblyContext::virtual_link.

Referenced by free_reassembly_cb(), handle_fragment_box(), and reassembly_cleanup_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ reassembly_cleanup_task()

static void reassembly_cleanup_task ( void *  cls)
static

Task run to clean up reassembly context of a neighbour that have expired.

Parameters
clsa struct Neighbour

Definition at line 3349 of file gnunet-service-transport.c.

3350{
3351 struct VirtualLink *vl = cls;
3352 struct ReassemblyContext *rc;
3353
3354 vl->reassembly_timeout_task = NULL;
3355 while (NULL != (rc = GNUNET_CONTAINER_heap_peek (vl->reassembly_heap)))
3356 {
3358 .rel_value_us)
3359 {
3361 continue;
3362 }
3367 vl);
3368 return;
3369 }
3370}

References free_reassembly_context(), GNUNET_assert, GNUNET_CONTAINER_heap_peek(), GNUNET_SCHEDULER_add_at(), GNUNET_TIME_absolute_get_remaining(), reassembly_cleanup_task(), VirtualLink::reassembly_heap, ReassemblyContext::reassembly_timeout, VirtualLink::reassembly_timeout_task, and GNUNET_TIME_Relative::rel_value_us.

Referenced by handle_fragment_box(), and reassembly_cleanup_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_reassembly_cb()

static int free_reassembly_cb ( void *  cls,
uint32_t  key,
void *  value 
)
static

function called to free_reassembly_context().

Parameters
clsNULL
keyunused
valuea struct ReassemblyContext to free
Returns
GNUNET_OK (continue iteration)

Definition at line 3382 of file gnunet-service-transport.c.

3383{
3384 struct ReassemblyContext *rc = value;
3385
3386 (void) cls;
3387 (void) key;
3389 return GNUNET_OK;
3390}

References free_reassembly_context(), GNUNET_OK, key, and value.

Referenced by free_virtual_link().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_virtual_link()

static void free_virtual_link ( struct VirtualLink vl)
static

Free virtual link.

Parameters
vllink data to free

Definition at line 3399 of file gnunet-service-transport.c.

3400{
3401 struct PendingMessage *pm;
3402 struct CoreSentContext *csc;
3403
3405 "free virtual link %p\n",
3406 vl);
3407
3408 if (NULL != vl->reassembly_map)
3409 {
3412 NULL);
3414 vl->reassembly_map = NULL;
3416 vl->reassembly_heap = NULL;
3417 }
3418 if (NULL != vl->reassembly_timeout_task)
3419 {
3422 }
3423 while (NULL != (pm = vl->pending_msg_head))
3427 if (NULL != vl->visibility_task)
3428 {
3430 vl->visibility_task = NULL;
3431 }
3432 if (NULL != vl->fc_retransmit_task)
3433 {
3435 vl->fc_retransmit_task = NULL;
3436 }
3437 while (NULL != (csc = vl->csc_head))
3438 {
3440 GNUNET_assert (vl == csc->vl);
3441 csc->vl = NULL;
3442 }
3443 GNUNET_break (NULL == vl->n);
3444 GNUNET_break (NULL == vl->dv);
3445 GNUNET_free (vl);
3446}

References VirtualLink::csc_head, VirtualLink::csc_tail, VirtualLink::dv, VirtualLink::fc_retransmit_task, free_pending_message(), free_reassembly_cb(), GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_heap_destroy(), GNUNET_CONTAINER_multihashmap32_destroy(), GNUNET_CONTAINER_multihashmap32_iterate(), GNUNET_CONTAINER_multipeermap_remove(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_SCHEDULER_cancel(), GNUNET_YES, links, VirtualLink::n, VirtualLink::pending_msg_head, pm, VirtualLink::reassembly_heap, VirtualLink::reassembly_map, VirtualLink::reassembly_timeout_task, VirtualLink::target, VirtualLink::visibility_task, and CoreSentContext::vl.

Referenced by check_link_down(), free_dv_route(), and free_neighbour().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_validation_state()

static void free_validation_state ( struct ValidationState vs)
static

Free validation state.

Parameters
vsvalidation state to free

Definition at line 3455 of file gnunet-service-transport.c.

3456{
3457 if (NULL != vs->revalidation_task)
3458 {
3459 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
3460 vs->revalidation_task = NULL;
3461 }
3462 /*memcpy (&hkey,
3463 &hc,
3464 sizeof (hkey));*/
3466 "Remove key %s for address %s map size %u contains %u during freeing state\n",
3467 GNUNET_h2s (&vs->hc),
3468 vs->address,
3471 &vs->hc));
3474 GNUNET_YES ==
3477 vs->hn = NULL;
3478 if (NULL != vs->sc)
3479 {
3481 "store cancel\n");
3483 vs->sc = NULL;
3484 }
3485 GNUNET_free (vs->address);
3486 GNUNET_free (vs);
3487}

References GNUNET_assert, GNUNET_CONTAINER_heap_remove_node(), GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_CONTAINER_multihashmap_size(), GNUNET_CONTAINER_multipeermap_remove(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_h2s(), GNUNET_log, GNUNET_PEERSTORE_store_cancel(), GNUNET_SCHEDULER_cancel(), GNUNET_YES, ValidationState::pid, revalidation_map, and validation_map.

Referenced by free_validation_state_cb(), and validation_start_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookup_neighbour()

static struct Neighbour * lookup_neighbour ( const struct GNUNET_PeerIdentity pid)
static

Lookup neighbour for peer pid.

Parameters
pidneighbour to look for
Returns
NULL if we do not have this peer as a neighbour

Definition at line 3497 of file gnunet-service-transport.c.

3498{
3500}

References GNUNET_CONTAINER_multipeermap_get(), neighbours, and pid.

Referenced by find_queue(), handle_add_queue_message(), handle_communicator_backchannel(), handle_dv_box(), handle_dv_learn(), learn_dv_path(), route_control_message_without_fc(), sign_dhp_cp(), sign_t_validation_cb(), and transmit_cummulative_ack_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookup_virtual_link()

static struct VirtualLink * lookup_virtual_link ( const struct GNUNET_PeerIdentity pid)
static

Lookup virtual link for peer pid.

Parameters
pidvirtual link to look for
Returns
NULL if we do not have this peer as a virtual link

Definition at line 3510 of file gnunet-service-transport.c.

3511{
3513}

References GNUNET_CONTAINER_multipeermap_get(), links, and pid.

Referenced by activate_core_visible_dv_path(), check_vl_transmission(), free_queue(), handle_client_recv_ok(), handle_client_send(), handle_communicator_backchannel(), handle_flow_control(), handle_fragment_box(), handle_raw_message(), handle_validation_response(), sign_dhp_cp(), sign_t_validation_cb(), and transmit_cummulative_ack_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_distance_vector_hop()

static void free_distance_vector_hop ( struct DistanceVectorHop dvh)
static

Free a dvh.

Callers MAY want to check if this was the last path to the target, and if so call free_dv_route to also free the associated DV entry in dv_routes (if not, the associated scheduler job should eventually take care of it).

Parameters
dvhhop to free

Definition at line 3559 of file gnunet-service-transport.c.

3560{
3561 struct Neighbour *n = dvh->next_hop;
3562 struct DistanceVector *dv = dvh->dv;
3563 struct PendingAcknowledgement *pa;
3564
3565 while (NULL != (pa = dvh->pa_head))
3566 {
3568 pa->dvh = NULL;
3569 }
3570 GNUNET_CONTAINER_MDLL_remove (neighbour, n->dv_head, n->dv_tail, dvh);
3572 GNUNET_free (dvh);
3573}

References DistanceVectorHop::dv, DistanceVector::dv_head, Neighbour::dv_head, DistanceVector::dv_tail, Neighbour::dv_tail, PendingAcknowledgement::dvh, GNUNET_CONTAINER_MDLL_remove, GNUNET_free, DistanceVectorHop::next_hop, DistanceVectorHop::pa_head, and DistanceVectorHop::pa_tail.

Referenced by free_dv_route(), free_neighbour(), and path_cleanup_cb().

Here is the caller graph for this function:

◆ check_link_down()

static void check_link_down ( void *  cls)
static

Task run to check whether the hops of the cls still are validated, or if we need to core about disconnection.

Parameters
clsa struct VirtualLink

Definition at line 3998 of file gnunet-service-transport.c.

3999{
4000 struct VirtualLink *vl = cls;
4001 struct DistanceVector *dv = vl->dv;
4002 struct Neighbour *n = vl->n;
4003 struct GNUNET_TIME_Absolute dvh_timeout;
4004 struct GNUNET_TIME_Absolute q_timeout;
4005
4007 "Checking if link is down\n");
4008 vl->visibility_task = NULL;
4009 dvh_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
4010 if (NULL != dv)
4011 {
4012 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4013 pos = pos->next_dv)
4014 dvh_timeout = GNUNET_TIME_absolute_max (dvh_timeout,
4015 pos->path_valid_until);
4016 if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
4017 {
4018 vl->dv->vl = NULL;
4019 vl->dv = NULL;
4020 }
4021 }
4022 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
4023 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
4024 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
4026 {
4027 vl->n->vl = NULL;
4028 vl->n = NULL;
4029 }
4030 if ((NULL == vl->n) && (NULL == vl->dv))
4031 {
4033 free_virtual_link (vl);
4034 return;
4035 }
4036 vl->visibility_task =
4037 GNUNET_SCHEDULER_add_at (GNUNET_TIME_absolute_max (q_timeout, dvh_timeout),
4039 vl);
4040}

References check_link_down(), cores_send_disconnect_info(), VirtualLink::dv, DistanceVector::dv_head, free_virtual_link(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_SCHEDULER_add_at(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_absolute_max(), GNUNET_TIME_UNIT_ZERO_ABS, VirtualLink::n, q, Neighbour::queue_head, GNUNET_TIME_Relative::rel_value_us, VirtualLink::target, VirtualLink::visibility_task, DistanceVector::vl, and Neighbour::vl.

Referenced by activate_core_visible_dv_path(), check_link_down(), free_dv_route(), free_neighbour(), free_queue(), and handle_validation_response().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cores_send_disconnect_info()

static void cores_send_disconnect_info ( const struct GNUNET_PeerIdentity pid)
static

Send message to CORE clients that we lost a connection.

Parameters
pidpeer the connection was for

Definition at line 3592 of file gnunet-service-transport.c.

3593{
3595 "Informing CORE clients about disconnect from %s\n",
3596 GNUNET_i2s (pid));
3597 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3598 {
3599 struct GNUNET_MQ_Envelope *env;
3600 struct DisconnectInfoMessage *dim;
3601
3602 if (CT_CORE != tc->type)
3603 continue;
3605 dim->peer = *pid;
3606 GNUNET_MQ_send (tc->mq, env);
3607 }
3608}

References clients_head, CT_CORE, dim, env, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT, GNUNET_MQ_msg, GNUNET_MQ_send(), pid, and tc.

Referenced by check_link_down(), free_dv_route(), and free_neighbour().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_dv_route()

static void free_dv_route ( struct DistanceVector dv)
static

Free entry in dv_routes.

First frees all hops to the target, and if there are no entries left, frees dv as well.

Parameters
dvroute to free

Definition at line 3618 of file gnunet-service-transport.c.

3619{
3620 struct DistanceVectorHop *dvh;
3621 struct VirtualLink *vl;
3622
3623 while (NULL != (dvh = dv->dv_head))
3625
3627 GNUNET_YES ==
3629 if (NULL != (vl = dv->vl))
3630 {
3631 GNUNET_assert (dv == vl->dv);
3632 vl->dv = NULL;
3633 if (NULL == vl->n)
3634 {
3636 free_virtual_link (vl);
3637 }
3638 else
3639 {
3642 }
3643 dv->vl = NULL;
3644 }
3645
3646 if (NULL != dv->timeout_task)
3647 {
3649 dv->timeout_task = NULL;
3650 }
3651 GNUNET_free (dv->km);
3652 GNUNET_free (dv);
3653}

References check_link_down(), cores_send_disconnect_info(), VirtualLink::dv, DistanceVector::dv_head, dv_routes, free_distance_vector_hop(), free_virtual_link(), GNUNET_assert, GNUNET_CONTAINER_multipeermap_remove(), GNUNET_free, GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_cancel(), GNUNET_YES, DistanceVector::km, VirtualLink::n, DistanceVector::target, DistanceVector::timeout_task, VirtualLink::visibility_task, and DistanceVector::vl.

Referenced by free_dv_routes_cb(), free_neighbour(), and path_cleanup_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ notify_monitor()

static void notify_monitor ( struct TransportClient tc,
const struct GNUNET_PeerIdentity peer,
const char *  address,
enum GNUNET_NetworkType  nt,
const struct MonitorEvent me 
)
static

Notify monitor tc about an event.

That tc cares about the event has already been checked.

Send tc information in me about a peer's status with respect to some address to all monitors that care.

Parameters
tcmonitor to inform
peerpeer the information is about
addressaddress the information is about
ntnetwork type associated with address
medetailed information to transmit

Definition at line 3670 of file gnunet-service-transport.c.

3675{
3676 struct GNUNET_MQ_Envelope *env;
3678 size_t addr_len = strlen (address) + 1;
3679
3681 addr_len,
3683 md->nt = htonl ((uint32_t) nt);
3684 md->peer = *peer;
3685 md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
3686 md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
3687 md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
3688 md->rtt = GNUNET_TIME_relative_hton (me->rtt);
3689 md->cs = htonl ((uint32_t) me->cs);
3690 md->num_msg_pending = htonl (me->num_msg_pending);
3691 md->num_bytes_pending = htonl (me->num_bytes_pending);
3692 memcpy (&md[1], address, addr_len);
3693 GNUNET_MQ_send (tc->mq, env);
3694}

References address, GNUNET_TRANSPORT_MonitorData::cs, env, GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_TIME_absolute_hton(), GNUNET_TIME_relative_hton(), GNUNET_TRANSPORT_MonitorData::last_validation, me, GNUNET_TRANSPORT_MonitorData::next_validation, nt, GNUNET_TRANSPORT_MonitorData::nt, GNUNET_TRANSPORT_MonitorData::num_bytes_pending, GNUNET_TRANSPORT_MonitorData::num_msg_pending, GNUNET_TRANSPORT_MonitorData::peer, GNUNET_TRANSPORT_MonitorData::rtt, tc, and GNUNET_TRANSPORT_MonitorData::valid_until.

Referenced by notify_client_queues(), and notify_monitors().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ notify_monitors()

static void notify_monitors ( const struct GNUNET_PeerIdentity peer,
const char *  address,
enum GNUNET_NetworkType  nt,
const struct MonitorEvent me 
)
static

Send information in me about a peer's status with respect to some address to all monitors that care.

Parameters
peerpeer the information is about
addressaddress the information is about
ntnetwork type associated with address
medetailed information to transmit

Definition at line 3707 of file gnunet-service-transport.c.

3711{
3712 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3713 {
3714 if (CT_MONITOR != tc->type)
3715 continue;
3716 if (tc->details.monitor.one_shot)
3717 continue;
3718 if ((GNUNET_NO == GNUNET_is_zero (&tc->details.monitor.peer)) &&
3719 (0 != GNUNET_memcmp (&tc->details.monitor.peer, peer)))
3720 continue;
3721 notify_monitor (tc, peer, address, nt, me);
3722 }
3723}

References address, clients_head, CT_MONITOR, GNUNET_is_zero, GNUNET_memcmp, GNUNET_NO, me, notify_monitor(), nt, GNUNET_TRANSPORT_MonitorData::peer, and tc.

Referenced by free_queue(), and handle_add_queue_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ client_connect_cb()

static void * client_connect_cb ( void *  cls,
struct GNUNET_SERVICE_Client client,
struct GNUNET_MQ_Handle mq 
)
static

Called whenever a client connects.

Allocates our data structures associated with that client.

Parameters
clsclosure, NULL
clientidentification of the client
mqmessage queue for the client
Returns
our struct TransportClient

Definition at line 3736 of file gnunet-service-transport.c.

3739{
3740 struct TransportClient *tc;
3741
3742 (void) cls;
3743 tc = GNUNET_new (struct TransportClient);
3744 tc->client = client;
3745 tc->mq = mq;
3748 "Client %p of type %u connected\n",
3749 tc,
3750 tc->type);
3751 return tc;
3752}

References TransportClient::client, clients_head, clients_tail, GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_new, mq, and tc.

◆ remove_global_addresses()

static enum GNUNET_GenericReturnValue remove_global_addresses ( void *  cls,
const struct GNUNET_PeerIdentity pid,
void *  value 
)
static

Definition at line 3756 of file gnunet-service-transport.c.

3759{
3760 struct TransportGlobalNattedAddress *tgna = value;
3761 (void) cls;
3762
3763 GNUNET_free (tgna);
3764
3765 return GNUNET_OK;
3766}

References GNUNET_free, GNUNET_OK, and value.

Referenced by free_neighbour().

Here is the caller graph for this function:

◆ free_neighbour()

static void free_neighbour ( struct Neighbour neighbour,
enum GNUNET_GenericReturnValue  drop_link 
)
static

Release memory used by neighbour.

Parameters
neighbourneighbour entry to free
drop_linkflag to decide whether to drop its virtual link

Definition at line 3776 of file gnunet-service-transport.c.

3778{
3779 struct DistanceVectorHop *dvh;
3780 struct VirtualLink *vl;
3781
3782 GNUNET_assert (NULL == neighbour->queue_head);
3785 &neighbour->pid,
3786 neighbour));
3788 "Freeing neighbour\n");
3791 NULL);
3793 while (NULL != (dvh = neighbour->dv_head))
3794 {
3795 struct DistanceVector *dv = dvh->dv;
3796
3798 if (NULL == dv->dv_head)
3799 free_dv_route (dv);
3800 }
3801 if (NULL != neighbour->get)
3802 {
3804 neighbour->get = NULL;
3805 }
3806 if (NULL != neighbour->sc)
3807 {
3809 "store cancel\n");
3810 GNUNET_PEERSTORE_store_cancel (neighbour->sc);
3811 neighbour->sc = NULL;
3812 }
3813 if (NULL != (vl = neighbour->vl))
3814 {
3815 GNUNET_assert (neighbour == vl->n);
3816 vl->n = NULL;
3817 if ((GNUNET_YES == drop_link) || (NULL == vl->dv))
3818 {
3821 }
3822 else
3823 {
3826 }
3827 neighbour->vl = NULL;
3828 }
3829 GNUNET_free (neighbour);
3830}

References check_link_down(), cores_send_disconnect_info(), VirtualLink::dv, DistanceVectorHop::dv, DistanceVector::dv_head, Neighbour::dv_head, free_distance_vector_hop(), free_dv_route(), free_virtual_link(), Neighbour::get, GNUNET_assert, GNUNET_CONTAINER_multipeermap_destroy(), GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_CONTAINER_multipeermap_remove(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_PEERSTORE_iteration_stop(), GNUNET_PEERSTORE_store_cancel(), GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_cancel(), GNUNET_YES, VirtualLink::n, Neighbour::natted_addresses, neighbours, Neighbour::pid, Neighbour::queue_head, remove_global_addresses(), Neighbour::sc, VirtualLink::target, VirtualLink::visibility_task, DistanceVector::vl, and Neighbour::vl.

Referenced by free_neighbour_cb(), and free_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ core_send_connect_info()

static void core_send_connect_info ( struct TransportClient tc,
const struct GNUNET_PeerIdentity pid 
)
static

Send message to CORE clients that we lost a connection.

Parameters
tcclient to inform (must be CORE client)
pidpeer the connection is for

Definition at line 3840 of file gnunet-service-transport.c.

3842{
3843 struct GNUNET_MQ_Envelope *env;
3844 struct ConnectInfoMessage *cim;
3845
3846 GNUNET_assert (CT_CORE == tc->type);
3848 cim->id = *pid;
3849 GNUNET_MQ_send (tc->mq, env);
3850}

References CT_CORE, env, GNUNET_assert, GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT, GNUNET_MQ_msg, GNUNET_MQ_send(), ConnectInfoMessage::id, pid, and tc.

Referenced by cores_send_connect_info(), and notify_client_connect_info().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cores_send_connect_info()

static void cores_send_connect_info ( const struct GNUNET_PeerIdentity pid)
static

Send message to CORE clients that we gained a connection.

Parameters
pidpeer the queue was for

Definition at line 3859 of file gnunet-service-transport.c.

3860{
3862 "Informing CORE clients about connection to %s\n",
3863 GNUNET_i2s (pid));
3864 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3865 {
3866 if (CT_CORE != tc->type)
3867 continue;
3869 }
3870}

References clients_head, core_send_connect_info(), CT_CORE, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, pid, and tc.

Referenced by activate_core_visible_dv_path(), and handle_validation_response().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ transmit_on_queue()

static void transmit_on_queue ( void *  cls)
static

We believe we are ready to transmit a message on a queue.

We believe we are ready to transmit a struct PendingMessage on a queue, the big question is which one! We need to see if there is one pending that is allowed by flow control and congestion control and (ideally) matches our queue's performance profile.

Gives the message to the communicator for transmission (updating the tracker, and re-scheduling itself if applicable).

Parameters
clsthe struct Queue to process transmissions for

If such a message is found, we give the message to the communicator for transmission (updating the tracker, and re-scheduling ourselves if applicable).

If no such message is found, the queue's idle field must be set to GNUNET_YES.

Parameters
clsthe struct Queue to process transmissions for

Definition at line 11404 of file gnunet-service-transport.c.

11405{
11406 struct Queue *queue = cls;
11407 struct Neighbour *n = queue->neighbour;
11409 struct PendingMessage *pm;
11410
11411 queue->transmit_task = NULL;
11412 if (NULL == n->vl)
11413 {
11415 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
11416 GNUNET_i2s (&n->pid),
11417 queue->address);
11418 queue->idle = GNUNET_YES;
11419 return;
11420 }
11421 memset (&sc, 0, sizeof(sc));
11422 select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
11423 if (NULL == sc.best)
11424 {
11425 /* Also look at DVH that have the n as first hop! */
11426 for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
11427 dvh = dvh->next_neighbour)
11428 {
11430 queue,
11431 dvh->dv->vl,
11432 dvh,
11433 sizeof(struct GNUNET_PeerIdentity)
11434 * (1 + dvh->distance)
11435 + sizeof(struct TransportDVBoxMessage)
11436 + sizeof(struct TransportDVBoxPayloadP));
11437 }
11438 }
11439 if (NULL == sc.best)
11440 {
11441 /* no message pending, nothing to do here! */
11443 "No pending messages, queue `%s' to %s now idle\n",
11444 queue->address,
11445 GNUNET_i2s (&n->pid));
11446 if (GNUNET_YES == sc.to_early)
11447 schedule_transmit_on_queue (sc.to_early_retry_delay,
11448 queue,
11450 queue->idle = GNUNET_YES;
11451 return;
11452 }
11453 /* There is a message pending, we are certainly not idle */
11454 queue->idle = GNUNET_NO;
11455
11456 /* Given selection in `sc`, do transmission */
11457 pm = sc.best;
11459 "Selected message <%" PRIu64 ">\n",
11460 pm->logging_uuid);
11461 if (NULL != sc.dvh)
11462 {
11464 "Is this %u a DV box?\n",
11465 pm->pmt);
11466 GNUNET_assert (PMT_DV_BOX != pm->pmt);
11467 if ((NULL != sc.best->bpm) && (sc.best->bpm->used_dvh != sc.dvh))
11468 {
11470 "Discard old box, because we have a new DV path.\n");
11471 free_pending_message (sc.best->bpm);
11472 sc.best->bpm = NULL;
11473 }
11474
11475 if (NULL == sc.best->bpm)
11476 {
11478 "encapsulate_for_dv 2\n");
11479 encapsulate_for_dv (sc.dvh->dv,
11480 1,
11481 &sc.dvh,
11482 (const struct GNUNET_MessageHeader *) &sc.best[1],
11484 &sc,
11485 RMO_NONE,
11486 GNUNET_NO);
11487 GNUNET_assert (NULL != sc.best->bpm);
11489 "%lu %lu %lu %lu %u\n",
11490 sizeof(struct GNUNET_PeerIdentity),
11491 sizeof(struct TransportDVBoxMessage),
11492 sizeof(struct TransportDVBoxPayloadP),
11493 sizeof(struct TransportFragmentBoxMessage),
11494 ((const struct GNUNET_MessageHeader *) &sc.best[1])->size);
11495 sc.best->bpm->used_dvh = sc.dvh;
11496 }
11497 pm = sc.best->bpm;
11498 }
11499 if (GNUNET_YES == sc.frag)
11500 {
11501 pm = fragment_message (queue, sc.dvh, pm);
11502 if (NULL == pm)
11503 {
11505 "Fragmentation failed queue %s to %s for <%" PRIu64
11506 ">, trying again\n",
11507 queue->address,
11508 GNUNET_i2s (&n->pid),
11509 sc.best->logging_uuid);
11511 queue,
11513 return;
11514 }
11515 }
11516 else if (GNUNET_YES == sc.relb)
11517 {
11519 if (NULL == pm)
11520 {
11521 /* Reliability boxing failed, try next message... */
11522 GNUNET_log (
11524 "Reliability boxing failed queue %s to %s for <%" PRIu64
11525 ">, trying again\n",
11526 queue->address,
11527 GNUNET_i2s (&n->pid),
11528 sc.best->logging_uuid);
11530 queue,
11532 return;
11533 }
11534 }
11535
11536 /* Pass 'pm' for transission to the communicator */
11537 GNUNET_log (
11539 "Passing message <%" PRIu64
11540 "> to queue %s for peer %s (considered %u others)\n",
11541 pm->logging_uuid,
11542 queue->address,
11543 GNUNET_i2s (&n->pid),
11544 sc.consideration_counter);
11545
11546 /* Flow control: increment amount of traffic sent; if we are routing
11547 via DV (and thus the ultimate target of the pending message is for
11548 a different virtual link than the one of the queue), then we need
11549 to use up not only the window of the direct link but also the
11550 flow control window for the DV link! */
11551 pm->vl->outbound_fc_window_size_used += pm->bytes_msg;
11552
11553 if (pm->vl != queue->neighbour->vl)
11554 {
11555 /* If the virtual link of the queue differs, this better be distance
11556 vector routing! */
11557 GNUNET_assert (NULL != sc.dvh);
11558 /* If we do distance vector routing, we better not do this for a
11559 message that was itself DV-routed */
11560 GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
11561 /* We use the size of the unboxed message here, to avoid counting
11562 the DV-Box header which is eaten up on the way by intermediaries */
11563 queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
11564 }
11565 else
11566 {
11567 GNUNET_assert (NULL == sc.dvh);
11568 }
11569
11570 queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
11571
11572 /* Check if this transmission somehow conclusively finished handing 'pm'
11573 even without any explicit ACKs */
11574 if ((PMT_CORE == pm->pmt) ||
11575 (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
11576 {
11578 }
11579 else
11580 {
11581 struct GNUNET_TIME_Relative wait_duration;
11582 unsigned int wait_multiplier;
11583
11584 if (PMT_FRAGMENT_BOX == pm->pmt)
11585 {
11586 struct PendingMessage *root;
11587
11588 root = pm->frag_parent;
11589 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11590 root = root->frag_parent;
11591
11592 wait_multiplier = (unsigned int) ceil ((double) root->bytes_msg
11593 / ((double) root->frag_off
11594 / (double) root->frag_count))
11595 * 4;
11596 }
11597 else
11598 {
11599 // No fragments, we use 4 RTT before retransmitting.
11600 wait_multiplier = 4;
11601 }
11602
11603 // Depending on how much pending message the VirtualLink is queueing, we wait longer.
11604 // wait_multiplier = wait_multiplier * pm->vl->pending_msg_num;
11605
11607 "Wait multiplier %u\n",
11608 wait_multiplier);
11609
11610 /* Message not finished, waiting for acknowledgement.
11611 Update time by which we might retransmit 's' based on queue
11612 characteristics (i.e. RTT); it takes one RTT for the message to
11613 arrive and the ACK to come back in the best case; but the other
11614 side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
11615 retransmitting.
11616
11617 OPTIMIZE: Note that in the future this heuristic should likely
11618 be improved further (measure RTT stability, consider message
11619 urgency and size when delaying ACKs, etc.) */
11620
11621 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
11622 queue->pd.aged_rtt.rel_value_us)
11623 wait_duration = queue->pd.aged_rtt;
11624 else
11625 {
11626 wait_duration = DEFAULT_ACK_WAIT_DURATION;
11627 wait_multiplier = 4;
11628 }
11629 {
11632 wait_duration, wait_multiplier));
11634 wait_duration, wait_multiplier);
11636 "Waiting %s for ACK until %s\n",
11641 GNUNET_TIME_relative_multiply (wait_duration,
11642 wait_multiplier))
11643 );
11644 }
11645 }
11646 /* finally, re-schedule queue transmission task itself */
11648 queue,
11650}

References PendingMessage::bytes_msg, completed_pending_message(), DEFAULT_ACK_WAIT_DURATION, Neighbour::dv_head, encapsulate_for_dv(), extract_box_cb(), PendingMessage::frag_count, PendingMessage::frag_off, PendingMessage::frag_parent, fragment_message(), free_pending_message(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_STRINGS_absolute_time_to_string(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_relative_multiply(), GNUNET_TIME_relative_to_absolute(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TIME_UNIT_ZERO, GNUNET_TRANSPORT_CC_RELIABLE, GNUNET_YES, Neighbour::pid, pm, PendingMessage::pmt, PMT_CORE, PMT_DV_BOX, PMT_FRAGMENT_BOX, queue(), queue_send_msg(), reliability_box_message(), RMO_NONE, sc, schedule_transmit_on_queue(), select_best_pending_from_link(), update_pm_next_attempt(), and Neighbour::vl.

Referenced by schedule_transmit_on_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_for_queue_with_higher_prio()

static unsigned int check_for_queue_with_higher_prio ( struct Queue queue,
struct Queue queue_head 
)
static

Check if the communicator has another queue with higher prio ready for sending.

Definition at line 3888 of file gnunet-service-transport.c.

3889{
3890 for (struct Queue *s = queue_head; NULL != s;
3891 s = s->next_client)
3892 {
3893 if (s->tc->details.communicator.address_prefix !=
3894 queue->tc->details.communicator.address_prefix)
3895 {
3897 "queue address %s qid %u compare with queue: address %s qid %u\n",
3898 queue->address,
3899 queue->qid,
3900 s->address,
3901 s->qid);
3902 if ((s->priority > queue->priority) && (0 < s->q_capacity) &&
3903 (QUEUE_LENGTH_LIMIT > s->queue_length) )
3904 return GNUNET_YES;
3906 "Lower prio\n");
3907 }
3908 }
3909 return GNUNET_NO;
3910}

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_YES, Queue::next_client, queue(), queue_head, and QUEUE_LENGTH_LIMIT.

Referenced by schedule_transmit_on_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ schedule_transmit_on_queue()

static void schedule_transmit_on_queue ( struct GNUNET_TIME_Relative  delay,
struct Queue queue,
enum GNUNET_SCHEDULER_Priority  p 
)
static

Called whenever something changed that might effect when we try to do the next transmission on queue using transmit_on_queue().

Parameters
queuethe queue to do scheduling for
ptask priority to use, if queue is scheduled

Definition at line 3921 of file gnunet-service-transport.c.

3924{
3926
3927 if (queue->validated_until.abs_value_us < now.abs_value_us)
3928 return;
3930 queue->tc->details.communicator.
3931 queue_head))
3932 return;
3933
3934 if (queue->tc->details.communicator.total_queue_length >=
3936 {
3938 "Transmission on queue %s (QID %u) throttled due to communicator queue limit\n",
3939 queue->address,
3940 queue->qid);
3942 GST_stats,
3943 "# Transmission throttled due to communicator queue limit",
3944 1,
3945 GNUNET_NO);
3946 queue->idle = GNUNET_NO;
3947 return;
3948 }
3949 if (queue->queue_length >= QUEUE_LENGTH_LIMIT)
3950 {
3952 "Transmission on queue %s (QID %u) throttled due to communicator queue length limit\n",
3953 queue->address,
3954 queue->qid);
3956 "# Transmission throttled due to queue queue limit",
3957 1,
3958 GNUNET_NO);
3959 queue->idle = GNUNET_NO;
3960 return;
3961 }
3962 if (0 == queue->q_capacity)
3963 {
3965 "Transmission on queue %s (QID %u) throttled due to communicator message has capacity %"
3966 PRIu64 ".\n",
3967 queue->address,
3968 queue->qid,
3969 queue->q_capacity);
3971 "# Transmission throttled due to message queue capacity",
3972 1,
3973 GNUNET_NO);
3974 queue->idle = GNUNET_NO;
3975 return;
3976 }
3977 /* queue might indeed be ready, schedule it */
3978 if (NULL != queue->transmit_task)
3979 GNUNET_SCHEDULER_cancel (queue->transmit_task);
3980 queue->transmit_task =
3982 queue);
3984 "Considering transmission on queue `%s' QID %llu to %s\n",
3985 queue->address,
3986 (unsigned long long) queue->qid,
3987 GNUNET_i2s (&queue->neighbour->pid));
3988}

References GNUNET_TIME_Absolute::abs_value_us, check_for_queue_with_higher_prio(), COMMUNICATOR_TOTAL_QUEUE_LIMIT, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_SCHEDULER_add_delayed_with_priority(), GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_update(), GNUNET_TIME_absolute_get(), GST_stats, p, queue(), queue_head, QUEUE_LENGTH_LIMIT, and transmit_on_queue().

Referenced by check_vl_transmission(), free_queue(), free_queue_entry(), handle_update_queue_message(), and transmit_on_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_queue()

static void free_queue ( struct Queue queue)
static

Free queue.

Parameters
queuethe queue to free

Definition at line 4049 of file gnunet-service-transport.c.

4050{
4051 struct Neighbour *neighbour = queue->neighbour;
4052 struct TransportClient *tc = queue->tc;
4053 struct MonitorEvent me = { .cs = GNUNET_TRANSPORT_CS_DOWN,
4055 struct QueueEntry *qe;
4056 int maxxed;
4057 struct PendingAcknowledgement *pa;
4058 struct VirtualLink *vl;
4059
4061 "Cleaning up queue %u\n", queue->qid);
4062 if (NULL != queue->mo)
4063 {
4065 queue->mo = NULL;
4066 }
4067 if (NULL != queue->transmit_task)
4068 {
4069 GNUNET_SCHEDULER_cancel (queue->transmit_task);
4070 queue->transmit_task = NULL;
4071 }
4072 while (NULL != (pa = queue->pa_head))
4073 {
4074 GNUNET_CONTAINER_MDLL_remove (queue, queue->pa_head, queue->pa_tail, pa);
4075 pa->queue = NULL;
4076 }
4077
4079 neighbour->queue_head,
4080 neighbour->queue_tail,
4081 queue);
4083 tc->details.communicator.queue_head,
4084 tc->details.communicator.queue_tail,
4085 queue);
4087 tc->details.communicator.total_queue_length);
4089 "Cleaning up queue with length %u\n",
4090 queue->queue_length);
4091 while (NULL != (qe = queue->queue_head))
4092 {
4093 GNUNET_CONTAINER_DLL_remove (queue->queue_head, queue->queue_tail, qe);
4094 queue->queue_length--;
4095 tc->details.communicator.total_queue_length--;
4096 if (NULL != qe->pm)
4097 {
4098 GNUNET_assert (qe == qe->pm->qe);
4099 qe->pm->qe = NULL;
4100 }
4101 GNUNET_free (qe);
4102 }
4103 GNUNET_assert (0 == queue->queue_length);
4104 if ((maxxed) && (COMMUNICATOR_TOTAL_QUEUE_LIMIT >
4105 tc->details.communicator.total_queue_length))
4106 {
4107 /* Communicator dropped below threshold, resume all _other_ queues */
4109 GST_stats,
4110 "# Transmission throttled due to communicator queue limit",
4111 -1,
4112 GNUNET_NO);
4113 for (struct Queue *s = tc->details.communicator.queue_head; NULL != s;
4114 s = s->next_client)
4116 s,
4118 }
4119 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
4121
4122 vl = lookup_virtual_link (&neighbour->pid);
4123 if ((NULL != vl) && (neighbour == vl->n))
4124 {
4126 check_link_down (vl);
4127 }
4128 if (NULL == neighbour->queue_head)
4129 {
4130 free_neighbour (neighbour, GNUNET_NO);
4131 }
4132}

References check_link_down(), COMMUNICATOR_TOTAL_QUEUE_LIMIT, free_neighbour(), GNUNET_assert, GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_MDLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_NO, GNUNET_PEERSTORE_monitor_stop(), GNUNET_SCHEDULER_cancel(), GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_STATISTICS_update(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TIME_UNIT_ZERO, GNUNET_TRANSPORT_CS_DOWN, GST_stats, lookup_virtual_link(), me, VirtualLink::n, notify_monitors(), Neighbour::pid, qe, queue(), PendingAcknowledgement::queue, Neighbour::queue_head, Neighbour::queue_tail, schedule_transmit_on_queue(), tc, and VirtualLink::visibility_task.

Referenced by client_disconnect_cb(), and handle_del_queue_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_address_list_entry()

static void free_address_list_entry ( struct AddressListEntry ale)
static

Free ale.

Parameters
aleaddress list entry to free

Definition at line 4141 of file gnunet-service-transport.c.

4142{
4143 struct TransportClient *tc = ale->tc;
4144
4145 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
4146 tc->details.communicator.addr_tail,
4147 ale);
4148 if (NULL != ale->sc)
4149 {
4151 "store cancel\n");
4153 ale->sc = NULL;
4154 }
4155 if (NULL != ale->st)
4156 {
4158 ale->st = NULL;
4159 }
4160 if (NULL != ale->signed_address)
4162 GNUNET_free (ale);
4163}

References GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_PEERSTORE_store_cancel(), GNUNET_SCHEDULER_cancel(), AddressListEntry::sc, AddressListEntry::signed_address, AddressListEntry::st, tc, and AddressListEntry::tc.

Referenced by client_disconnect_cb(), and handle_del_address().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ stop_peer_request()

static int stop_peer_request ( void *  cls,
const struct GNUNET_PeerIdentity pid,
void *  value 
)
static

Stop the peer request in value.

Parameters
clsa struct TransportClient that no longer makes the request
pidthe peer's identity
valuea struct PeerRequest
Returns
GNUNET_YES (always)

Definition at line 4175 of file gnunet-service-transport.c.

4178{
4179 struct TransportClient *tc = cls;
4180 struct PeerRequest *pr = value;
4181
4182 if (NULL != pr->nc)
4184 pr->nc = NULL;
4186 GNUNET_YES ==
4187 GNUNET_CONTAINER_multipeermap_remove (tc->details.application.requests,
4188 pid,
4189 pr));
4190 GNUNET_free (pr);
4191
4192 return GNUNET_OK;
4193}

References GNUNET_assert, GNUNET_CONTAINER_multipeermap_remove(), GNUNET_free, GNUNET_OK, GNUNET_PEERSTORE_monitor_stop(), GNUNET_YES, pid, PeerRequest::pr, tc, and value.

Referenced by client_disconnect_cb(), and handle_suggest_cancel().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_shutdown()

static void do_shutdown ( void *  cls)
static

Function called when the service shuts down.

Unloads our plugins and cancels pending validations.

Parameters
clsclosure, unused

Definition at line 13366 of file gnunet-service-transport.c.

13367{
13368 struct LearnLaunchEntry *lle;
13369 struct PilsRequest *pr;
13370 (void) cls;
13371
13373 "shutdown logic\n");
13376 &free_neighbour_cb, NULL);
13377 if (NULL != validation_task)
13378 {
13380 validation_task = NULL;
13381 }
13382 if (NULL != dvlearn_task)
13383 {
13385 dvlearn_task = NULL;
13386 }
13388 dvlearn_map = NULL;
13391 dv_routes = NULL;
13392 if (NULL != GST_stats)
13393 {
13395 GST_stats = NULL;
13396 }
13397 if (NULL != GST_my_hello)
13398 {
13400 GST_my_hello = NULL;
13401 }
13402 if (NULL != GST_my_identity)
13403 {
13405 GST_my_identity = NULL;
13406 }
13409 NULL);
13411 ack_cummulators = NULL;
13414 NULL);
13416 pending_acks = NULL;
13419 neighbours = NULL;
13422 links = NULL;
13425 NULL);
13427 backtalkers = NULL;
13430 NULL);
13432 validation_map = NULL;
13434 validation_heap = NULL;
13436 revalidation_map = NULL;
13437 while (NULL != ir_head)
13439 GNUNET_assert (0 == ir_total);
13440 while (NULL != (lle = lle_head))
13441 {
13443 GNUNET_free (lle);
13444 }
13445 while (NULL != (pr = pils_requests_head))
13446 {
13449 pr);
13450 if (NULL != pr->op)
13451 GNUNET_PILS_cancel (pr->op);
13452 GNUNET_free (pr);
13453 }
13454 if (NULL != pils_feed_task)
13455 {
13457 pils_feed_task = NULL;
13458 }
13459 if (NULL != pils)
13460 {
13462 pils = NULL;
13463 }
13464 if (NULL != peerstore)
13465 {
13467 "Disconnecting from PEERSTORE service\n");
13469 peerstore = NULL;
13470 }
13472}

References ack_cummulators, backtalkers, dv_routes, dvlearn_map, dvlearn_task, free_ack_cummulator_cb(), free_backtalker_cb(), free_dv_routes_cb(), free_incoming_request(), free_neighbour_cb(), free_pending_ack_cb(), free_validation_state_cb(), GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_heap_destroy(), GNUNET_CONTAINER_multihashmap_destroy(), GNUNET_CONTAINER_multipeermap_destroy(), GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_CONTAINER_multipeermap_size(), GNUNET_CONTAINER_multishortmap_destroy(), GNUNET_CONTAINER_multiuuidmap_destroy(), GNUNET_CONTAINER_multiuuidmap_iterate(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_HELLO_builder_free(), GNUNET_log, GNUNET_NAT_unregister(), GNUNET_NO, GNUNET_PEERSTORE_disconnect(), GNUNET_PILS_cancel(), GNUNET_PILS_disconnect(), GNUNET_SCHEDULER_cancel(), GNUNET_SCHEDULER_shutdown(), GNUNET_STATISTICS_destroy(), GST_my_hello, GST_my_identity, GST_stats, ir_head, ir_total, links, lle_head, lle_tail, neighbours, nh, PilsRequest::op, peerstore, pending_acks, pils, pils_feed_task, pils_requests_head, pils_requests_tail, revalidation_map, validation_heap, validation_map, and validation_task.

Here is the call graph for this function:

◆ client_disconnect_cb()

static void client_disconnect_cb ( void *  cls,
struct GNUNET_SERVICE_Client client,
void *  app_ctx 
)
static

Called whenever a client is disconnected.

Frees our resources associated with that client.

Parameters
clsclosure, NULL
clientidentification of the client
app_ctxour struct TransportClient

Definition at line 4208 of file gnunet-service-transport.c.

4211{
4212 struct TransportClient *tc = app_ctx;
4213
4214 (void) cls;
4215 (void) client;
4217 switch (tc->type)
4218 {
4219 case CT_NONE:
4221 "Unknown Client %p disconnected, cleaning up.\n",
4222 tc);
4223 break;
4224
4225 case CT_CORE: {
4226 struct PendingMessage *pm;
4228 "CORE Client %p disconnected, cleaning up.\n",
4229 tc);
4230
4231
4232 while (NULL != (pm = tc->details.core.pending_msg_head))
4233 {
4235 tc->details.core.pending_msg_head,
4236 tc->details.core.pending_msg_tail,
4237 pm);
4238 pm->client = NULL;
4239 }
4240 }
4241 break;
4242
4243 case CT_MONITOR:
4245 "MONITOR Client %p disconnected, cleaning up.\n",
4246 tc);
4247
4248 break;
4249
4250 case CT_COMMUNICATOR: {
4251 struct Queue *q;
4252 struct AddressListEntry *ale;
4253
4255 "COMMUNICATOR Client %p disconnected, cleaning up.\n",
4256 tc);
4257
4258 if (NULL != tc->details.communicator.free_queue_entry_task)
4260 tc->details.communicator.free_queue_entry_task);
4261 while (NULL != (q = tc->details.communicator.queue_head))
4262 free_queue (q);
4263 while (NULL != (ale = tc->details.communicator.addr_head))
4265 GNUNET_free (tc->details.communicator.address_prefix);
4266 }
4267 break;
4268
4269 case CT_APPLICATION:
4271 "APPLICATION Client %p disconnected, cleaning up.\n",
4272 tc);
4273
4274 GNUNET_CONTAINER_multipeermap_iterate (tc->details.application.requests,
4276 tc);
4277 GNUNET_CONTAINER_multipeermap_destroy (tc->details.application.requests);
4278 break;
4279 }
4280 GNUNET_free (tc);
4281 if ((GNUNET_YES == in_shutdown) && (NULL == clients_head))
4282 {
4284 "Our last client disconnected\n");
4285 do_shutdown (cls);
4286 }
4287}

References PendingMessage::client, TransportClient::client, clients_head, clients_tail, CT_APPLICATION, CT_COMMUNICATOR, CT_CORE, CT_MONITOR, CT_NONE, do_shutdown, free_address_list_entry(), free_queue(), GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_MDLL_remove, GNUNET_CONTAINER_multipeermap_destroy(), GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_SCHEDULER_cancel(), GNUNET_YES, in_shutdown, pm, q, stop_peer_request(), and tc.

Here is the call graph for this function:

◆ notify_client_connect_info()

static int notify_client_connect_info ( void *  cls,
const struct GNUNET_PeerIdentity pid,
void *  value 
)
static

Iterator telling new CORE client about all existing connections to peers.

Parameters
clsthe new struct TransportClient
pida connected peer
valuethe struct Neighbour with more information
Returns
GNUNET_OK (continue to iterate)

Definition at line 4300 of file gnunet-service-transport.c.

4303{
4304 struct TransportClient *tc = cls;
4305 struct VirtualLink *vl = value;
4306
4307 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4308 return GNUNET_OK;
4309
4311 "Telling new CORE client about existing connection to %s\n",
4312 GNUNET_i2s (pid));
4314 return GNUNET_OK;
4315}

References VirtualLink::confirmed, core_send_connect_info(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_OK, pid, tc, and value.

Referenced by handle_client_start().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ finish_cmc_handling_with_continue()

static void finish_cmc_handling_with_continue ( struct CommunicatorMessageContext cmc,
unsigned int  free_cmc 
)
static

Send ACK to communicator (if requested) and free cmc.

Parameters
cmccontext for which we are done handling the message

Definition at line 4571 of file gnunet-service-transport.c.

4574{
4575 if (0 != ntohl (cmc->im.fc_on))
4576 {
4577 /* send ACK when done to communicator for flow control! */
4578 struct GNUNET_MQ_Envelope *env;
4580
4582 "Acknowledge message with flow control id %" PRIu64 "\n",
4583 cmc->im.fc_id);
4585 ack->reserved = htonl (0);
4586 ack->fc_id = cmc->im.fc_id;
4587 ack->sender = cmc->im.neighbour_sender;
4588 GNUNET_MQ_send (cmc->tc->mq, env);
4589 }
4590
4592
4593 if (GNUNET_YES == free_cmc)
4594 {
4595 GNUNET_free (cmc);
4596 }
4597}

References TransportClient::client, env, GNUNET_TRANSPORT_IncomingMessage::fc_id, GNUNET_TRANSPORT_IncomingMessageAck::fc_id, GNUNET_TRANSPORT_IncomingMessage::fc_on, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_SERVICE_client_continue(), GNUNET_YES, CommunicatorMessageContext::im, TransportClient::mq, GNUNET_TRANSPORT_IncomingMessage::neighbour_sender, GNUNET_TRANSPORT_IncomingMessageAck::reserved, GNUNET_TRANSPORT_IncomingMessageAck::sender, and CommunicatorMessageContext::tc.

Referenced by finish_cmc_handling(), finish_handling_raw_message(), handle_client_recv_ok(), handle_raw_message(), and resume_communicators().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ resume_communicators()

static enum GNUNET_GenericReturnValue resume_communicators ( void *  cls,
const struct GNUNET_PeerIdentity pid,
void *  value 
)
static

Definition at line 4329 of file gnunet-service-transport.c.

4332{
4333 struct VirtualLink *vl = value;
4334 struct CommunicatorMessageContext *cmc;
4335
4336 /* resume communicators */
4337 while (NULL != (cmc = vl->cmc_tail))
4338 {
4340 if (GNUNET_NO == cmc->continue_send)
4342 }
4343 return GNUNET_OK;
4344}

References VirtualLink::cmc_head, VirtualLink::cmc_tail, CommunicatorMessageContext::continue_send, finish_cmc_handling_with_continue(), GNUNET_CONTAINER_DLL_remove, GNUNET_NO, GNUNET_OK, GNUNET_YES, and value.

Referenced by handle_client_start().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_client_start()

static void handle_client_start ( void *  cls,
const struct StartMessage start 
)
static

Initialize a "CORE" client.

We got a start message from this client, so add it to the list of clients for broadcasting of inbound messages.

Parameters
clsthe client
startthe start message that was sent

Definition at line 4356 of file gnunet-service-transport.c.

4357{
4358 struct TransportClient *tc = cls;
4359 // uint32_t options;
4360 //
4361 // FIXME ignore the check of the peer ids for now.
4362 // (also deprecate the old way of obtaining our own peer ID)
4363 // options = ntohl (start->options);
4364 // if ((0 != (1 & options)) &&
4365 // (0 != GNUNET_memcmp (&start->self, &GST_my_identity)))
4366 // {
4367 // /* client thinks this is a different peer, reject */
4368 // GNUNET_break (0);
4369 // GNUNET_SERVICE_client_drop (tc->client);
4370 // return;
4371 // }
4372 if (CT_NONE != tc->type)
4373 {
4374 GNUNET_break (0);
4376 return;
4377 }
4378 tc->type = CT_CORE;
4380 "New CORE client with PID %s registered\n",
4381 GNUNET_i2s (&start->self));
4384 tc);
4387 NULL);
4389}

References CT_CORE, CT_NONE, GNUNET_break, GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), links, notify_client_connect_info(), resume_communicators(), start, and tc.

Here is the call graph for this function:

◆ check_client_send()

static int check_client_send ( void *  cls,
const struct OutboundMessage obm 
)
static

Client asked for transmission to a peer.

Process the request.

Parameters
clsthe client
obmthe send message that was sent

Definition at line 4399 of file gnunet-service-transport.c.

4400{
4401 struct TransportClient *tc = cls;
4402 uint16_t size;
4403 const struct GNUNET_MessageHeader *obmm;
4404
4405 if (CT_CORE != tc->type)
4406 {
4407 GNUNET_break (0);
4408 return GNUNET_SYSERR;
4409 }
4410 size = ntohs (obm->header.size) - sizeof(struct OutboundMessage);
4411 if (size < sizeof(struct GNUNET_MessageHeader))
4412 {
4413 GNUNET_break (0);
4414 return GNUNET_SYSERR;
4415 }
4416 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
4417 if (size != ntohs (obmm->size))
4418 {
4419 GNUNET_break (0);
4420 return GNUNET_SYSERR;
4421 }
4422 return GNUNET_OK;
4423}

References CT_CORE, GNUNET_break, GNUNET_OK, GNUNET_SYSERR, OutboundMessage::header, GNUNET_MessageHeader::size, size, and tc.

◆ client_send_response()

static void client_send_response ( struct PendingMessage pm)
static

Send a response to the pm that we have processed a "send" request.

Sends a confirmation to the "core" client responsible for the original request and free's pm.

Parameters
pmhandle to the original pending message

Definition at line 4434 of file gnunet-service-transport.c.

4435{
4436 struct TransportClient *tc = pm->client;
4437 struct VirtualLink *vl = pm->vl;
4438
4440 "client send response\n");
4441 if (NULL != tc)
4442 {
4443 struct GNUNET_MQ_Envelope *env;
4444 struct SendOkMessage *so_msg;
4445
4447 so_msg->peer = vl->target;
4449 "Confirming transmission of <%" PRIu64 "> to %s\n",
4450 pm->logging_uuid,
4451 GNUNET_i2s (&vl->target));
4452 GNUNET_MQ_send (tc->mq, env);
4453 }
4455}

References env, free_pending_message(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK, GNUNET_MQ_msg, GNUNET_MQ_send(), SendOkMessage::peer, pm, VirtualLink::target, and tc.

Referenced by completed_pending_message(), and reliability_box_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pick_random_dv_hops()

static unsigned int pick_random_dv_hops ( const struct DistanceVector dv,
enum RouteMessageOptions  options,
struct DistanceVectorHop **  hops_array,
unsigned int  hops_array_length 
)
static

Pick hops_array_length random DV paths satisfying options.

Parameters
dvdata structure to pick paths from
optionsconstraints to satisfy
[out]hops_arrayset to the result
hops_array_lengthlength of the hops_array
Returns
number of entries set in hops_array

Definition at line 4468 of file gnunet-service-transport.c.

4472{
4473 uint64_t choices[hops_array_length];
4474 uint64_t num_dv;
4475 unsigned int dv_count;
4476
4477 /* Pick random vectors, but weighted by distance, giving more weight
4478 to shorter vectors */
4479 num_dv = 0;
4480 dv_count = 0;
4481 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4482 pos = pos->next_dv)
4483 {
4484 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
4485 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
4486 .rel_value_us == 0))
4487 continue; /* pos unconfirmed and confirmed required */
4488 num_dv += MAX_DV_HOPS_ALLOWED - pos->distance;
4489 dv_count++;
4490 }
4491 if (0 == dv_count)
4492 return 0;
4493 if (dv_count <= hops_array_length)
4494 {
4495 dv_count = 0;
4496 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4497 pos = pos->next_dv)
4498 hops_array[dv_count++] = pos;
4499 return dv_count;
4500 }
4501 for (unsigned int i = 0; i < hops_array_length; i++)
4502 {
4503 int ok = GNUNET_NO;
4504 while (GNUNET_NO == ok)
4505 {
4506 choices[i] =
4508 ok = GNUNET_YES;
4509 for (unsigned int j = 0; j < i; j++)
4510 if (choices[i] == choices[j])
4511 {
4512 ok = GNUNET_NO;
4513 break;
4514 }
4515 }
4516 }
4517 dv_count = 0;
4518 num_dv = 0;
4519 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4520 pos = pos->next_dv)
4521 {
4522 uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance;
4523
4524 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
4525 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
4526 .rel_value_us == 0))
4527 continue; /* pos unconfirmed and confirmed required */
4528 for (unsigned int i = 0; i < hops_array_length; i++)
4529 if ((num_dv <= choices[i]) && (num_dv + delta > choices[i]))
4530 hops_array[dv_count++] = pos;
4531 num_dv += delta;
4532 }
4533 return dv_count;
4534}

References delta, DistanceVector::dv_head, GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u64(), GNUNET_NO, GNUNET_TIME_absolute_get_remaining(), GNUNET_YES, MAX_DV_HOPS_ALLOWED, options, GNUNET_TIME_Relative::rel_value_us, and RMO_UNCONFIRMED_ALLOWED.

Referenced by route_control_message_without_fc().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_communicator_available()

static int check_communicator_available ( void *  cls,
const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage cam 
)
static

Communicator started.

Test message is well-formed.

Parameters
clsthe client
camthe send message that was sent

Definition at line 4544 of file gnunet-service-transport.c.

4547{
4548 struct TransportClient *tc = cls;
4549 uint16_t size;
4550
4551 if (CT_NONE != tc->type)
4552 {
4553 GNUNET_break (0);
4554 return GNUNET_SYSERR;
4555 }
4556 tc->type = CT_COMMUNICATOR;
4557 size = ntohs (cam->header.size) - sizeof(*cam);
4558 if (0 == size)
4559 return GNUNET_OK; /* receive-only communicator */
4561 return GNUNET_OK;
4562}

References CT_COMMUNICATOR, CT_NONE, GNUNET_break, GNUNET_MQ_check_zero_termination, GNUNET_OK, GNUNET_SYSERR, GNUNET_TRANSPORT_CommunicatorAvailableMessage::header, GNUNET_MessageHeader::size, size, and tc.

◆ finish_cmc_handling()

static void finish_cmc_handling ( struct CommunicatorMessageContext cmc)
static

Definition at line 4601 of file gnunet-service-transport.c.

References finish_cmc_handling_with_continue(), and GNUNET_YES.

Referenced by backtalker_monotime_cb(), decaps_dv_box_cb(), free_backtalker(), handle_backchannel_encapsulation(), handle_dv_box(), handle_dv_learn(), handle_flow_control(), handle_fragment_box(), handle_raw_message(), handle_reliability_ack(), handle_validation_challenge(), handle_validation_response(), and sign_t_validation_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_client_recv_ok()

static void handle_client_recv_ok ( void *  cls,
const struct RecvOkMessage rom 
)
static

Client confirms that it is done handling message(s) to a particular peer.

We may now provide more messages to CORE for this peer.

Notifies the respective queues that more messages can now be received.

Parameters
clsthe client
romthe message that was sent

Definition at line 4617 of file gnunet-service-transport.c.

4618{
4619 struct TransportClient *tc = cls;
4620 struct VirtualLink *vl;
4621 uint32_t delta;
4622 struct CommunicatorMessageContext *cmc;
4623
4624 if (CT_CORE != tc->type)
4625 {
4626 GNUNET_break (0);
4628 return;
4629 }
4630 vl = lookup_virtual_link (&rom->peer);
4631 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4632 {
4634 "# RECV_OK dropped: virtual link unknown",
4635 1,
4636 GNUNET_NO);
4638 return;
4639 }
4640 delta = ntohl (rom->increase_window_delta);
4641 vl->core_recv_window += delta;
4643 "CORE ack receiving message, increased CORE recv window to %d\n",
4644 vl->core_recv_window);
4646 if (vl->core_recv_window <= 0)
4647 return;
4648 /* resume communicators */
4649 while (NULL != (cmc = vl->cmc_tail))
4650 {
4652 if (GNUNET_NO == cmc->continue_send)
4654 }
4655}

References VirtualLink::cmc_head, VirtualLink::cmc_tail, VirtualLink::confirmed, CommunicatorMessageContext::continue_send, VirtualLink::core_recv_window, CT_CORE, delta, finish_cmc_handling_with_continue(), GNUNET_break, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_STATISTICS_update(), GNUNET_YES, GST_stats, RecvOkMessage::increase_window_delta, lookup_virtual_link(), RecvOkMessage::peer, and tc.

Here is the call graph for this function:

◆ handle_communicator_available()

static void handle_communicator_available ( void *  cls,
const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage cam 
)
static

Communicator started.

Process the request.

Parameters
clsthe client
camthe send message that was sent

Definition at line 4665 of file gnunet-service-transport.c.

4668{
4669 struct TransportClient *tc = cls;
4670 uint16_t size;
4671
4672 size = ntohs (cam->header.size) - sizeof(*cam);
4673 if (0 == size)
4674 {
4676 "Receive-only communicator connected\n");
4677 return; /* receive-only communicator */
4678 }
4679 tc->details.communicator.address_prefix =
4680 GNUNET_strdup ((const char *) &cam[1]);
4681 tc->details.communicator.cc = ntohl (cam->cc);
4682 tc->details.communicator.can_burst = ntohl (cam->can_burst);
4684 "Communicator for peer %s with prefix '%s' connected %s\n",
4686 tc->details.communicator.address_prefix,
4687 tc->details.communicator.can_burst ? "can burst" :
4688 "can not burst");
4690}

References GNUNET_TRANSPORT_CommunicatorAvailableMessage::can_burst, GNUNET_TRANSPORT_CommunicatorAvailableMessage::cc, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_SERVICE_client_continue(), GNUNET_strdup, GST_my_identity, GNUNET_TRANSPORT_CommunicatorAvailableMessage::header, GNUNET_MessageHeader::size, size, and tc.

Here is the call graph for this function:

◆ check_communicator_backchannel()

static int check_communicator_backchannel ( void *  cls,
const struct GNUNET_TRANSPORT_CommunicatorBackchannel cb 
)
static

Communicator requests backchannel transmission.

Check the request.

Parameters
clsthe client
cbthe send message that was sent
Returns
GNUNET_OK if message is well-formed

Definition at line 4701 of file gnunet-service-transport.c.

4704{
4705 const struct GNUNET_MessageHeader *inbox;
4706 const char *is;
4707 uint16_t msize;
4708 uint16_t isize;
4709
4710 (void) cls;
4711 msize = ntohs (cb->header.size) - sizeof(*cb);
4712 inbox = (const struct GNUNET_MessageHeader *) &cb[1];
4713 isize = ntohs (inbox->size);
4714 if (isize >= msize)
4715 {
4716 GNUNET_break (0);
4717 return GNUNET_SYSERR;
4718 }
4719 is = (const char *) inbox;
4720 is += isize;
4721 msize -= isize;
4722 GNUNET_assert (0 < msize);
4723 if ('\0' != is[msize - 1])
4724 {
4725 GNUNET_break (0);
4726 return GNUNET_SYSERR;
4727 }
4728 return GNUNET_OK;
4729}

References GNUNET_assert, GNUNET_break, GNUNET_OK, GNUNET_SYSERR, GNUNET_TRANSPORT_CommunicatorBackchannel::header, is, and GNUNET_MessageHeader::size.

◆ sign_dv_cb()

static void sign_dv_cb ( void *  cls,
const struct GNUNET_PeerIdentity pid,
const struct GNUNET_CRYPTO_EddsaSignature sig 
)
static

Definition at line 4740 of file gnunet-service-transport.c.

4743{
4744 struct SignDvCls *sign_dv_cls = cls;
4745 struct DistanceVector *dv = sign_dv_cls->dv;
4746 struct PilsRequest *pr = sign_dv_cls->req;
4747
4748 pr->op = NULL;
4751 pr);
4752 GNUNET_free (pr);
4753
4754 dv->sender_sig = *sig;
4755}

References SignDvCls::dv, GNUNET_CONTAINER_DLL_remove, GNUNET_free, PilsRequest::op, pils_requests_head, pils_requests_tail, SignDvCls::req, and DistanceVector::sender_sig.

Referenced by sign_ephemeral().

Here is the caller graph for this function:

◆ sign_ephemeral()

static void sign_ephemeral ( struct DistanceVector dv)
static

Sign ephemeral keys in our dv are current.

Parameters
[in,out]dvvirtual link to update ephemeral for

Definition at line 4764 of file gnunet-service-transport.c.

4765{
4766 struct EphemeralConfirmationPS ec;
4767 struct SignDvCls *sign_dv_cls;
4768
4772 ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL);
4773 ec.target = dv->target;
4774 ec.ephemeral_key = dv->ephemeral_key;
4775 ec.sender_monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
4776 ec.purpose.size = htonl (sizeof(ec));
4777 sign_dv_cls = GNUNET_new (struct SignDvCls);
4778 sign_dv_cls->req = GNUNET_new (struct PilsRequest);
4779 sign_dv_cls->dv = dv;
4782 sign_dv_cls->req);
4784 &ec.purpose,
4785 sign_dv_cb,
4786 sign_dv_cls);
4787}

References SignDvCls::dv, EphemeralConfirmationPS::ephemeral_key, DistanceVector::ephemeral_key, EPHEMERAL_VALIDITY, DistanceVector::ephemeral_validity, GNUNET_CONTAINER_DLL_insert, GNUNET_new, GNUNET_PILS_sign_by_peer_identity(), GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL, GNUNET_TIME_absolute_add(), GNUNET_TIME_absolute_get_monotonic(), GNUNET_TIME_absolute_hton(), GST_cfg, DistanceVector::monotime, PilsRequest::op, pils, pils_requests_head, pils_requests_tail, GNUNET_CRYPTO_EccSignaturePurpose::purpose, EphemeralConfirmationPS::purpose, SignDvCls::req, EphemeralConfirmationPS::sender_monotonic_time, sign_dv_cb(), GNUNET_CRYPTO_EccSignaturePurpose::size, EphemeralConfirmationPS::target, and DistanceVector::target.

Referenced by encapsulate_for_dv().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_queue_entry()

static void free_queue_entry ( struct QueueEntry qe,
struct TransportClient tc 
)
static

Definition at line 11693 of file gnunet-service-transport.c.

11695{
11696 struct PendingMessage *pm;
11697
11698 GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
11699 qe->queue->queue_tail,
11700 qe);
11701 qe->queue->queue_length--;
11702 tc->details.communicator.total_queue_length--;
11704 "Received ACK on queue %s (QID %u) to peer %s (new length: %u/%u)\n",
11705 qe->queue->address,
11706 qe->queue->qid,
11707 GNUNET_i2s (&qe->queue->neighbour->pid),
11708 qe->queue->queue_length,
11709 tc->details.communicator.total_queue_length);
11710
11711 /* if applicable, resume transmissions that waited on ACK */
11713 tc->details.communicator.total_queue_length)
11714 {
11715 /* Communicator dropped below threshold, resume all queues
11716 incident with this client! */
11718 GST_stats,
11719 "# Transmission throttled due to communicator queue limit",
11720 -1,
11721 GNUNET_NO);
11722 for (struct Queue *queue = tc->details.communicator.queue_head;
11723 NULL != queue;
11724 queue = queue->next_client)
11725 {
11727 queue,
11729 }
11730 }
11731 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
11732 {
11733 /* queue dropped below threshold; only resume this one queue */
11735 "# Transmission throttled due to queue queue limit",
11736 -1,
11737 GNUNET_NO);
11739 qe->queue,
11741 }
11742 else if (1 == qe->queue->q_capacity)
11743 {
11744 // TODO I guess this will never happen, because the communicator triggers this by updating its queue length itself.
11746 "Transmission rescheduled due to communicator message queue with qid %u has capacity %"
11747 PRIu64 ".\n",
11748 qe->queue->qid,
11749 qe->queue->q_capacity);
11750 /* message queue has capacity; only resume this one queue */
11751 /* queue dropped below threshold; only resume this one queue */
11753 "# Transmission throttled due to message queue capacity",
11754 -1,
11755 GNUNET_NO);
11757 qe->queue,
11759 }
11760
11761 if (NULL != (pm = qe->pm))
11762 {
11763 struct VirtualLink *vl;
11764
11765 // GNUNET_assert (qe == pm->qe);
11766 pm->qe = NULL;
11767 /* If waiting for this communicator may have blocked transmission
11768 of pm on other queues for this neighbour, force schedule
11769 transmit on queue for queues of the neighbour */
11770 if (NULL == pm->frag_parent)
11771 {
11772 vl = pm->vl;
11773 if ((NULL != vl) &&
11774 (NULL != vl->pending_msg_head) &&
11775 (vl->pending_msg_head == pm))
11777 }
11778 }
11779 GNUNET_free (qe);
11780}

References check_vl_transmission(), COMMUNICATOR_TOTAL_QUEUE_LIMIT, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_STATISTICS_update(), GNUNET_TIME_UNIT_ZERO, GST_stats, VirtualLink::pending_msg_head, pm, qe, queue(), QUEUE_LENGTH_LIMIT, schedule_transmit_on_queue(), and tc.

Referenced by free_timedout_queue_entry(), and handle_send_message_ack().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_timedout_queue_entry()

static void free_timedout_queue_entry ( void *  cls)
static

Definition at line 4796 of file gnunet-service-transport.c.

4797{
4798 struct TransportClient *tc = cls;
4800
4802 "freeing timedout queue entries\n");
4803
4804 tc->details.communicator.free_queue_entry_task = NULL;
4805 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
4806 queue = queue->next_client)
4807 {
4808 struct QueueEntry *qep = queue->queue_head;
4809
4811 "checking QID %u for timedout queue entries\n",
4812 queue->qid);
4813 while (NULL != qep)
4814 {
4815 struct QueueEntry *pos = qep;
4817 pos->creation_timestamp, now);
4818 qep = qep->next;
4819
4821 "diff to now %s \n",
4824 {
4826 "Freeing timed out QueueEntry with MID %" PRIu64
4827 " and QID %u\n",
4828 pos->mid,
4829 queue->qid);
4830 free_queue_entry (pos, tc);
4831 }
4832 }
4833 }
4834}

References QueueEntry::creation_timestamp, free_queue_entry(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_TIME_absolute_get(), GNUNET_TIME_absolute_get_difference(), GNUNET_TIME_relative2s(), GNUNET_TIME_relative_cmp, QueueEntry::mid, QueueEntry::next, queue(), QUEUE_ENTRY_TIMEOUT, and tc.

Referenced by queue_send_msg().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ queue_send_msg()

static void queue_send_msg ( struct Queue queue,
struct PendingMessage pm,
const void *  payload,
size_t  payload_size 
)
static

Send the message payload on queue.

Parameters
queuethe queue to use for transmission
pmpending message to update once transmission is done, may be NULL!
payloadthe payload to send (encapsulated in a GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG).
payload_sizenumber of bytes in payload

Definition at line 4847 of file gnunet-service-transport.c.

4851{
4852 struct Neighbour *n = queue->neighbour;
4854 struct GNUNET_MQ_Envelope *env;
4855 struct PendingAcknowledgement *pa;
4856
4857 GNUNET_log (
4859 "Queueing %u bytes of payload for transmission <%" PRIu64
4860 "> on queue %llu to %s\n",
4861 (unsigned int) payload_size,
4862 (NULL == pm) ? 0 : pm->logging_uuid,
4863 (unsigned long long) queue->qid,
4864 GNUNET_i2s (&queue->neighbour->pid));
4865 env = GNUNET_MQ_msg_extra (smt,
4866 payload_size,
4868 smt->qid = htonl (queue->qid);
4869 smt->mid = GNUNET_htonll (queue->mid_gen);
4870 smt->receiver = n->pid;
4871 memcpy (&smt[1], payload, payload_size);
4872 {
4873 /* Pass the env to the communicator of queue for transmission. */
4874 struct QueueEntry *qe;
4875
4876 qe = GNUNET_new (struct QueueEntry);
4877 qe->creation_timestamp = GNUNET_TIME_absolute_get ();
4878 qe->mid = queue->mid_gen;
4880 "Create QueueEntry with MID %" PRIu64
4881 " and QID %u and prefix %s\n",
4882 qe->mid,
4883 queue->qid,
4884 queue->tc->details.communicator.address_prefix);
4885 queue->mid_gen++;
4886 qe->queue = queue;
4887 if (NULL != pm)
4888 {
4889 qe->pm = pm;
4890 // TODO Why do we have a retransmission. When we know, make decision if we still want this.
4891 // GNUNET_assert (NULL == pm->qe);
4892 if (NULL != pm->qe)
4893 {
4895 "Retransmitting message <%" PRIu64
4896 "> remove pm from qe with MID: %llu \n",
4897 pm->logging_uuid,
4898 (unsigned long long) pm->qe->mid);
4899 pm->qe->pm = NULL;
4900 }
4901 pm->qe = qe;
4902 }
4903 GNUNET_assert (CT_COMMUNICATOR == queue->tc->type);
4904 if (0 == queue->q_capacity)
4905 {
4906 // Messages without FC or fragments can get here.
4907 if (NULL != pm)
4908 {
4910 "Message %" PRIu64
4911 " (pm type %u) was not send because queue has no capacity.\n",
4912 pm->logging_uuid,
4913 pm->pmt);
4914 pm->qe = NULL;
4915 }
4916 GNUNET_free (env);
4917 GNUNET_free (qe);
4918 return;
4919 }
4920 GNUNET_CONTAINER_DLL_insert (queue->queue_head, queue->queue_tail, qe);
4921 queue->queue_length++;
4922 queue->tc->details.communicator.total_queue_length++;
4923 if (GNUNET_NO == queue->unlimited_length)
4924 queue->q_capacity--;
4926 "Queue %s with qid %u has capacity %" PRIu64 "\n",
4927 queue->address,
4928 queue->qid,
4929 queue->q_capacity);
4931 queue->tc->details.communicator.total_queue_length)
4932 queue->idle = GNUNET_NO;
4933 if (QUEUE_LENGTH_LIMIT == queue->queue_length)
4934 queue->idle = GNUNET_NO;
4935 if (0 == queue->q_capacity)
4936 queue->idle = GNUNET_NO;
4937
4938 if (GNUNET_NO == queue->idle)
4939 {
4940 struct TransportClient *tc = queue->tc;
4941
4942 if (NULL == tc->details.communicator.free_queue_entry_task)
4943 tc->details.communicator.free_queue_entry_task =
4945 &
4947 tc);
4948 }
4949 if (NULL != pm && NULL != (pa = pm->pa_head))
4950 {
4951 while (pm != pa->pm)
4952 pa = pa->next_pa;
4953 pa->num_send++;
4954 }
4955 // GNUNET_CONTAINER_multiuuidmap_get (pending_acks, &ack[i].ack_uuid.value);
4957 "Sending message MID %" PRIu64
4958 " of type %u (%u) and size %lu with MQ %p queue %s (QID %u) pending %"
4959 PRIu64 "\n",
4960 GNUNET_ntohll (smt->mid),
4961 ntohs (((const struct GNUNET_MessageHeader *) payload)->type),
4962 ntohs (smt->header.size),
4963 (unsigned long) payload_size,
4964 queue->tc->mq,
4965 queue->address,
4966 queue->qid,
4967 (NULL == pm) ? 0 : pm->logging_uuid);
4968 GNUNET_MQ_send (queue->tc->mq, env);
4969 }
4970}

References COMMUNICATOR_TOTAL_QUEUE_LIMIT, CT_COMMUNICATOR, env, free_timedout_queue_entry(), GNUNET_assert, GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_htonll(), GNUNET_i2s(), GNUNET_log, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_new, GNUNET_NO, GNUNET_ntohll(), GNUNET_SCHEDULER_add_delayed(), GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_SECONDS, GNUNET_TRANSPORT_SendMessageTo::header, GNUNET_TRANSPORT_SendMessageTo::mid, PendingAcknowledgement::next_pa, PendingAcknowledgement::num_send, payload, Neighbour::pid, PendingAcknowledgement::pm, pm, qe, GNUNET_TRANSPORT_SendMessageTo::qid, queue(), QUEUE_LENGTH_LIMIT, GNUNET_TRANSPORT_SendMessageTo::receiver, GNUNET_MessageHeader::size, tc, and type.

Referenced by route_via_neighbour(), sign_dv_init_cb(), transmit_on_queue(), and validation_transmit_on_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ route_via_neighbour()

static struct GNUNET_TIME_Relative route_via_neighbour ( const struct Neighbour n,
const struct GNUNET_MessageHeader hdr,
enum RouteMessageOptions  options 
)
static

Pick a queue of n under constraints options and schedule transmission of hdr.

Parameters
nneighbour to send to
hdrmessage to send as payload
optionswhether queues must be confirmed or not, and whether we may pick multiple (2) queues
Returns
expected RTT for transmission, GNUNET_TIME_UNIT_FOREVER_REL if sending failed

Definition at line 4984 of file gnunet-service-transport.c.

4987{
4988 struct GNUNET_TIME_Absolute now;
4989 unsigned int candidates;
4990 unsigned int sel1;
4991 unsigned int sel2;
4992 struct GNUNET_TIME_Relative rtt;
4993
4994 /* Pick one or two 'random' queues from n (under constraints of options) */
4995 now = GNUNET_TIME_absolute_get ();
4996 /* FIXME-OPTIMIZE: give queues 'weights' and pick proportional to
4997 weight in the future; weight could be assigned by observed
4998 bandwidth (note: not sure if we should do this for this type
4999 of control traffic though). */
5000 candidates = 0;
5001 for (struct Queue *pos = n->queue_head; NULL != pos;
5002 pos = pos->next_neighbour)
5003 {
5004 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
5005 (pos->validated_until.abs_value_us > now.abs_value_us))
5006 candidates++;
5007 }
5008 if (0 == candidates)
5009 {
5010 /* This can happen rarely if the last confirmed queue timed
5011 out just as we were beginning to process this message. */
5013 "Could not route message of type %u to %s: no valid queue\n",
5014 ntohs (hdr->type),
5015 GNUNET_i2s (&n->pid));
5017 "# route selection failed (all no valid queue)",
5018 1,
5019 GNUNET_NO);
5021 }
5022
5025 if (0 == (options & RMO_REDUNDANT))
5026 sel2 = candidates; /* picks none! */
5027 else
5029 candidates = 0;
5030 for (struct Queue *pos = n->queue_head; NULL != pos;
5031 pos = pos->next_neighbour)
5032 {
5033 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
5034 (pos->validated_until.abs_value_us > now.abs_value_us))
5035 {
5036 if ((sel1 == candidates) || (sel2 == candidates))
5037 {
5039 "Routing message of type %u to %s using %s (#%u)\n",
5040 ntohs (hdr->type),
5041 GNUNET_i2s (&n->pid),
5042 pos->address,
5043 (sel1 == candidates) ? 1 : 2);
5044 rtt = GNUNET_TIME_relative_min (rtt, pos->pd.aged_rtt);
5045 queue_send_msg (pos, NULL, hdr, ntohs (hdr->size));
5046 }
5047 candidates++;
5048 }
5049 }
5050 return rtt;
5051}

References GNUNET_TIME_Absolute::abs_value_us, GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u32(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_min(), GNUNET_TIME_UNIT_FOREVER_REL, GST_stats, options, queue_send_msg(), RMO_REDUNDANT, RMO_UNCONFIRMED_ALLOWED, GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

Referenced by forward_dv_box(), handle_communicator_backchannel(), route_control_message_without_fc(), send_dv_to_neighbour(), sign_dhp_cp(), sign_t_validation_cb(), and transmit_cummulative_ack_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ dv_setup_key_state_from_km()

static void dv_setup_key_state_from_km ( const struct GNUNET_ShortHashCode km,
const struct GNUNET_ShortHashCode iv,
struct DVKeyState key 
)
static

Given the key material in km and the initialization vector iv, setup the key material for the backchannel in key.

Parameters
kmraw master secret
ivinitialization vector
[out]keysymmetric cipher and HMAC state to generate

Definition at line 5096 of file gnunet-service-transport.c.

5099{
5100 /* must match what we defive from decapsulated key */
5102 GNUNET_CRYPTO_hkdf_expand (&key->material,
5103 sizeof(key->material),
5104 km,
5105 "gnunet-transport-dv-key",
5106 strlen ("gnunet-transport-dv-key")
5107 ,
5108 km,
5109 sizeof(*km),
5110 iv,
5111 sizeof(*iv),
5112 NULL));
5114 "Deriving backchannel key based on KM %s and IV %s\n",
5115 GNUNET_sh2s (km),
5116 GNUNET_sh2s (iv));
5117 GNUNET_assert (0 == gcry_cipher_open (&key->cipher,
5118 GCRY_CIPHER_AES256 /* low level: go for speed */
5119 ,
5120 GCRY_CIPHER_MODE_CTR,
5121 0 /* flags */));
5122 GNUNET_assert (0 == gcry_cipher_setkey (key->cipher,
5123 &key->material.aes_key,
5124 sizeof(key->material.aes_key)));
5125 gcry_cipher_setctr (key->cipher,
5126 &key->material.aes_ctr,
5127 sizeof(key->material.aes_ctr));
5128}

References GNUNET_assert, GNUNET_CRYPTO_hkdf_expand(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_sh2s(), GNUNET_YES, and key.

Referenced by decaps_dv_box_cb(), and encapsulate_for_dv().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ dv_hmac()

static void dv_hmac ( const struct DVKeyState key,
struct GNUNET_HashCode hmac,
const void *  data,
size_t  data_size 
)
static

Do HMAC calculation for backchannel messages over data using key material from key.

Parameters
keykey material (from DH)
[out]hmacset to the HMAC
datadata to perform HMAC calculation over
data_sizenumber of bytes in data

Definition at line 5141 of file gnunet-service-transport.c.

5145{
5146 GNUNET_CRYPTO_hmac (&key->material.hmac_key, data, data_size, hmac);
5147}

References data, data_size, GNUNET_CRYPTO_hmac(), and key.

Referenced by decaps_dv_box_cb(), and encapsulate_for_dv().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ dv_encrypt()

static void dv_encrypt ( struct DVKeyState key,
const void *  in,
void *  dst,
size_t  in_size 
)
static

Perform backchannel encryption using symmetric secret in key to encrypt data from in to dst.

Parameters
[in,out]keykey material to use
dstwhere to write the result
ininput data to encrypt (plaintext)
in_sizenumber of bytes of input in in and available at dst

Definition at line 5160 of file gnunet-service-transport.c.

5161{
5162 GNUNET_assert (0 ==
5163 gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size));
5164}

References GNUNET_assert, and key.

Referenced by encapsulate_for_dv().

Here is the caller graph for this function:

◆ dv_decrypt()

static enum GNUNET_GenericReturnValue dv_decrypt ( struct DVKeyState key,
void *  out,
const void *  ciph,
size_t  out_size 
)
static

Perform backchannel encryption using symmetric secret in key to encrypt data from in to dst.

Parameters
[in,out]keykey material to use
ciphcipher text to decrypt
[out]outoutput data to generate (plaintext)
out_sizenumber of bytes of input in ciph and available in out
Returns
GNUNET_OK on success

Definition at line 5178 of file gnunet-service-transport.c.

5182{
5183 return (0 ==
5184 gcry_cipher_decrypt (key->cipher,
5185 out, out_size,
5186 ciph, out_size)) ? GNUNET_OK : GNUNET_SYSERR;
5187}

References GNUNET_OK, GNUNET_SYSERR, and key.

Referenced by decaps_dv_box_cb().

Here is the caller graph for this function:

◆ dv_key_clean()

static void dv_key_clean ( struct DVKeyState key)
static

Clean up key material in key.

Parameters
keykey material to clean up (memory must not be free'd!)

Definition at line 5196 of file gnunet-service-transport.c.

5197{
5198 gcry_cipher_close (key->cipher);
5199 GNUNET_CRYPTO_zero_keys (&key->material, sizeof(key->material));
5200}

References GNUNET_CRYPTO_zero_keys(), and key.

Referenced by decaps_dv_box_cb(), and encapsulate_for_dv().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ encapsulate_for_dv()

static struct GNUNET_TIME_Relative encapsulate_for_dv ( struct DistanceVector dv,
unsigned int  num_dvhs,
struct DistanceVectorHop **  dvhs,
const struct GNUNET_MessageHeader hdr,
DVMessageHandler  use,
void *  use_cls,
enum RouteMessageOptions  options,
enum GNUNET_GenericReturnValue  without_fc 
)
static

Pick a path of dv under constraints options and schedule transmission of hdr.

Parameters
targetneighbour to ultimately send to
num_dvhslength of the dvhs array
dvhsarray of hops to send the message to
hdrmessage to send as payload
usefunction to call with the encapsulated message
use_clsclosure for use
optionswhether path must be confirmed or not, to be passed to use
without_fcshall this TransportDVBoxMessage be forwarded without flow control.
Returns
expected RTT for transmission, GNUNET_TIME_UNIT_FOREVER_REL if sending failed

Definition at line 5233 of file gnunet-service-transport.c.

5241{
5242 struct TransportDVBoxMessage box_hdr;
5243 struct TransportDVBoxPayloadP payload_hdr;
5244 uint16_t enc_body_size = ntohs (hdr->size);
5245 char enc[sizeof(struct TransportDVBoxPayloadP) + enc_body_size] GNUNET_ALIGN;
5246 struct DVKeyState *key;
5247 struct GNUNET_TIME_Relative rtt;
5248 struct GNUNET_ShortHashCode km;
5249
5250 key = GNUNET_new (struct DVKeyState);
5251 /* Encrypt payload */
5252 box_hdr.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX);
5253 box_hdr.total_hops = htons (0);
5254 box_hdr.without_fc = htons (without_fc);
5255 // update_ephemeral (dv);
5256 if (0 ==
5258 {
5260 &dv->ephemeral_key,
5261 &km);
5262 dv->km = GNUNET_new (struct GNUNET_ShortHashCode);
5263 GNUNET_memcpy (dv->km, &km, sizeof(struct GNUNET_ShortHashCode));
5264 sign_ephemeral (dv);
5265 }
5266 box_hdr.ephemeral_key = dv->ephemeral_key;
5267 payload_hdr.sender_sig = dv->sender_sig;
5268
5270 &box_hdr.iv,
5271 sizeof(box_hdr.iv));
5272 // We are creating this key, so this must work.
5273 // FIXME: Possibly also add return values here. We are processing
5274 // Input from other peers...
5275 dv_setup_key_state_from_km (dv->km, &box_hdr.iv, key);
5276 payload_hdr.sender = *GST_my_identity;
5277 payload_hdr.monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
5278 dv_encrypt (key, &payload_hdr, enc, sizeof(payload_hdr));
5279 dv_encrypt (key,
5280 hdr,
5281 &enc[sizeof(struct TransportDVBoxPayloadP)],
5282 enc_body_size);
5283 dv_hmac (key, &box_hdr.hmac, enc, sizeof(enc));
5284 dv_key_clean (key);
5286 /* For each selected path, take the pre-computed header and body
5287 and add the path in the middle of the message; then send it. */
5288 for (unsigned int i = 0; i < num_dvhs; i++)
5289 {
5290 struct DistanceVectorHop *dvh = dvhs[i];
5291 unsigned int num_hops = dvh->distance + 1;
5292 char buf[sizeof(struct TransportDVBoxMessage)
5293 + sizeof(struct GNUNET_PeerIdentity) * num_hops
5294 + sizeof(struct TransportDVBoxPayloadP)
5295 + enc_body_size] GNUNET_ALIGN;
5296 struct GNUNET_PeerIdentity *dhops;
5297
5298 box_hdr.header.size = htons (sizeof(buf));
5299 box_hdr.orig_size = htons (sizeof(buf));
5300 box_hdr.num_hops = htons (num_hops);
5301 memcpy (buf, &box_hdr, sizeof(box_hdr));
5302 dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
5303 memcpy (dhops,
5304 dvh->path,
5305 dvh->distance * sizeof(struct GNUNET_PeerIdentity));
5306 dhops[dvh->distance] = dv->target;
5307 if (GNUNET_EXTRA_LOGGING > 0)
5308 {
5309 char *path;
5310
5312 for (unsigned int j = 0; j < num_hops; j++)
5313 {
5314 char *tmp;
5315
5316 GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
5317 GNUNET_free (path);
5318 path = tmp;
5319 }
5321 "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
5322 ntohs (hdr->type),
5323 GNUNET_i2s (&dv->target),
5324 i + 1,
5325 num_dvhs,
5326 path);
5327 GNUNET_free (path);
5328 }
5329 rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
5330 memcpy (&dhops[num_hops], enc, sizeof(enc));
5331 use (use_cls,
5332 dvh->next_hop,
5333 (const struct GNUNET_MessageHeader *) buf,
5334 options);
5335 GNUNET_free (key);
5336 }
5337 return rtt;
5338}

References PerformanceData::aged_rtt, DistanceVectorHop::distance, dv_encrypt(), dv_hmac(), dv_key_clean(), dv_setup_key_state_from_km(), enc, TransportDVBoxMessage::ephemeral_key, GNUNET_ALIGN, GNUNET_asprintf(), GNUNET_CRYPTO_eddsa_kem_encaps(), GNUNET_CRYPTO_QUALITY_NONCE, GNUNET_CRYPTO_random_block(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_EXTRA_LOGGING, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX, GNUNET_new, GNUNET_strdup, GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_absolute_hton(), GNUNET_TIME_relative_min(), GNUNET_TIME_UNIT_FOREVER_REL, GST_my_identity, TransportDVBoxMessage::header, TransportDVBoxMessage::hmac, TransportDVBoxMessage::iv, key, TransportDVBoxPayloadP::monotonic_time, DistanceVectorHop::next_hop, TransportDVBoxMessage::num_hops, options, TransportDVBoxMessage::orig_size, DistanceVectorHop::path, DistanceVectorHop::pd, GNUNET_TIME_Relative::rel_value_us, TransportDVBoxPayloadP::sender, TransportDVBoxPayloadP::sender_sig, sign_ephemeral(), GNUNET_MessageHeader::size, TransportDVBoxMessage::total_hops, GNUNET_MessageHeader::type, and TransportDVBoxMessage::without_fc.

Referenced by route_control_message_without_fc(), and transmit_on_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ send_dv_to_neighbour()

static void send_dv_to_neighbour ( void *  cls,
struct Neighbour next_hop,
const struct GNUNET_MessageHeader hdr,
enum RouteMessageOptions  options 
)
static

Wrapper around route_via_neighbour() that matches the DVMessageHandler structure.

Parameters
clsunused
next_hopwhere to send next
hdrheader of the message to send
optionsmessage options for queue selection

Definition at line 5351 of file gnunet-service-transport.c.

5355{
5356 (void) cls;
5357 (void) route_via_neighbour (next_hop, hdr, RMO_UNCONFIRMED_ALLOWED);
5358}

References RMO_UNCONFIRMED_ALLOWED, and route_via_neighbour().

Referenced by route_control_message_without_fc().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ route_control_message_without_fc()

static struct GNUNET_TIME_Relative route_control_message_without_fc ( struct VirtualLink vl,
const struct GNUNET_MessageHeader hdr,
enum RouteMessageOptions  options 
)
static

We need to transmit hdr to target.

If necessary, this may involve DV routing. This function routes without applying flow control or congestion control and should only be used for control traffic.

Parameters
targetpeer to receive hdr
hdrheader of the message to route and GNUNET_free()
optionswhich transmission channels are allowed
Returns
expected RTT for transmission, GNUNET_TIME_UNIT_FOREVER_REL if sending failed

Definition at line 5373 of file gnunet-service-transport.c.

5377{
5378 // struct VirtualLink *vl;
5379 struct Neighbour *n;
5380 struct DistanceVector *dv;
5381 struct GNUNET_TIME_Relative rtt1;
5382 struct GNUNET_TIME_Relative rtt2;
5383 const struct GNUNET_PeerIdentity *target = &vl->target;
5384
5386 "Trying to route message of type %u to %s without fc\n",
5387 ntohs (hdr->type),
5388 GNUNET_i2s (target));
5389
5390 // TODO Do this elsewhere. vl should be given as parameter to method.
5391 // vl = lookup_virtual_link (target);
5392 GNUNET_assert (NULL != vl && GNUNET_YES == vl->confirmed);
5393 if (NULL == vl)
5395 n = vl->n;
5396 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
5397 if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
5398 {
5399 /* if confirmed is required, and we do not have anything
5400 confirmed, drop respective options */
5401 if (NULL == n)
5402 n = lookup_neighbour (target);
5403 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
5405 }
5406 if ((NULL == n) && (NULL == dv))
5407 {
5409 "Cannot route message of type %u to %s: no route\n",
5410 ntohs (hdr->type),
5411 GNUNET_i2s (target));
5413 "# Messages dropped in routing: no acceptable method",
5414 1,
5415 GNUNET_NO);
5417 }
5419 "Routing message of type %u to %s with options %X\n",
5420 ntohs (hdr->type),
5421 GNUNET_i2s (target),
5422 (unsigned int) options);
5423 /* If both dv and n are possible and we must choose:
5424 flip a coin for the choice between the two; for now 50/50 */
5425 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
5426 {
5428 n = NULL;
5429 else
5430 dv = NULL;
5431 }
5432 if ((NULL != n) && (NULL != dv))
5433 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
5434 enough for redundancy, so clear the flag. */
5437 if (NULL != n)
5438 {
5440 "Try to route message of type %u to %s without fc via neighbour\n",
5441 ntohs (hdr->type),
5442 GNUNET_i2s (target));
5443 rtt1 = route_via_neighbour (n, hdr, options);
5444 }
5445 if (NULL != dv)
5446 {
5447 struct DistanceVectorHop *hops[2];
5448 unsigned int res;
5449
5451 options,
5452 hops,
5453 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
5454 if (0 == res)
5455 {
5457 "Failed to route message, could not determine DV path\n");
5458 return rtt1;
5459 }
5461 "encapsulate_for_dv 1\n");
5462 rtt2 = encapsulate_for_dv (dv,
5463 res,
5464 hops,
5465 hdr,
5467 NULL,
5469 GNUNET_YES);
5470 }
5471 return GNUNET_TIME_relative_min (rtt1, rtt2);
5472}

References DistanceVectorHop::dv, dv_routes, encapsulate_for_dv(), GNUNET_assert, GNUNET_CONTAINER_multipeermap_get(), GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u32(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_TIME_relative_min(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, GST_stats, lookup_neighbour(), options, pick_random_dv_hops(), res, RMO_DV_ALLOWED, RMO_REDUNDANT, RMO_UNCONFIRMED_ALLOWED, route_via_neighbour(), send_dv_to_neighbour(), and GNUNET_MessageHeader::type.

Referenced by consider_sending_fc(), handle_communicator_backchannel(), sign_dhp_cp(), sign_t_validation_cb(), and transmit_cummulative_ack_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ consider_sending_fc()

static void consider_sending_fc ( void *  cls)
static

Something changed on the virtual link with respect to flow control.

Consider retransmitting the FC window size.

Parameters
clsa struct VirtualLink to work with

Definition at line 5538 of file gnunet-service-transport.c.

5539{
5540 struct VirtualLink *vl = cls;
5541 struct GNUNET_TIME_Absolute monotime;
5542 struct TransportFlowControlMessage *fc;
5544 struct GNUNET_TIME_Relative rtt;
5545 struct GNUNET_TIME_Relative rtt_average;
5546 struct Neighbour *n = vl->n;
5547
5548 if (NULL != n && 0 < n->number_of_addresses)
5549 {
5550 size_t addresses_size =
5551 n->number_of_addresses * sizeof (struct TransportGlobalNattedAddress) + n
5552 ->size_of_global_addresses;
5553 char *tgnas = GNUNET_malloc (addresses_size);
5555 ctx.off = 0;
5556 ctx.tgnas = tgnas;
5557
5559 + addresses_size);
5560 fc->header.size = htons (sizeof(struct TransportFlowControlMessage)
5561 + addresses_size);
5562 fc->size_of_addresses = htonl (n->size_of_global_addresses);
5563 fc->number_of_addresses = htonl (n->number_of_addresses);
5566 &ctx);
5569 }
5570 else
5571 {
5572 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage));
5573 fc->header.size = htons (sizeof(struct TransportFlowControlMessage));
5574 }
5575
5577 /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
5578 it always! */
5579 /* For example, we should probably ONLY do this if a bit more than
5580 an RTT has passed, or if the window changed "significantly" since
5581 then. See vl->last_fc_rtt! NOTE: to do this properly, we also
5582 need an estimate for the bandwidth-delay-product for the entire
5583 VL, as that determines "significantly". We have the delay, but
5584 the bandwidth statistics need to be added for the VL!*/(void) duration;
5585
5586 if (NULL != vl->dv)
5587 rtt_average = calculate_rtt (vl->dv);
5588 else
5589 rtt_average = GNUNET_TIME_UNIT_FOREVER_REL;
5590 fc->rtt = GNUNET_TIME_relative_hton (rtt_average);
5592 "Sending FC seq %u to %s with new window %llu %lu %u\n",
5593 (unsigned int) vl->fc_seq_gen,
5594 GNUNET_i2s (&vl->target),
5595 (unsigned long long) vl->incoming_fc_window_size,
5596 (unsigned long) rtt_average.rel_value_us,
5597 vl->sync_ready);
5599 vl->last_fc_transmission = monotime;
5600 fc->sync_ready = vl->sync_ready;
5602 fc->seq = htonl (vl->fc_seq_gen++);
5603 fc->inbound_window_size = GNUNET_htonll (vl->incoming_fc_window_size
5606 fc->outbound_sent = GNUNET_htonll (vl->outbound_fc_window_size_used);
5607 fc->outbound_window_size = GNUNET_htonll (vl->outbound_fc_window_size);
5608 fc->sender_time = GNUNET_TIME_absolute_hton (monotime);
5610 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
5611 {
5614 "FC retransmission to %s failed, will retry in %s\n",
5615 GNUNET_i2s (&vl->target),
5618 }
5619 else
5620 {
5621 /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
5622 vl->last_fc_rtt = rtt;
5623 }
5624 if (NULL != vl->fc_retransmit_task)
5627 {
5629 vl->fc_retransmit_count = 0;
5630 }
5631 vl->fc_retransmit_task =
5633 vl->fc_retransmit_count++;
5634 GNUNET_free (fc);
5635}

References add_global_addresses(), calculate_rtt(), ctx, duration, VirtualLink::dv, VirtualLink::fc_retransmit_count, VirtualLink::fc_retransmit_task, VirtualLink::fc_seq_gen, GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_htonll(), GNUNET_i2s(), GNUNET_log, GNUNET_malloc, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL, GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_cancel(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_absolute_get_duration(), GNUNET_TIME_absolute_get_monotonic(), GNUNET_TIME_absolute_hton(), GNUNET_TIME_relative_hton(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TIME_UNIT_MINUTES, GNUNET_TIME_UNIT_SECONDS, GNUNET_TIME_UNIT_ZERO, GNUNET_YES, GST_cfg, VirtualLink::incoming_fc_window_size, VirtualLink::incoming_fc_window_size_loss, VirtualLink::incoming_fc_window_size_used, VirtualLink::last_fc_rtt, VirtualLink::last_fc_transmission, MAX_FC_RETRANSMIT_COUNT, VirtualLink::n, Neighbour::number_of_addresses, AddGlobalAddressesContext::off, VirtualLink::outbound_fc_window_size, VirtualLink::outbound_fc_window_size_used, GNUNET_TIME_Relative::rel_value_us, RMO_DV_ALLOWED, route_control_message_without_fc(), VirtualLink::sync_ready, VirtualLink::target, task_consider_sending_fc(), AddGlobalAddressesContext::tgnas, and Neighbour::vl.

Referenced by activate_core_visible_dv_path(), check_vl_transmission(), core_env_sent_cb(), handle_flow_control(), handle_validation_response(), and task_consider_sending_fc().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ task_consider_sending_fc()

static void task_consider_sending_fc ( void *  cls)
static

Something changed on the virtual link with respect to flow control.

Consider retransmitting the FC window size.

Parameters
clsa struct VirtualLink to work with

Definition at line 5485 of file gnunet-service-transport.c.

5486{
5487 struct VirtualLink *vl = cls;
5488 vl->fc_retransmit_task = NULL;
5489 consider_sending_fc (cls);
5490}

References consider_sending_fc(), and VirtualLink::fc_retransmit_task.

Referenced by consider_sending_fc().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_address_without_port()

static char * get_address_without_port ( const char *  address)
static

Get the IP address without the port number.

Parameters
addressThe string contains a communicator prefix, IP address and port like this 'tcp-92.68.150.1:55452'.
Returns
String with IP address only.

Definition at line 12368 of file gnunet-service-transport.c.

12369{
12370 const char *colon;
12371 char *colon_rest;
12372 size_t colon_rest_length;
12373 char *address_without_port;
12374
12375 colon = strchr (address,':');
12376 colon_rest = GNUNET_strndup (address, colon - address);
12377 colon_rest_length = strlen (colon_rest);
12378 address_without_port = GNUNET_strndup (&colon_rest[4], colon_rest_length - 4);
12379 GNUNET_free (colon_rest);
12380
12381 return address_without_port;
12382}

References address, GNUNET_free, and GNUNET_strndup.

Referenced by check_for_global_natted(), check_validation_request_pending(), create_address_entry(), handle_add_queue_message(), iterate_address_and_compare_cb(), and iterate_address_start_burst().

Here is the caller graph for this function:

◆ add_global_addresses()

static enum GNUNET_GenericReturnValue add_global_addresses ( void *  cls,
const struct GNUNET_PeerIdentity pid,
void *  value 
)
static

Definition at line 5505 of file gnunet-service-transport.c.

5508{
5509 struct AddGlobalAddressesContext *ctx = cls;
5510 struct TransportGlobalNattedAddress *tgna = value;
5511 char *addr = (char *) &tgna[1];
5512
5514 "sending address %s length %u\n",
5515 addr,
5516 ntohl (tgna->address_length));
5517 GNUNET_memcpy (&(ctx->tgnas[ctx->off]), tgna, sizeof (struct
5519 + ntohl (tgna->address_length));
5520 ctx->off += sizeof(struct TransportGlobalNattedAddress) + ntohl (tgna->
5522
5523 return GNUNET_OK;
5524}

References TransportGlobalNattedAddress::address_length, ctx, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcpy, GNUNET_OK, and value.

Referenced by consider_sending_fc().

Here is the caller graph for this function:

◆ calculate_rtt()

static struct GNUNET_TIME_Relative calculate_rtt ( struct DistanceVector dv)
static

Definition at line 10195 of file gnunet-service-transport.c.

10196{
10198 unsigned int n_hops = 0;
10199
10201 "calculate_rtt\n");
10202 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
10203 pos = pos->next_dv)
10204 {
10206 "calculate_rtt %lu\n",
10207 (unsigned long) pos->pd.aged_rtt.rel_value_us);
10208 n_hops++;
10210 aged_rtt, pos
10211 ->distance
10212 + 2), ret);
10213 }
10214
10215 GNUNET_assert (0 != n_hops);
10216
10217 return ret;
10218}

References GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_TIME_relative_add(), GNUNET_TIME_relative_multiply(), GNUNET_TIME_UNIT_ZERO, and ret.

Referenced by consider_sending_fc(), and handle_flow_control().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_vl_transmission()

static void check_vl_transmission ( struct VirtualLink vl)
static

There is a message at the head of the pending messages for vl which may be ready for transmission.

Check if a queue is ready to take it.

This function must (1) check for flow control to ensure that we can right now send to vl, (2) check that the pending message in the queue is actually eligible, (3) determine if any applicable queue (direct neighbour or DVH path) is ready to accept messages, and (4) prioritize based on the preferences associated with the pending message.

So yeah, easy.

Parameters
vlvirtual link where we should check for transmission

Definition at line 5655 of file gnunet-service-transport.c.

5656{
5657 struct Neighbour *n = vl->n;
5658 struct DistanceVector *dv = vl->dv;
5659 struct GNUNET_TIME_Absolute now;
5660 struct VirtualLink *vl_next_hop;
5661 int elig;
5662
5664 "check_vl_transmission to target %s\n",
5665 GNUNET_i2s (&vl->target));
5666 /* Check that we have an eligible pending message!
5667 (cheaper than having #transmit_on_queue() find out!) */
5668 elig = GNUNET_NO;
5669 for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
5670 pm = pm->next_vl)
5671 {
5673 "check_vl_transmission loop\n");
5674 if (NULL != pm->qe)
5675 continue; /* not eligible, is in a queue! */
5676 if (pm->bytes_msg + vl->outbound_fc_window_size_used >
5678 {
5680 "Stalled message %" PRIu64
5681 " transmission on VL %s due to flow control: %llu < %llu\n",
5682 pm->logging_uuid,
5683 GNUNET_i2s (&vl->target),
5684 (unsigned long long) vl->outbound_fc_window_size,
5685 (unsigned long long) (pm->bytes_msg
5688 return; /* We have a message, but flow control says "nope" */
5689 }
5691 "Target window on VL %s not stalled. Scheduling transmission on queue\n",
5692 GNUNET_i2s (&vl->target));
5693 /* Notify queues at direct neighbours that we are interested */
5694 now = GNUNET_TIME_absolute_get ();
5695 if (NULL != n)
5696 {
5697 for (struct Queue *queue = n->queue_head; NULL != queue;
5698 queue = queue->next_neighbour)
5699 {
5700 if ((GNUNET_YES == queue->idle) &&
5701 (queue->validated_until.abs_value_us > now.abs_value_us))
5702 {
5704 "Direct neighbour %s not stalled\n",
5705 GNUNET_i2s (&n->pid));
5707 queue,
5709 elig = GNUNET_YES;
5710 }
5711 else
5713 "Neighbour Queue QID: %u (%u) busy or invalid\n",
5714 queue->qid,
5715 queue->idle);
5716 }
5717 }
5718 /* Notify queues via DV that we are interested */
5719 if (NULL != dv)
5720 {
5721 /* Do DV with lower scheduler priority, which effectively means that
5722 IF a neighbour exists and is available, we prefer it. */
5723 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5724 pos = pos->next_dv)
5725 {
5726 struct Neighbour *nh_iter = pos->next_hop;
5727
5728
5729 if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
5730 continue; /* skip this one: path not validated */
5731 else
5732 {
5733 vl_next_hop = lookup_virtual_link (&nh_iter->pid);
5734 GNUNET_assert (NULL != vl_next_hop);
5735 if (pm->bytes_msg + vl_next_hop->outbound_fc_window_size_used >
5736 vl_next_hop->outbound_fc_window_size)
5737 {
5739 "Stalled message %" PRIu64
5740 " transmission on next hop %s due to flow control: %llu < %llu\n",
5741 pm->logging_uuid,
5742 GNUNET_i2s (&vl_next_hop->target),
5743 (unsigned long
5744 long) vl_next_hop->outbound_fc_window_size,
5745 (unsigned long long) (pm->bytes_msg
5746 + vl_next_hop->
5747 outbound_fc_window_size_used));
5748 consider_sending_fc (vl_next_hop);
5749 continue; /* We have a message, but flow control says "nope" for the first hop of this path */
5750 }
5751 for (struct Queue *queue = nh_iter->queue_head; NULL != queue;
5752 queue = queue->next_neighbour)
5753 if ((GNUNET_YES == queue->idle) &&
5754 (queue->validated_until.abs_value_us > now.abs_value_us))
5755 {
5757 "Next hop neighbour %s not stalled\n",
5758 GNUNET_i2s (&nh_iter->pid));
5760 queue,
5762 elig = GNUNET_YES;
5763 }
5764 else
5766 "DV Queue QID: %u (%u) busy or invalid\n",
5767 queue->qid,
5768 queue->idle);
5769 }
5770 }
5771 }
5772 if (GNUNET_YES == elig)
5774 "Eligible message %" PRIu64 " of size %u to %s: %llu/%llu\n",
5775 pm->logging_uuid,
5776 pm->bytes_msg,
5777 GNUNET_i2s (&vl->target),
5778 (unsigned long long) vl->outbound_fc_window_size,
5779 (unsigned long long) (pm->bytes_msg
5781 break;
5782 }
5783}

References GNUNET_TIME_Absolute::abs_value_us, consider_sending_fc(), VirtualLink::dv, DistanceVector::dv_head, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_SCHEDULER_PRIORITY_BACKGROUND, GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_ZERO, GNUNET_YES, lookup_virtual_link(), VirtualLink::n, VirtualLink::outbound_fc_window_size, VirtualLink::outbound_fc_window_size_used, VirtualLink::pending_msg_head, Neighbour::pid, pm, queue(), Neighbour::queue_head, schedule_transmit_on_queue(), VirtualLink::target, DistanceVector::vl, and Neighbour::vl.

Referenced by forward_dv_box(), free_queue_entry(), handle_client_send(), handle_flow_control(), and send_msg_from_cache().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_client_send()

static void handle_client_send ( void *  cls,
const struct OutboundMessage obm 
)
static

Client asked for transmission to a peer.

Process the request.

Parameters
clsthe client
obmthe send message that was sent

Definition at line 5793 of file gnunet-service-transport.c.

5794{
5795 struct TransportClient *tc = cls;
5796 struct PendingMessage *pm;
5797 const struct GNUNET_MessageHeader *obmm;
5798 uint32_t bytes_msg;
5799 struct VirtualLink *vl;
5801
5802 GNUNET_assert (CT_CORE == tc->type);
5803 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
5804 bytes_msg = ntohs (obmm->size);
5805 pp = ntohl (obm->priority);
5806 vl = lookup_virtual_link (&obm->peer);
5807 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
5808 {
5810 "Don't have %s as a neighbour (anymore).\n",
5811 GNUNET_i2s (&obm->peer));
5812 /* Failure: don't have this peer as a neighbour (anymore).
5813 Might have gone down asynchronously, so this is NOT
5814 a protocol violation by CORE. Still count the event,
5815 as this should be rare. */
5818 "# messages dropped (neighbour unknown)",
5819 1,
5820 GNUNET_NO);
5821 return;
5822 }
5823
5824 pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
5826 "1 created pm %p storing vl %p\n",
5827 pm,
5828 vl);
5829 pm->logging_uuid = logging_uuid_gen++;
5830 pm->prefs = pp;
5831 pm->client = tc;
5832 pm->vl = vl;
5833 pm->bytes_msg = bytes_msg;
5834 memcpy (&pm[1], obmm, bytes_msg);
5836 "Sending message of type %u with %u bytes as <%" PRIu64
5837 "> to %s\n",
5838 ntohs (obmm->type),
5839 bytes_msg,
5840 pm->logging_uuid,
5841 GNUNET_i2s (&obm->peer));
5843 tc->details.core.pending_msg_head,
5844 tc->details.core.pending_msg_tail,
5845 pm);
5847 vl->pending_msg_head,
5848 vl->pending_msg_tail,
5849 pm);
5852}

References check_vl_transmission(), VirtualLink::confirmed, CT_CORE, GNUNET_assert, GNUNET_CONTAINER_MDLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_malloc, GNUNET_NO, GNUNET_SERVICE_client_continue(), GNUNET_STATISTICS_update(), GST_stats, logging_uuid_gen, lookup_virtual_link(), OutboundMessage::peer, VirtualLink::pending_msg_head, VirtualLink::pending_msg_tail, pm, OutboundMessage::priority, GNUNET_MessageHeader::size, tc, and GNUNET_MessageHeader::type.

Here is the call graph for this function:

◆ handle_communicator_backchannel()

static void handle_communicator_backchannel ( void *  cls,
const struct GNUNET_TRANSPORT_CommunicatorBackchannel cb 
)
static

Communicator requests backchannel transmission.

Process the request. Just repacks it into our struct TransportBackchannelEncapsulationMessage * (which for now has exactly the same format, only a different message type) and passes it on for routing.

Parameters
clsthe client
cbthe send message that was sent

Definition at line 5865 of file gnunet-service-transport.c.

5868{
5869 struct Neighbour *n;
5870 struct VirtualLink *vl;
5871 struct TransportClient *tc = cls;
5872 const struct GNUNET_MessageHeader *inbox =
5873 (const struct GNUNET_MessageHeader *) &cb[1];
5874 uint16_t isize = ntohs (inbox->size);
5875 const char *is = ((const char *) &cb[1]) + isize;
5876 size_t slen = strlen (is) + 1;
5877 char
5878 mbuf[slen + isize
5879 + sizeof(struct
5883
5884 /* 0-termination of 'is' was checked already in
5885 #check_communicator_backchannel() */
5887 "Preparing backchannel transmission to %s:%s of type %u and size %u\n",
5888 GNUNET_i2s (&cb->pid),
5889 is,
5890 ntohs (inbox->type),
5891 ntohs (inbox->size));
5892 /* encapsulate and encrypt message */
5893 be->header.type =
5895 be->header.size = htons (sizeof(mbuf));
5896 memcpy (&be[1], inbox, isize);
5897 memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
5898 + isize],
5899 is,
5900 strlen (is) + 1);
5901 // route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
5902 vl = lookup_virtual_link (&cb->pid);
5903 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
5904 {
5906 }
5907 else
5908 {
5909 /* Use route via neighbour */
5910 n = lookup_neighbour (&cb->pid);
5911 if (NULL != n)
5913 n,
5914 &be->header,
5915 RMO_NONE);
5916 }
5918}

References VirtualLink::confirmed, GNUNET_ALIGN, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION, GNUNET_SERVICE_client_continue(), GNUNET_YES, TransportBackchannelEncapsulationMessage::header, is, lookup_neighbour(), lookup_virtual_link(), GNUNET_TRANSPORT_CommunicatorBackchannel::pid, RMO_DV_ALLOWED, RMO_NONE, route_control_message_without_fc(), route_via_neighbour(), GNUNET_MessageHeader::size, tc, and GNUNET_MessageHeader::type.

Here is the call graph for this function:

◆ check_add_address()

static int check_add_address ( void *  cls,
const struct GNUNET_TRANSPORT_AddAddressMessage aam 
)
static

Address of our peer added.

Test message is well-formed.

Parameters
clsthe client
aamthe send message that was sent
Returns
GNUNET_OK if message is well-formed

Definition at line 5929 of file gnunet-service-transport.c.

5931{
5932 struct TransportClient *tc = cls;
5933
5934 if (CT_COMMUNICATOR != tc->type)
5935 {
5936 GNUNET_break (0);
5937 return GNUNET_SYSERR;
5938 }
5940 return GNUNET_OK;
5941}

References CT_COMMUNICATOR, GNUNET_break, GNUNET_MQ_check_zero_termination, GNUNET_OK, GNUNET_SYSERR, and tc.

◆ store_pi()

static void store_pi ( void *  cls)
static

Ask peerstore to store our address.

Parameters
clsan struct AddressListEntry *

Definition at line 6196 of file gnunet-service-transport.c.

6197{
6198 struct AddressListEntry *ale = cls;
6199 const char *dash;
6200 char *address_uri;
6202 unsigned int add_success;
6203
6204 if (NULL == GST_my_identity)
6205 {
6207 &store_pi,
6208 ale);
6209 return;
6210 }
6211
6212 dash = strchr (ale->address, '-');
6213 GNUNET_assert (NULL != dash);
6214 dash++;
6215 GNUNET_asprintf (&address_uri,
6216 "%s://%s",
6217 prefix,
6218 dash);
6220 ale->st = NULL;
6222 "Storing our address `%s' in peerstore until %s!\n",
6223 ale->address,
6226 address_uri);
6227 if (GNUNET_OK != add_success)
6228 {
6230 "Storing our address `%s' %s\n",
6231 address_uri,
6232 GNUNET_NO == add_success ? "not done" : "failed");
6233 GNUNET_free (address_uri);
6234 return;
6235 }
6236 else
6237 {
6238
6240 "Storing our address `%s'\n",
6241 address_uri);
6242 }
6243 // FIXME hello_mono_time used here?? What about expiration in ale?
6244 pils_sign_address (ale,
6246 // TODO keep track of op and potentially cancle/clean
6247 GNUNET_free (address_uri);
6248}

References AddressListEntry::address, GNUNET_asprintf(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_HELLO_address_to_prefix(), GNUNET_HELLO_builder_add_address(), GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_delayed(), GNUNET_STRINGS_absolute_time_to_string(), GNUNET_TIME_UNIT_MILLISECONDS, GST_my_hello, GST_my_identity, hello_mono_time, pils_sign_address(), prefix, AddressListEntry::st, and store_pi().

Referenced by create_address_entry(), peerstore_store_own_cb(), shc_cont(), and store_pi().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ shc_cont()

static void shc_cont ( void *  cls,
int  success 
)
static

Definition at line 5978 of file gnunet-service-transport.c.

5979{
5980 struct PilsAddressSignContext *pc = cls;
5981
5982 GNUNET_assert (NULL == pc->req);
5983 if (GNUNET_OK != success)
5984 {
5986 "Failed to store our address `%s' with peerstore\n",
5987 pc->ale->address);
5988 if (NULL == pc->ale->st)
5989 {
5991 &store_pi,
5992 pc->ale);
5993 }
5994 }
5995 GNUNET_free (pc);
5996}

References GNUNET_assert, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_OK, GNUNET_SCHEDULER_add_delayed(), GNUNET_TIME_UNIT_SECONDS, pc, and store_pi().

Referenced by pils_sign_hello_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pils_sign_hello_cb()

static void pils_sign_hello_cb ( void *  cls,
const struct GNUNET_PeerIdentity pid,
const struct GNUNET_CRYPTO_EddsaSignature sig 
)
static

Get HELLO signature and create message to store in PEERSTORE.

Definition at line 6003 of file gnunet-service-transport.c.

6006{
6007 struct PilsAddressSignContext *pc = cls;
6008 struct GNUNET_MQ_Envelope *env;
6009 const struct GNUNET_MessageHeader *msg;
6010
6011 pc->req->op = NULL;
6014 pc->req);
6015 GNUNET_free (pc->req);
6016 pc->req = NULL;
6019 pid,
6020 sig,
6021 pc->et);
6024 "store_pi 1\n");
6026 msg,
6027 shc_cont,
6028 pc);
6029 GNUNET_free (env);
6030}

References env, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_HELLO_builder_to_env(), GNUNET_log, GNUNET_MQ_env_get_msg(), GNUNET_PEERSTORE_hello_add(), GST_my_hello, msg, pc, peerstore, pid, pils_requests_head, pils_requests_tail, and shc_cont().

Referenced by peerstore_store_own_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ peerstore_store_own_cb()

static void peerstore_store_own_cb ( void *  cls,
int  success 
)
static

Function called when peerstore is done storing our address.

Parameters
clsa struct AddressListEntry
successGNUNET_YES if peerstore was successful

Definition at line 6040 of file gnunet-service-transport.c.

6041{
6042 struct PilsAddressSignContext *pc = cls;
6043
6044 pc->ale->sc = NULL;
6045 if (GNUNET_YES != success)
6047 "Failed to store our own address `%s' in peerstore!\n",
6048 pc->ale->address);
6049 else
6051 "Successfully stored our own address `%s' in peerstore!\n",
6052 pc->ale->address);
6053 /* refresh period is 1/4 of expiration time, that should be plenty
6054 without being excessive. */
6055 if (NULL == pc->ale->st)
6056 {
6057 pc->ale->st =
6059 GNUNET_TIME_relative_divide (pc->ale->expiration,
6060 4ULL),
6061 &store_pi,
6062 pc->ale);
6063 }
6064
6065 /* Now we have to update our HELLO! */
6067 pc->req = GNUNET_new (struct PilsRequest);
6070 pc->req);
6071 pc->req->op = GNUNET_PILS_sign_hello (pils,
6073 pc->et,
6075 pc);
6076}

References GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_HELLO_ADDRESS_EXPIRATION, GNUNET_log, GNUNET_new, GNUNET_PILS_sign_hello(), GNUNET_SCHEDULER_add_delayed(), GNUNET_TIME_relative_divide(), GNUNET_TIME_relative_to_absolute(), GNUNET_YES, GST_my_hello, pc, pils, pils_requests_head, pils_requests_tail, pils_sign_hello_cb(), and store_pi().

Referenced by pils_sign_addr_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pils_sign_addr_cb()

static void pils_sign_addr_cb ( void *  cls,
const struct GNUNET_PeerIdentity pid,
const struct GNUNET_CRYPTO_EddsaSignature sig 
)
static

Definition at line 6081 of file gnunet-service-transport.c.

6084{
6085 struct PilsAddressSignContext *pc = cls;
6086 char *sig_str;
6087 void *result;
6088 size_t result_size;
6089
6090 pc->req->op = NULL;
6093 pc->req);
6094 GNUNET_free (pc->req);
6095 sig_str = NULL;
6096 (void) GNUNET_STRINGS_base64_encode (sig, sizeof(*sig), &sig_str);
6097 result_size =
6098 1 + GNUNET_asprintf (
6099 (char **) &result,
6100 "%s;%llu;%u;%s",
6101 sig_str,
6102 (unsigned long long) pc->et.abs_value_us,
6103 (unsigned int) pc->ale->nt,
6104 pc->ale->address);
6105 GNUNET_free (sig_str);
6106
6108 "Build our HELLO URI `%s'\n",
6109 (char*) result);
6110
6111 pc->ale->signed_address = result;
6112 pc->ale->signed_address_len = result_size;
6114
6115 expiration = GNUNET_TIME_relative_to_absolute (pc->ale->expiration);
6117 "transport",
6118 GST_my_identity, // FIXME
6120 result,
6121 result_size,
6122 expiration,
6125 pc);
6126}

References expiration, GNUNET_asprintf(), GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_PEERSTORE_store(), GNUNET_PEERSTORE_STOREOPTION_MULTIPLE, GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY, GNUNET_STRINGS_base64_encode(), GNUNET_TIME_relative_to_absolute(), GST_my_identity, pc, peerstore, peerstore_store_own_cb(), pils_requests_head, pils_requests_tail, and result.

Referenced by pils_sign_address().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pils_sign_address()

void pils_sign_address ( struct AddressListEntry ale,
struct GNUNET_TIME_Absolute  mono_time 
)

Build address record by signing raw information with private key of the peer identity.

Parameters
handlehandle to the PILS service
addresstext address at communicator to sign
ntnetwork type of address
mono_timemonotonic time at which address was valid
cbcallback called once the signature is ready
cb_clsclosure to the cb callback
Returns
handle to the operation, NULL on error

Definition at line 6165 of file gnunet-service-transport.c.

6168{
6169 struct SignedAddress sa;
6170 struct PilsAddressSignContext *pc;
6171
6172 sa.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS);
6173 sa.purpose.size = htonl (sizeof(sa));
6174 sa.mono_time = GNUNET_TIME_absolute_hton (mono_time);
6175 GNUNET_CRYPTO_hash (ale->address, strlen (ale->address), &sa.addr_hash);
6177 pc->ale = ale;
6178 pc->et = mono_time;
6179 pc->req = GNUNET_new (struct PilsRequest);
6181 &sa.purpose,
6183 pc);
6186 pc->req);
6187}

References AddressListEntry::address, PilsAddressSignContext::ale, GNUNET_CONTAINER_DLL_insert, GNUNET_CRYPTO_hash(), GNUNET_new, GNUNET_PILS_sign_by_peer_identity(), GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS, GNUNET_TIME_absolute_hton(), SignedAddress::mono_time, pc, pils, pils_requests_head, pils_requests_tail, pils_sign_addr_cb(), GNUNET_CRYPTO_EccSignaturePurpose::purpose, SignedAddress::purpose, and GNUNET_CRYPTO_EccSignaturePurpose::size.

Referenced by store_pi().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_address_entry()

static struct AddressListEntry * create_address_entry ( struct TransportClient tc,
struct GNUNET_TIME_Relative  expiration,
enum GNUNET_NetworkType  nt,
const char *  address,
uint32_t  aid,
size_t  slen 
)
static

Definition at line 6252 of file gnunet-service-transport.c.

6258{
6259 struct AddressListEntry *ale;
6260 char *address_without_port;
6261
6262 ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
6263 ale->tc = tc;
6264 ale->address = (const char *) &ale[1];
6265 ale->expiration = expiration;
6266 ale->aid = aid;
6267 ale->nt = nt;
6268 memcpy (&ale[1], address, slen);
6269 address_without_port = get_address_without_port (ale->address);
6271 "Is this %s a local address (%s)\n",
6272 address_without_port,
6273 ale->address);
6274 if (0 != strcmp ("127.0.0.1", address_without_port))
6275 {
6276 if (NULL != ale->st)
6277 {
6279 }
6280 ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
6281 }
6282 GNUNET_free (address_without_port);
6283
6284 return ale;
6285}

References address, AddressListEntry::address, AddressListEntry::aid, expiration, AddressListEntry::expiration, get_address_without_port(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_malloc, GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_cancel(), nt, AddressListEntry::nt, AddressListEntry::st, store_pi(), tc, and AddressListEntry::tc.

Referenced by handle_add_address().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ feed_addresses_to_pils()

static void feed_addresses_to_pils ( void *  cls)
static

Definition at line 6289 of file gnunet-service-transport.c.

6290{
6291
6293 "Feeding addresses to PILS\n");
6294 pils_feed_task = NULL;
6295
6297 GST_my_hello);
6298}

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_PILS_feed_addresses(), GST_my_hello, pils, and pils_feed_task.

Referenced by handle_add_address(), and handle_del_address().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_add_address()

static void handle_add_address ( void *  cls,
const struct GNUNET_TRANSPORT_AddAddressMessage aam 
)
static

Address of our peer added.

Process the request.

Parameters
clsthe client
aamthe send message that was sent

Definition at line 6308 of file gnunet-service-transport.c.

6310{
6311 struct TransportClient *tc = cls;
6312 struct AddressListEntry *ale;
6313 size_t slen;
6314 char *address;
6315
6316 /* 0-termination of &aam[1] was checked in #check_add_address */
6318 "Communicator added address `%s'!\n",
6319 (const char *) &aam[1]);
6320 slen = ntohs (aam->header.size) - sizeof(*aam);
6321 address = GNUNET_malloc (slen);
6322 memcpy (address, &aam[1], slen);
6323 ale = create_address_entry (tc,
6325 ntohl (aam->nt),
6326 address,
6327 aam->aid,
6328 slen);
6329 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
6330 tc->details.communicator.addr_tail,
6331 ale);
6332 {
6333 for (struct AddressListEntry *iter = tc->details.communicator.addr_head;
6334 (NULL != iter && NULL != iter->next);
6335 iter = iter->next)
6336 {
6337 char *address_uri;
6338 char *dash = strchr (ale->address, '-');
6340 GNUNET_assert (NULL != dash);
6341 dash++;
6342 GNUNET_asprintf (&address_uri,
6343 "%s://%s",
6344 prefix,
6345 dash);
6348 GNUNET_free (address_uri);
6349 }
6350 if (NULL != pils_feed_task)
6354 NULL);
6355 }
6358}

References address, AddressListEntry::address, GNUNET_TRANSPORT_AddAddressMessage::aid, create_address_entry(), GNUNET_TRANSPORT_AddAddressMessage::expiration, feed_addresses_to_pils(), GNUNET_asprintf(), GNUNET_assert, GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_HELLO_address_to_prefix(), GNUNET_HELLO_builder_add_address(), GNUNET_log, GNUNET_malloc, GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_cancel(), GNUNET_SERVICE_client_continue(), GNUNET_TIME_relative_ntoh(), GST_my_hello, GNUNET_TRANSPORT_AddAddressMessage::header, GNUNET_TRANSPORT_AddAddressMessage::nt, PILS_FEED_ADDRESSES_DELAY, pils_feed_task, prefix, GNUNET_MessageHeader::size, and tc.

Here is the call graph for this function:

◆ handle_del_address()

static void handle_del_address ( void *  cls,
const struct GNUNET_TRANSPORT_DelAddressMessage dam 
)
static

Address of our peer deleted.

Process the request.

Parameters
clsthe client
damthe send message that was sent

Definition at line 6368 of file gnunet-service-transport.c.

6370{
6371 struct TransportClient *tc = cls;
6372 struct AddressListEntry *alen;
6373
6374 if (CT_COMMUNICATOR != tc->type)
6375 {
6376 GNUNET_break (0);
6378 return;
6379 }
6380 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
6381 NULL != ale;
6382 ale = alen)
6383 {
6384 alen = ale->next;
6385 if (dam->aid != ale->aid)
6386 continue;
6387 GNUNET_assert (ale->tc == tc);
6389 "Communicator deleted address `%s'!\n",
6390 ale->address);
6392 ale->address);
6393 if (NULL != pils_feed_task)
6397 NULL);
6400 return;
6401 }
6403 "Communicator removed address we did not even have.\n");
6405 // GNUNET_SERVICE_client_drop (tc->client);
6406}

References GNUNET_TRANSPORT_DelAddressMessage::aid, CT_COMMUNICATOR, feed_addresses_to_pils(), free_address_list_entry(), GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_HELLO_builder_del_address(), GNUNET_log, GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_cancel(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GST_my_hello, AddressListEntry::next, PILS_FEED_ADDRESSES_DELAY, pils_feed_task, and tc.

Here is the call graph for this function:

◆ demultiplex_with_cmc()

static void demultiplex_with_cmc ( struct CommunicatorMessageContext cmc)
static

Given an inbound message msg from a communicator cmc, demultiplex it based on the type calling the right handler.

Parameters
cmccontext for demultiplexing
msgmessage to demultiplex

Definition at line 10586 of file gnunet-service-transport.c.

10587{
10589 { GNUNET_MQ_hd_var_size (fragment_box,
10592 cmc),
10593 GNUNET_MQ_hd_var_size (reliability_box,
10596 cmc),
10597 GNUNET_MQ_hd_var_size (reliability_ack,
10600 cmc),
10601 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
10604 cmc),
10605 GNUNET_MQ_hd_var_size (dv_learn,
10608 cmc),
10609 GNUNET_MQ_hd_var_size (dv_box,
10611 struct TransportDVBoxMessage,
10612 cmc),
10613 GNUNET_MQ_hd_var_size (flow_control,
10616 cmc),
10618 validation_challenge,
10621 cmc),
10623 validation_response,
10626 cmc),
10628 int ret;
10629 const struct GNUNET_MessageHeader *msg = cmc->mh;
10630
10632 "Handling message of type %u with %u bytes\n",
10633 (unsigned int) ntohs (msg->type),
10634 (unsigned int) ntohs (msg->size));
10636 if (GNUNET_SYSERR == ret)
10637 {
10638 GNUNET_break (0);
10640 GNUNET_free (cmc);
10641 return;
10642 }
10643 if (GNUNET_NO == ret)
10644 {
10645 /* unencapsulated 'raw' message */
10646 handle_raw_message (cmc, msg);
10647 }
10648}

References TransportClient::client, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE, GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE, GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION, GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX, GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN, GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL, GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT, GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK, GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX, GNUNET_MQ_handle_message(), GNUNET_MQ_handler_end, GNUNET_MQ_hd_fixed_size, GNUNET_MQ_hd_var_size, GNUNET_NO, GNUNET_SERVICE_client_drop(), GNUNET_SYSERR, handle_raw_message(), handlers, CommunicatorMessageContext::mh, msg, ret, GNUNET_MessageHeader::size, CommunicatorMessageContext::tc, and GNUNET_MessageHeader::type.

Referenced by backtalker_monotime_cb(), decaps_dv_box_cb(), handle_fragment_box(), handle_incoming_msg(), and handle_reliability_box().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ core_env_sent_cb()

static void core_env_sent_cb ( void *  cls)
static

Function called when we are done giving a message of a certain size to CORE and should thus decrement the number of bytes of RAM reserved for that peer's MQ.

Parameters
clsa struct CoreSentContext

Definition at line 6428 of file gnunet-service-transport.c.

6429{
6430 struct CoreSentContext *ctx = cls;
6431 struct VirtualLink *vl = ctx->vl;
6432
6433 if (NULL == vl)
6434 {
6435 /* lost the link in the meantime, ignore */
6436 GNUNET_free (ctx);
6437 return;
6438 }
6441 vl->incoming_fc_window_size_ram -= ctx->size;
6442 vl->incoming_fc_window_size_used += ctx->isize;
6444 GNUNET_free (ctx);
6445}

References consider_sending_fc(), VirtualLink::csc_head, VirtualLink::csc_tail, ctx, GNUNET_assert, GNUNET_CONTAINER_DLL_remove, GNUNET_free, VirtualLink::incoming_fc_window_size_ram, and VirtualLink::incoming_fc_window_size_used.

Referenced by finish_handling_raw_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ finish_handling_raw_message()

static void finish_handling_raw_message ( struct VirtualLink vl,
const struct GNUNET_MessageHeader mh,
struct CommunicatorMessageContext cmc,
unsigned int  free_cmc 
)
static

Definition at line 6449 of file gnunet-service-transport.c.

6453{
6454 uint16_t size = ntohs (mh->size);
6455 int have_core;
6456
6457 if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
6458 {
6460 "# CORE messages dropped (FC arithmetic overflow)",
6461 1,
6462 GNUNET_NO);
6464 "CORE messages of type %u with %u bytes dropped (FC arithmetic overflow)\n",
6465 (unsigned int) ntohs (mh->type),
6466 (unsigned int) ntohs (mh->size));
6467 if (GNUNET_YES == free_cmc)
6469 return;
6470 }
6472 {
6474 "# CORE messages dropped (FC window overflow)",
6475 1,
6476 GNUNET_NO);
6478 "CORE messages of type %u with %u bytes dropped (FC window overflow)\n",
6479 (unsigned int) ntohs (mh->type),
6480 (unsigned int) ntohs (mh->size));
6481 if (GNUNET_YES == free_cmc)
6483 return;
6484 }
6485
6486 /* Forward to all CORE clients */
6487 have_core = GNUNET_NO;
6488 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
6489 {
6490 struct GNUNET_MQ_Envelope *env;
6491 struct InboundMessage *im;
6492 struct CoreSentContext *ctx;
6493
6494 if (CT_CORE != tc->type)
6495 continue;
6498 ctx = GNUNET_new (struct CoreSentContext);
6499 ctx->vl = vl;
6500 ctx->size = size;
6501 ctx->isize = (GNUNET_NO == have_core) ? size : 0;
6502 have_core = GNUNET_YES;
6505 im->peer = cmc->im.sender;
6506 memcpy (&im[1], mh, size);
6507 GNUNET_MQ_send (tc->mq, env);
6509 }
6510 if (GNUNET_NO == have_core)
6511 {
6513 "Dropped message to CORE: no CORE client connected!\n");
6514 /* Nevertheless, count window as used, as it is from the
6515 perspective of the other peer! */
6517 /* TODO-M1 */
6519 "Dropped message of type %u with %u bytes to CORE: no CORE client connected!\n",
6520 (unsigned int) ntohs (mh->type),
6521 (unsigned int) ntohs (mh->size));
6522 if (GNUNET_YES == free_cmc)
6524 return;
6525 }
6527 "Delivered message from %s of type %u to CORE recv window %d\n",
6528 GNUNET_i2s (&cmc->im.sender),
6529 ntohs (mh->type),
6531 if (vl->core_recv_window > 0)
6532 {
6533 if (GNUNET_YES == free_cmc)
6535 return;
6536 }
6537 /* Wait with calling #finish_cmc_handling(cmc) until the message
6538 was processed by CORE MQs (for CORE flow control)! */
6539 if (GNUNET_YES == free_cmc)
6541}

References VirtualLink::available_fc_window_size, clients_head, VirtualLink::cmc_head, VirtualLink::cmc_tail, core_env_sent_cb(), VirtualLink::core_recv_window, VirtualLink::csc_head, VirtualLink::csc_tail, CT_CORE, ctx, env, finish_cmc_handling_with_continue(), GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_i2s(), GNUNET_log, GNUNET_MESSAGE_TYPE_TRANSPORT_RECV, GNUNET_MQ_msg_extra, GNUNET_MQ_notify_sent(), GNUNET_MQ_send(), GNUNET_new, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_YES, GST_stats, CommunicatorMessageContext::im, VirtualLink::incoming_fc_window_size_ram, VirtualLink::incoming_fc_window_size_used, mh, InboundMessage::peer, GNUNET_TRANSPORT_IncomingMessage::sender, size, tc, and CoreSentContext::vl.

Referenced by handle_raw_message(), and send_msg_from_cache().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_raw_message()

static void handle_raw_message ( void *  cls,
const struct GNUNET_MessageHeader mh 
)
static

Communicator gave us an unencapsulated message to pass as-is to CORE.

Process the request.

Parameters
clsa struct CommunicatorMessageContext (must call finish_cmc_handling() when done)
mhthe message that was received

Definition at line 6553 of file gnunet-service-transport.c.

6554{
6555 struct CommunicatorMessageContext *cmc = cls;
6556 // struct CommunicatorMessageContext *cmc_copy =
6557 // GNUNET_new (struct CommunicatorMessageContext);
6558 struct GNUNET_MessageHeader *mh_copy;
6559 struct RingBufferEntry *rbe;
6560 struct VirtualLink *vl;
6561 uint16_t size = ntohs (mh->size);
6562
6564 "Handling raw message of type %u with %u bytes\n",
6565 (unsigned int) ntohs (mh->type),
6566 (unsigned int) ntohs (mh->size));
6567
6568 if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
6569 (size < sizeof(struct GNUNET_MessageHeader)))
6570 {
6571 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6572
6573 GNUNET_break (0);
6574 finish_cmc_handling (cmc);
6576 return;
6577 }
6578 vl = lookup_virtual_link (&cmc->im.sender);
6579 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6580 {
6581 /* FIXME: sender is giving us messages for CORE but we don't have
6582 the link up yet! I *suspect* this can happen right now (i.e.
6583 sender has verified us, but we didn't verify sender), but if
6584 we pass this on, CORE would be confused (link down, messages
6585 arrive). We should investigate more if this happens often,
6586 or in a persistent manner, and possibly do "something" about
6587 it. Thus logging as error for now. */
6588
6589 mh_copy = GNUNET_malloc (size);
6590 rbe = GNUNET_new (struct RingBufferEntry);
6591 rbe->cmc = cmc;
6592 /*cmc_copy->tc = cmc->tc;
6593 cmc_copy->im = cmc->im;*/
6594 GNUNET_memcpy (mh_copy, mh, size);
6595
6596 rbe->mh = mh_copy;
6597
6599 {
6600 struct RingBufferEntry *rbe_old = ring_buffer[ring_buffer_head];
6601 GNUNET_free (rbe_old->cmc);
6602 GNUNET_free (rbe_old->mh);
6603 GNUNET_free (rbe_old);
6604 }
6605 ring_buffer[ring_buffer_head] = rbe;// cmc_copy;
6606 // cmc_copy->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6607 cmc->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6609 "Storing message for %s and type %u (%u) in ring buffer head %u is full %u\n",
6610 GNUNET_i2s (&cmc->im.sender),
6611 (unsigned int) ntohs (mh->type),
6612 (unsigned int) ntohs (mh_copy->type),
6616 {
6617 ring_buffer_head = 0;
6619 }
6620 else
6622
6624 "%u items stored in ring buffer\n",
6627
6628 /*GNUNET_break_op (0);
6629 GNUNET_STATISTICS_update (GST_stats,
6630 "# CORE messages dropped (virtual link still down)",
6631 1,
6632 GNUNET_NO);
6633
6634 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6635 "CORE messages of type %u with %u bytes dropped (virtual link still down)\n",
6636 (unsigned int) ntohs (mh->type),
6637 (unsigned int) ntohs (mh->size));
6638 finish_cmc_handling (cmc);*/
6641 // GNUNET_free (cmc);
6642 return;
6643 }
6645}

References TransportClient::client, RingBufferEntry::cmc, VirtualLink::confirmed, CommunicatorMessageContext::continue_send, finish_cmc_handling(), finish_cmc_handling_with_continue(), finish_handling_raw_message(), GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_malloc, GNUNET_memcpy, GNUNET_new, GNUNET_NO, GNUNET_SERVICE_client_drop(), GNUNET_YES, CommunicatorMessageContext::im, is_ring_buffer_full, lookup_virtual_link(), mh, CommunicatorMessageContext::mh, RingBufferEntry::mh, ring_buffer, ring_buffer_head, RING_BUFFER_SIZE, GNUNET_TRANSPORT_IncomingMessage::sender, size, CommunicatorMessageContext::tc, and GNUNET_MessageHeader::type.

Referenced by demultiplex_with_cmc().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_fragment_box()

static int check_fragment_box ( void *  cls,
const struct TransportFragmentBoxMessage fb 
)
static

Communicator gave us a fragment box.

Check the message.

Parameters
clsa struct CommunicatorMessageContext
fbthe send message that was sent
Returns
GNUNET_YES if message is well-formed

Definition at line 6656 of file gnunet-service-transport.c.

6657{
6658 uint16_t size = ntohs (fb->header.size);
6659 uint16_t bsize = size - sizeof(*fb);
6660
6661 (void) cls;
6662 if (0 == bsize)
6663 {
6664 GNUNET_break_op (0);
6665 return GNUNET_SYSERR;
6666 }
6667 if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
6668 {
6669 GNUNET_break_op (0);
6670 return GNUNET_SYSERR;
6671 }
6672 if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
6673 {
6674 GNUNET_break_op (0);
6675 return GNUNET_SYSERR;
6676 }
6677 return GNUNET_YES;
6678}

References bsize, TransportFragmentBoxMessage::frag_off, GNUNET_break_op, GNUNET_SYSERR, GNUNET_YES, TransportFragmentBoxMessage::header, TransportFragmentBoxMessage::msg_size, GNUNET_MessageHeader::size, and size.

◆ destroy_ack_cummulator()

static void destroy_ack_cummulator ( void *  cls)
static

Clean up an idle cumulative acknowledgement data structure.

Parameters
clsa struct AcknowledgementCummulator *

Definition at line 6687 of file gnunet-service-transport.c.

6688{
6689 struct AcknowledgementCummulator *ac = cls;
6690
6691 ac->task = NULL;
6692 GNUNET_assert (0 == ac->num_acks);
6694 GNUNET_YES ==
6696 GNUNET_free (ac);
6697}

References ack_cummulators, GNUNET_assert, GNUNET_CONTAINER_multipeermap_remove(), GNUNET_free, GNUNET_YES, AcknowledgementCummulator::num_acks, AcknowledgementCummulator::target, and AcknowledgementCummulator::task.

Referenced by transmit_cummulative_ack_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ transmit_cummulative_ack_cb()

static void transmit_cummulative_ack_cb ( void *  cls)
static

Do the transmission of a cumulative acknowledgement now.

Parameters
clsa struct AcknowledgementCummulator *

Definition at line 6706 of file gnunet-service-transport.c.

6707{
6708 struct Neighbour *n;
6709 struct VirtualLink *vl;
6710 struct AcknowledgementCummulator *ac = cls;
6711 char buf[sizeof(struct TransportReliabilityAckMessage)
6712 + ac->num_acks
6714 struct TransportReliabilityAckMessage *ack =
6715 (struct TransportReliabilityAckMessage *) buf;
6717
6718 ac->task = NULL;
6720 "Sending ACK with %u components to %s\n",
6721 ac->num_acks,
6722 GNUNET_i2s (&ac->target));
6723 GNUNET_assert (0 < ac->num_acks);
6725 ack->header.size =
6726 htons (sizeof(*ack)
6727 + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP));
6728 ack->ack_counter = htonl (ac->ack_counter += ac->num_acks);
6729 ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
6730 for (unsigned int i = 0; i < ac->num_acks; i++)
6731 {
6732 ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
6735 }
6736 /*route_control_message_without_fc (
6737 &ac->target,
6738 &ack->header,
6739 RMO_DV_ALLOWED);*/
6740 vl = lookup_virtual_link (&ac->target);
6741 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
6742 {
6744 vl,
6745 &ack->header,
6747 }
6748 else
6749 {
6750 /* Use route via neighbour */
6751 n = lookup_neighbour (&ac->target);
6752 if (NULL != n)
6754 n,
6755 &ack->header,
6756 RMO_NONE);
6757 }
6758 ac->num_acks = 0;
6761 ac);
6762}

References TransportReliabilityAckMessage::ack_counter, AcknowledgementCummulator::ack_counter, ACK_CUMMULATOR_TIMEOUT, TransportCummulativeAckPayloadP::ack_delay, TransportCummulativeAckPayloadP::ack_uuid, TransportCummulativeAckPayload::ack_uuid, AcknowledgementCummulator::ack_uuids, VirtualLink::confirmed, destroy_ack_cummulator(), GNUNET_ALIGN, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK, GNUNET_SCHEDULER_add_delayed(), GNUNET_TIME_absolute_get_duration(), GNUNET_TIME_relative_hton(), GNUNET_YES, TransportReliabilityAckMessage::header, lookup_neighbour(), lookup_virtual_link(), AcknowledgementCummulator::num_acks, TransportCummulativeAckPayload::receive_time, RMO_DV_ALLOWED, RMO_NONE, route_control_message_without_fc(), route_via_neighbour(), GNUNET_MessageHeader::size, AcknowledgementCummulator::target, AcknowledgementCummulator::task, and GNUNET_MessageHeader::type.

Referenced by cummulative_ack().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cummulative_ack()

static void cummulative_ack ( const struct GNUNET_PeerIdentity pid,
const struct AcknowledgementUUIDP ack_uuid,
struct GNUNET_TIME_Absolute  max_delay 
)
static

Transmit an acknowledgement for ack_uuid to pid delaying transmission by at most ack_delay.

Parameters
pidtarget peer
ack_uuidUUID to ack
max_delayhow long can the ACK wait

Definition at line 6774 of file gnunet-service-transport.c.

6777{
6778 struct AcknowledgementCummulator *ac;
6779
6781 "Scheduling ACK %s for transmission to %s\n",
6782 GNUNET_uuid2s (&ack_uuid->value),
6783 GNUNET_i2s (pid));
6785 if (NULL == ac)
6786 {
6788 ac->target = *pid;
6789 ac->min_transmission_time = max_delay;
6793 &ac->target,
6794 ac,
6796 }
6797 else
6798 {
6799 if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
6800 {
6801 /* must run immediately, ack buffer full! */
6803 }
6807 }
6810 ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
6811 ac->num_acks++;
6814 ac);
6815}

References ack_cummulators, TransportCummulativeAckPayload::ack_uuid, AcknowledgementCummulator::ack_uuids, GNUNET_assert, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multipeermap_get(), GNUNET_CONTAINER_multipeermap_put(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_new, GNUNET_SCHEDULER_add_at(), GNUNET_SCHEDULER_cancel(), GNUNET_TIME_absolute_get(), GNUNET_TIME_absolute_min(), GNUNET_uuid2s(), GNUNET_YES, MAX_CUMMULATIVE_ACKS, AcknowledgementCummulator::min_transmission_time, AcknowledgementCummulator::num_acks, pid, TransportCummulativeAckPayload::receive_time, AcknowledgementCummulator::target, AcknowledgementCummulator::task, transmit_cummulative_ack_cb(), and AcknowledgementUUIDP::value.

Referenced by handle_fragment_box(), and handle_reliability_box().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_by_message_uuid()

static int find_by_message_uuid ( void *  cls,
uint32_t  key,
void *  value 
)
static

Iterator called to find a reassembly context by the message UUID in the multihashmap32.

Parameters
clsa struct FindByMessageUuidContext
keya key (unused)
valuea struct ReassemblyContext
Returns
GNUNET_YES if not found, GNUNET_NO if found

Definition at line 6845 of file gnunet-service-transport.c.

6846{
6847 struct FindByMessageUuidContext *fc = cls;
6848 struct ReassemblyContext *rc = value;
6849
6850 (void) key;
6851 if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
6852 {
6853 fc->rc = rc;
6854 return GNUNET_NO;
6855 }
6856 return GNUNET_YES;
6857}

References GNUNET_memcmp, GNUNET_NO, GNUNET_YES, key, FindByMessageUuidContext::message_uuid, ReassemblyContext::msg_uuid, FindByMessageUuidContext::rc, and value.

Referenced by handle_fragment_box().

Here is the caller graph for this function:

◆ handle_fragment_box()

static void handle_fragment_box ( void *  cls,
const struct TransportFragmentBoxMessage fb 
)
static

Communicator gave us a fragment.

Process the request.

Parameters
clsa struct CommunicatorMessageContext (must call finish_cmc_handling() when done)
fbthe message that was received

Definition at line 6868 of file gnunet-service-transport.c.

6869{
6870 struct CommunicatorMessageContext *cmc = cls;
6871 struct VirtualLink *vl;
6872 struct ReassemblyContext *rc;
6873 const struct GNUNET_MessageHeader *msg;
6874 uint16_t msize;
6875 uint16_t fsize;
6876 uint16_t frag_off;
6877 char *target;
6878 struct GNUNET_TIME_Relative cdelay;
6879 struct FindByMessageUuidContext fc;
6880
6881 vl = lookup_virtual_link (&cmc->im.sender);
6882 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6883 {
6884 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6885
6887 "No virtual link for %s to handle fragment\n",
6888 GNUNET_i2s (&cmc->im.sender));
6889 GNUNET_break (0);
6890 finish_cmc_handling (cmc);
6892 return;
6893 }
6894 if (NULL == vl->reassembly_map)
6895 {
6897 vl->reassembly_heap =
6902 vl);
6903 }
6904 msize = ntohs (fb->msg_size);
6905 fc.message_uuid = fb->msg_uuid;
6906 fc.rc = NULL;
6908 fb->msg_uuid.uuid,
6910 &fc);
6911 fsize = ntohs (fb->header.size) - sizeof(*fb);
6912 if (NULL == (rc = fc.rc))
6913 {
6914 rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */
6915 + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
6916 rc->msg_uuid = fb->msg_uuid;
6917 rc->virtual_link = vl;
6918 rc->msg_size = msize;
6919 rc->reassembly_timeout =
6923 rc,
6927 vl->reassembly_map,
6928 rc->msg_uuid.uuid,
6929 rc,
6931 target = (char *) &rc[1];
6932 rc->bitfield = (uint8_t *) (target + rc->msg_size);
6933 if (fsize != rc->msg_size)
6934 rc->msg_missing = rc->msg_size;
6935 else
6936 rc->msg_missing = 0;
6938 "Received fragment with size %u at offset %u/%u %u bytes missing from %s for NEW message %"
6939 PRIu64 "\n",
6940 fsize,
6941 ntohs (fb->frag_off),
6942 msize,
6943 rc->msg_missing,
6944 GNUNET_i2s (&cmc->im.sender),
6945 fb->msg_uuid.uuid);
6946 }
6947 else
6948 {
6949 target = (char *) &rc[1];
6951 "Received fragment at offset %u/%u from %s for message %u\n",
6952 ntohs (fb->frag_off),
6953 msize,
6954 GNUNET_i2s (&cmc->im.sender),
6955 (unsigned int) fb->msg_uuid.uuid);
6956 }
6957 if (msize != rc->msg_size)
6958 {
6959 GNUNET_break (0);
6960 finish_cmc_handling (cmc);
6961 return;
6962 }
6963
6964 /* reassemble */
6965 if (0 == fsize)
6966 {
6967 GNUNET_break (0);
6968 finish_cmc_handling (cmc);
6969 return;
6970 }
6971 frag_off = ntohs (fb->frag_off);
6972 if (frag_off + fsize > msize)
6973 {
6974 /* Fragment (plus fragment size) exceeds message size! */
6975 GNUNET_break_op (0);
6976 finish_cmc_handling (cmc);
6977 return;
6978 }
6979 memcpy (&target[frag_off], &fb[1], fsize);
6980 /* update bitfield and msg_missing */
6981 for (unsigned int i = frag_off; i < frag_off + fsize; i++)
6982 {
6983 if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
6984 {
6985 rc->bitfield[i / 8] |= (1 << (i % 8));
6986 rc->msg_missing--;
6987 }
6988 }
6989
6990 /* Compute cumulative ACK */
6992 cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
6993 if (0 == rc->msg_missing)
6994 cdelay = GNUNET_TIME_UNIT_ZERO;
6995 cummulative_ack (&cmc->im.sender,
6996 &fb->ack_uuid,
6999 /* is reassembly complete? */
7000 if (0 != rc->msg_missing)
7001 {
7002 finish_cmc_handling (cmc);
7003 return;
7004 }
7005 /* reassembly is complete, verify result */
7006 msg = (const struct GNUNET_MessageHeader *) &rc[1];
7007 if (ntohs (msg->size) != rc->msg_size)
7008 {
7009 GNUNET_break (0);
7011 finish_cmc_handling (cmc);
7012 return;
7013 }
7014 /* successful reassembly */
7016 "Fragment reassembly complete for message %u\n",
7017 (unsigned int) fb->msg_uuid.uuid);
7018 /* FIXME: check that the resulting msg is NOT a
7019 DV Box or Reliability Box, as that is NOT allowed! */
7020 cmc->mh = msg;
7022 /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
7023 en-route and we forget that we finished this reassembly immediately!
7024 -> keep around until timeout?
7025 -> shorten timeout based on ACK? */
7027}

References GNUNET_TIME_Absolute::abs_value_us, TransportFragmentBoxMessage::ack_uuid, ReassemblyContext::bitfield, TransportClient::client, VirtualLink::confirmed, cummulative_ack(), demultiplex_with_cmc(), find_by_message_uuid(), finish_cmc_handling(), TransportFragmentBoxMessage::frag_off, free_reassembly_context(), GNUNET_assert, GNUNET_break, GNUNET_break_op, GNUNET_CONTAINER_heap_create(), GNUNET_CONTAINER_heap_insert(), GNUNET_CONTAINER_HEAP_ORDER_MIN, GNUNET_CONTAINER_multihashmap32_create(), GNUNET_CONTAINER_multihashmap32_get_multiple(), GNUNET_CONTAINER_multihashmap32_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_malloc, GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_delayed(), GNUNET_SERVICE_client_drop(), GNUNET_TIME_absolute_get(), GNUNET_TIME_absolute_get_duration(), GNUNET_TIME_relative_multiply(), GNUNET_TIME_relative_to_absolute(), GNUNET_TIME_UNIT_ZERO, TransportFragmentBoxMessage::header, ReassemblyContext::hn, CommunicatorMessageContext::im, ReassemblyContext::last_frag, lookup_virtual_link(), FindByMessageUuidContext::message_uuid, CommunicatorMessageContext::mh, msg, ReassemblyContext::msg_missing, TransportFragmentBoxMessage::msg_size, ReassemblyContext::msg_size, TransportFragmentBoxMessage::msg_uuid, ReassemblyContext::msg_uuid, FindByMessageUuidContext::rc, reassembly_cleanup_task(), REASSEMBLY_EXPIRATION, VirtualLink::reassembly_heap, VirtualLink::reassembly_map, ReassemblyContext::reassembly_timeout, VirtualLink::reassembly_timeout_task, GNUNET_TRANSPORT_IncomingMessage::sender, GNUNET_MessageHeader::size, CommunicatorMessageContext::tc, MessageUUIDP::uuid, and ReassemblyContext::virtual_link.

Here is the call graph for this function:

◆ check_reliability_box()

static int check_reliability_box ( void *  cls,
const struct TransportReliabilityBoxMessage rb 
)
static

Communicator gave us a reliability box.

Check the message.

Parameters
clsa struct CommunicatorMessageContext
rbthe send message that was sent
Returns
GNUNET_YES if message is well-formed

Definition at line 7038 of file gnunet-service-transport.c.

7040{
7041 const struct GNUNET_MessageHeader *box = (const struct
7042 GNUNET_MessageHeader *) &rb[1];
7043 (void) cls;
7044
7046 "check_send_msg with size %u: inner msg type %u and size %u (%lu %lu)\n",
7047 ntohs (rb->header.size),
7048 ntohs (box->type),
7049 ntohs (box->size),
7050 sizeof (struct TransportReliabilityBoxMessage),
7051 sizeof (struct GNUNET_MessageHeader));
7053 return GNUNET_YES;
7054}

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MQ_check_boxed_message, GNUNET_YES, TransportReliabilityBoxMessage::header, GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

◆ handle_reliability_box()

static void handle_reliability_box ( void *  cls,
const struct TransportReliabilityBoxMessage rb 
)
static

Communicator gave us a reliability box.

Process the request.

Parameters
clsa struct CommunicatorMessageContext (must call finish_cmc_handling() when done)
rbthe message that was received

Definition at line 7065 of file gnunet-service-transport.c.

7067{
7068 struct CommunicatorMessageContext *cmc = cls;
7069 const struct GNUNET_MessageHeader *inbox =
7070 (const struct GNUNET_MessageHeader *) &rb[1];
7071 struct GNUNET_TIME_Relative rtt;
7072
7074 "Received reliability box from %s with UUID %s of type %u\n",
7075 GNUNET_i2s (&cmc->im.sender),
7077 (unsigned int) ntohs (inbox->type));
7078 rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
7079 do not really have an RTT for the
7080 * incoming* queue (should we have
7081 the sender add it to the rb message?) */
7083 &cmc->im.sender,
7084 &rb->ack_uuid,
7085 (0 == ntohl (rb->ack_countdown))
7088 GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
7089 /* continue with inner message */
7090 /* FIXME: check that inbox is NOT a DV Box, fragment or another
7091 reliability box (not allowed!) */
7092 cmc->mh = inbox;
7094}

References TransportReliabilityBoxMessage::ack_countdown, TransportReliabilityBoxMessage::ack_uuid, cummulative_ack(), demultiplex_with_cmc(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_TIME_relative_divide(), GNUNET_TIME_relative_to_absolute(), GNUNET_TIME_UNIT_SECONDS, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_uuid2s(), CommunicatorMessageContext::im, CommunicatorMessageContext::mh, GNUNET_TRANSPORT_IncomingMessage::sender, GNUNET_MessageHeader::type, and AcknowledgementUUIDP::value.

Here is the call graph for this function:

◆ update_pd_age()

static void update_pd_age ( struct PerformanceData pd,
unsigned int  age 
)
static

Check if we have advanced to another age since the last time.

If so, purge ancient statistics (more than GOODPUT_AGING_SLOTS before the current age)

Parameters
[in,out]pddata to update
agecurrent age

Definition at line 7106 of file gnunet-service-transport.c.

7107{
7108 unsigned int sage;
7109
7110 if (age == pd->last_age)
7111 return; /* nothing to do */
7112 sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
7113 for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
7114 {
7115 struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
7116
7117 the->bytes_sent = 0;
7118 the->bytes_received = 0;
7119 }
7120 pd->last_age = age;
7121}

References TransmissionHistoryEntry::bytes_received, TransmissionHistoryEntry::bytes_sent, GNUNET_MAX, GOODPUT_AGING_SLOTS, PerformanceData::last_age, and PerformanceData::the.

Referenced by update_performance_data().

Here is the caller graph for this function:

◆ update_performance_data()

static void update_performance_data ( struct PerformanceData pd,
struct GNUNET_TIME_Relative  rtt,
uint16_t  bytes_transmitted_ok 
)
static

Update pd based on the latest rtt and the number of bytes that were confirmed to be successfully transmitted.

Parameters
[in,out]pddata to update
rttlatest round-trip time
bytes_transmitted_oknumber of bytes receiver confirmed as received

Definition at line 7133 of file gnunet-service-transport.c.

7136{
7137 uint64_t nval = rtt.rel_value_us;
7138 uint64_t oval = pd->aged_rtt.rel_value_us;
7139 unsigned int age = get_age ();
7140 struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
7141
7142 if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
7143 pd->aged_rtt = rtt;
7144 else
7145 pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
7146 update_pd_age (pd, age);
7147 the->bytes_received += bytes_transmitted_ok;
7148}

References PerformanceData::aged_rtt, TransmissionHistoryEntry::bytes_received, get_age(), GNUNET_TIME_UNIT_FOREVER_REL, GOODPUT_AGING_SLOTS, GNUNET_TIME_Relative::rel_value_us, PerformanceData::the, and update_pd_age().

Referenced by update_dvh_performance(), and update_queue_performance().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_queue_performance()

static void update_queue_performance ( struct Queue q,
struct GNUNET_TIME_Relative  rtt,
uint16_t  bytes_transmitted_ok 
)
static

We have successfully transmitted data via q, update metrics.

Parameters
qqueue to update
rttround trip time observed
bytes_transmitted_oknumber of bytes successfully transmitted

Definition at line 7159 of file gnunet-service-transport.c.

7162{
7163 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
7164}

References q, and update_performance_data().

Referenced by handle_acknowledged().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_dvh_performance()

static void update_dvh_performance ( struct DistanceVectorHop dvh,
struct GNUNET_TIME_Relative  rtt,
uint16_t  bytes_transmitted_ok 
)
static

We have successfully transmitted data via dvh, update metrics.

Parameters
dvhdistance vector path data to update
rttround trip time observed
bytes_transmitted_oknumber of bytes successfully transmitted

Definition at line 7175 of file gnunet-service-transport.c.

7178{
7179 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
7180}

References DistanceVectorHop::pd, and update_performance_data().

Referenced by handle_acknowledged().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ completed_pending_message()

static void completed_pending_message ( struct PendingMessage pm)
static

We have completed transmission of pm, remove it from the transmission queues (and if it is a fragment, continue up the tree as necessary).

Parameters
pmpending message that was transmitted

Definition at line 7191 of file gnunet-service-transport.c.

7192{
7193 struct PendingMessage *pos;
7194
7196 "Complete transmission of message %" PRIu64 " %u\n",
7197 pm->logging_uuid,
7198 pm->pmt);
7199 switch (pm->pmt)
7200 {
7201 case PMT_CORE:
7203 /* Full message sent, we are done */
7205 return;
7206
7207 case PMT_FRAGMENT_BOX:
7208 /* Fragment sent over reliable channel */
7209 pos = pm->frag_parent;
7213 "pos frag_off %lu pos bytes_msg %lu pmt %u parent %u\n",
7214 (unsigned long) pos->frag_off,
7215 (unsigned long) pos->bytes_msg,
7216 pos->pmt,
7217 NULL == pos->frag_parent ? 1 : 0);
7218 /* check if subtree is done */
7219 while ((NULL == pos->head_frag) && (pos->frag_off == (pos->bytes_msg
7220 - sizeof(struct
7222 &&
7223 (NULL != pos->frag_parent))
7224 {
7225 pm = pos;
7226 pos = pm->frag_parent;
7227 if ((NULL == pos) && (PMT_DV_BOX == pm->pmt))
7228 {
7230 return;
7231 }
7232 else if (PMT_DV_BOX == pm->pmt)
7233 {
7235 return;
7236 }
7239 }
7240
7241 /* Was this the last applicable fragment? */
7242 if ((NULL == pos->head_frag) && (NULL == pos->frag_parent || PMT_DV_BOX ==
7243 pos->pmt) &&
7244 (pos->frag_off == pos->bytes_msg))
7246 return;
7247
7248 case PMT_DV_BOX:
7250 "Completed transmission of message %" PRIu64 " (DV Box)\n",
7251 pm->logging_uuid);
7252 if (NULL != pm->frag_parent)
7253 {
7254 pos = pm->frag_parent;
7256 pos->bpm = NULL;
7258 }
7259 else
7261 return;
7262 }
7263}

References PendingMessage::bpm, PendingMessage::bytes_msg, client_send_response(), PendingMessage::frag_off, PendingMessage::frag_parent, free_pending_message(), GNUNET_CONTAINER_MDLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, PendingMessage::head_frag, pm, PendingMessage::pmt, PMT_CORE, PMT_DV_BOX, PMT_FRAGMENT_BOX, PMT_RELIABILITY_BOX, and PendingMessage::tail_frag.

Referenced by handle_acknowledged(), and transmit_on_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_acknowledged()

static void handle_acknowledged ( struct PendingAcknowledgement pa,
struct GNUNET_TIME_Relative  ack_delay 
)
static

The pa was acknowledged, process the acknowledgement.

Parameters
pathe pending acknowledgement that was satisfied
ack_delayartificial delay from cumulative acks created by the other peer

Definition at line 7274 of file gnunet-service-transport.c.

7276{
7277 struct GNUNET_TIME_Relative delay;
7278
7280 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
7281 if (NULL != pa->queue && 1 == pa->num_send)
7283 if (NULL != pa->dvh && 1 == pa->num_send)
7284 update_dvh_performance (pa->dvh, delay, pa->message_size);
7285 if (NULL != pa->pm)
7288}

References completed_pending_message(), PendingAcknowledgement::dvh, free_pending_acknowledgement(), GNUNET_TIME_absolute_get_duration(), GNUNET_TIME_relative_subtract(), PendingAcknowledgement::message_size, PendingAcknowledgement::num_send, PendingAcknowledgement::pm, PendingAcknowledgement::queue, PendingAcknowledgement::transmission_time, update_dvh_performance(), and update_queue_performance().

Referenced by handle_reliability_ack().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_reliability_ack()

static int check_reliability_ack ( void *  cls,
const struct TransportReliabilityAckMessage ra 
)
static

Communicator gave us a reliability ack.

Check it is well-formed.

Parameters
clsa struct CommunicatorMessageContext (unused)
rathe message that was received
Returns
#GNUNET_Ok if ra is well-formed

Definition at line 7299 of file gnunet-service-transport.c.

7301{
7302 unsigned int n_acks;
7303
7304 (void) cls;
7305 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7306 / sizeof(struct TransportCummulativeAckPayloadP);
7307 if (0 == n_acks)
7308 {
7309 GNUNET_break_op (0);
7310 return GNUNET_SYSERR;
7311 }
7312 if ((ntohs (ra->header.size) - sizeof(*ra)) !=
7313 n_acks * sizeof(struct TransportCummulativeAckPayloadP))
7314 {
7315 GNUNET_break_op (0);
7316 return GNUNET_SYSERR;
7317 }
7318 return GNUNET_OK;
7319}

References GNUNET_break_op, GNUNET_OK, GNUNET_SYSERR, TransportReliabilityAckMessage::header, and GNUNET_MessageHeader::size.

◆ handle_reliability_ack()

static void handle_reliability_ack ( void *  cls,
const struct TransportReliabilityAckMessage ra 
)
static

Communicator gave us a reliability ack.

Process the request.

Parameters
clsa struct CommunicatorMessageContext (must call finish_cmc_handling() when done)
rathe message that was received

Definition at line 7330 of file gnunet-service-transport.c.

7332{
7333 struct CommunicatorMessageContext *cmc = cls;
7334 const struct TransportCummulativeAckPayloadP *ack;
7335 unsigned int n_acks;
7336 uint32_t ack_counter;
7337
7338 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7339 / sizeof(struct TransportCummulativeAckPayloadP);
7340 ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
7341 for (unsigned int i = 0; i < n_acks; i++)
7342 {
7343 struct PendingAcknowledgement *pa =
7345 if (NULL == pa)
7346 {
7348 "Received ACK from %s with UUID %s which is unknown to us!\n",
7349 GNUNET_i2s (&cmc->im.sender),
7350 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7352 GST_stats,
7353 "# FRAGMENT_ACKS dropped, no matching pending message",
7354 1,
7355 GNUNET_NO);
7356 continue;
7357 }
7359 "Received ACK from %s with UUID %s\n",
7360 GNUNET_i2s (&cmc->im.sender),
7361 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7362 handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
7363 }
7364
7365 ack_counter = htonl (ra->ack_counter);
7366 (void) ack_counter; /* silence compiler warning for now */
7367 // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
7368 // (DV and/or Neighbour?)
7369 finish_cmc_handling (cmc);
7370}

References TransportReliabilityAckMessage::ack_counter, PendingAcknowledgement::ack_uuid, finish_cmc_handling(), GNUNET_CONTAINER_multiuuidmap_get(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_TIME_relative_ntoh(), GNUNET_uuid2s(), GST_stats, handle_acknowledged(), TransportReliabilityAckMessage::header, CommunicatorMessageContext::im, pending_acks, GNUNET_TRANSPORT_IncomingMessage::sender, GNUNET_MessageHeader::size, and AcknowledgementUUIDP::value.

Here is the call graph for this function:

◆ check_backchannel_encapsulation()

static int check_backchannel_encapsulation ( void *  cls,
const struct TransportBackchannelEncapsulationMessage be 
)
static

Communicator gave us a backchannel encapsulation.

Check the message.

Parameters
clsa struct CommunicatorMessageContext
bethe send message that was sent
Returns
GNUNET_YES if message is well-formed

Definition at line 7381 of file gnunet-service-transport.c.

7384{
7385 uint16_t size = ntohs (be->header.size) - sizeof(*be);
7386 const struct GNUNET_MessageHeader *inbox =
7387 (const struct GNUNET_MessageHeader *) &be[1];
7388 const char *is;
7389 uint16_t isize;
7390
7391 (void) cls;
7392 if (ntohs (inbox->size) >= size)
7393 {
7394 GNUNET_break_op (0);
7395 return GNUNET_SYSERR;
7396 }
7397 isize = ntohs (inbox->size);
7398 is = ((const char *) inbox) + isize;
7399 size -= isize;
7400 if ('\0' != is[size - 1])
7401 {
7402 GNUNET_break_op (0);
7403 return GNUNET_SYSERR;
7404 }
7405 return GNUNET_YES;
7406}

References GNUNET_break_op, GNUNET_SYSERR, GNUNET_YES, TransportBackchannelEncapsulationMessage::header, is, GNUNET_MessageHeader::size, and size.

◆ handle_backchannel_encapsulation()

static void handle_backchannel_encapsulation ( void *  cls,
const struct TransportBackchannelEncapsulationMessage be 
)
static

Communicator gave us a backchannel encapsulation.

Process the request. (We are the destination of the backchannel here.)

Parameters
clsa struct CommunicatorMessageContext (must call finish_cmc_handling() when done)
bethe message that was received

Definition at line 7418 of file gnunet-service-transport.c.

7421{
7422 struct CommunicatorMessageContext *cmc = cls;
7424 struct GNUNET_MQ_Envelope *env;
7425 struct TransportClient *tc;
7426 const struct GNUNET_MessageHeader *inbox =
7427 (const struct GNUNET_MessageHeader *) &be[1];
7428 uint16_t isize = ntohs (inbox->size);
7429 const char *target_communicator = ((const char *) inbox) + isize;
7430 char *sender;
7431 char *self;
7432
7433 GNUNET_asprintf (&sender,
7434 "%s",
7435 GNUNET_i2s (&cmc->im.sender));
7436 GNUNET_asprintf (&self,
7437 "%s",
7439
7440 /* Find client providing this communicator */
7441 for (tc = clients_head; NULL != tc; tc = tc->next)
7442 if ((CT_COMMUNICATOR == tc->type) &&
7443 (0 ==
7444 strcmp (tc->details.communicator.address_prefix, target_communicator)))
7445 break;
7446 if (NULL == tc)
7447 {
7448 char *stastr;
7449
7451 &stastr,
7452 "# Backchannel message dropped: target communicator `%s' unknown",
7453 target_communicator);
7455 GNUNET_free (stastr);
7456 finish_cmc_handling (cmc);
7457 return;
7458 }
7459 /* Finally, deliver backchannel message to communicator */
7461 "Delivering backchannel message from %s to %s of type %u to %s\n",
7462 sender,
7463 self,
7464 ntohs (inbox->type),
7465 target_communicator);
7467 cbi,
7468 isize,
7470 cbi->pid = cmc->im.sender;
7471 memcpy (&cbi[1], inbox, isize);
7472 GNUNET_MQ_send (tc->mq, env);
7473 finish_cmc_handling (cmc);
7474}

References clients_head, CT_COMMUNICATOR, env, finish_cmc_handling(), GNUNET_asprintf(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_NO, GNUNET_STATISTICS_update(), GST_my_identity, GST_stats, CommunicatorMessageContext::im, GNUNET_TRANSPORT_CommunicatorBackchannelIncoming::pid, GNUNET_TRANSPORT_IncomingMessage::sender, GNUNET_MessageHeader::size, tc, and GNUNET_MessageHeader::type.

Here is the call graph for this function:

◆ path_cleanup_cb()

static void path_cleanup_cb ( void *  cls)
static

Task called when we should check if any of the DV paths we have learned to a target are due for garbage collection.

Collects stale paths, and possibly frees the entire DV entry if no paths are left. Otherwise re-schedules itself.

Parameters
clsa struct DistanceVector

Definition at line 7487 of file gnunet-service-transport.c.

7488{
7489 struct DistanceVector *dv = cls;
7490 struct DistanceVectorHop *pos;
7491
7492 dv->timeout_task = NULL;
7493 while (NULL != (pos = dv->dv_head))
7494 {
7495 GNUNET_assert (dv == pos->dv);
7497 break;
7499 }
7500 if (NULL == pos)
7501 {
7502 free_dv_route (dv);
7503 return;
7504 }
7505 dv->timeout_task =
7507}

References DistanceVectorHop::dv, DistanceVector::dv_head, free_distance_vector_hop(), free_dv_route(), GNUNET_assert, GNUNET_SCHEDULER_add_at(), GNUNET_TIME_absolute_get_remaining(), path_cleanup_cb(), GNUNET_TIME_Relative::rel_value_us, DistanceVectorHop::timeout, and DistanceVector::timeout_task.

Referenced by learn_dv_path(), and path_cleanup_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ send_msg_from_cache()

static void send_msg_from_cache ( struct VirtualLink vl)
static

Definition at line 7511 of file gnunet-service-transport.c.

7512{
7513
7514 const struct GNUNET_PeerIdentity target = vl->target;
7515
7516
7518 {
7519 struct RingBufferEntry *ring_buffer_copy[RING_BUFFER_SIZE];
7520 unsigned int tail = GNUNET_YES == is_ring_buffer_full ? ring_buffer_head :
7521 0;
7522 unsigned int head = GNUNET_YES == is_ring_buffer_full ? RING_BUFFER_SIZE :
7525 struct CommunicatorMessageContext *cmc;
7526 struct RingBufferEntry *rbe;
7527 struct GNUNET_MessageHeader *mh;
7528
7530 "Sending from ring buffer, which has %u items\n",
7531 head);
7532
7533 ring_buffer_head = 0;
7534 for (unsigned int i = 0; i < head; i++)
7535 {
7536 rbe = ring_buffer[(i + tail) % RING_BUFFER_SIZE];
7537 cmc = rbe->cmc;
7538 mh = rbe->mh;
7539
7540 im = cmc->im;
7541 // mh = cmc->mh;
7543 "Sending message of type %u to ring buffer target %s using vl target %s index %u\n",
7544 mh->type,
7545 GNUNET_i2s (&im.sender),
7546 GNUNET_i2s2 (&target),
7547 (i + tail) % RING_BUFFER_SIZE);
7548 if (0 == GNUNET_memcmp (&target, &im.sender))
7549 {
7551 "Finish handling message of type %u and size %u\n",
7552 (unsigned int) ntohs (mh->type),
7553 (unsigned int) ntohs (mh->size));
7555 GNUNET_free (mh);
7556 GNUNET_free (rbe->cmc);
7557 GNUNET_free (rbe);
7558 }
7559 else
7560 {
7561 ring_buffer_copy[ring_buffer_head] = rbe;
7563 }
7564 }
7565
7568 {
7570 }
7571
7572 for (unsigned int i = 0; i < ring_buffer_head; i++)
7573 {
7574 ring_buffer[i] = ring_buffer_copy[i];
7576 "ring_buffer_copy[i]->mh->type for i %u %u\n",
7577 i,
7578 ring_buffer_copy[i]->mh->type);
7580 "ring_buffer[i]->mh->type for i %u %u\n",
7581 i,
7582 ring_buffer[i]->mh->type);
7583 }
7584
7586 "%u items still in ring buffer\n",
7588 }
7589
7591 {
7592 struct PendingMessage *ring_buffer_dv_copy[RING_BUFFER_SIZE];
7593 struct PendingMessage *pm;
7594 unsigned int tail = GNUNET_YES == is_ring_buffer_dv_full ?
7596 0;
7597 unsigned int head = GNUNET_YES == is_ring_buffer_dv_full ?
7600
7602 "Sending from ring buffer dv, which has %u items\n",
7603 head);
7604
7606 for (unsigned int i = 0; i < head; i++)
7607 {
7608 pm = ring_buffer_dv[(i + tail) % RING_BUFFER_SIZE];
7609
7611 "Sending to ring buffer target %s using vl target %s\n",
7612 GNUNET_i2s (&pm->target),
7613 GNUNET_i2s2 (&target));
7614 if (0 == GNUNET_memcmp (&target, &pm->target))
7615 {
7617 "Adding PendingMessage to vl, checking transmission.\n");
7618 pm->vl = vl;
7622 pm);
7623
7625 }
7626 else
7627 {
7628 ring_buffer_dv_copy[ring_buffer_dv_head] = pm;
7630 }
7631 }
7632
7634 {
7636 }
7637
7638 for (unsigned int i = 0; i < ring_buffer_dv_head; i++)
7639 ring_buffer_dv[i] = ring_buffer_dv_copy[i];
7640
7642 "%u items still in ring buffer dv.\n",
7644
7645 }
7646}

References check_vl_transmission(), RingBufferEntry::cmc, finish_handling_raw_message(), GNUNET_CONTAINER_MDLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_i2s(), GNUNET_i2s2(), GNUNET_log, GNUNET_memcmp, GNUNET_NO, GNUNET_YES, is_ring_buffer_dv_full, is_ring_buffer_full, mh, RingBufferEntry::mh, VirtualLink::pending_msg_head, VirtualLink::pending_msg_tail, pm, ring_buffer, ring_buffer_dv, ring_buffer_dv_head, ring_buffer_head, RING_BUFFER_SIZE, GNUNET_TRANSPORT_IncomingMessage::sender, VirtualLink::target, PendingMessage::target, and PendingMessage::vl.

Referenced by activate_core_visible_dv_path(), and handle_validation_response().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ activate_core_visible_dv_path()

static void activate_core_visible_dv_path ( struct DistanceVectorHop hop)
static

The hop is a validated path to the respective target peer and we should tell core about it – and schedule a job to revoke the state.

Parameters
hopa path to some peer that is the reason for activation

Definition at line 7657 of file gnunet-service-transport.c.

7658{
7659 struct DistanceVector *dv = hop->dv;
7660 struct VirtualLink *vl;
7661
7662 vl = lookup_virtual_link (&dv->target);
7663 if (NULL == vl)
7664 {
7665
7666 vl = GNUNET_new (struct VirtualLink);
7668 "Creating new virtual link %p to %s using DV!\n",
7669 vl,
7670 GNUNET_i2s (&dv->target));
7671 vl->burst_addr = NULL;
7672 vl->confirmed = GNUNET_YES;
7673 vl->message_uuid_ctr =
7675 vl->target = dv->target;
7681 links,
7682 &vl->target,
7683 vl,
7685 vl->dv = dv;
7686 dv->vl = vl;
7687 vl->visibility_task =
7690 /* We lacked a confirmed connection to the target
7691 before, so tell CORE about it (finally!) */
7694 }
7695 else
7696 {
7697 /* Link was already up, remember dv is also now available and we are done */
7698 vl->dv = dv;
7699 dv->vl = vl;
7700 if (GNUNET_NO == vl->confirmed)
7701 {
7702 vl->confirmed = GNUNET_YES;
7703 vl->visibility_task =
7706 /* We lacked a confirmed connection to the target
7707 before, so tell CORE about it (finally!) */
7710 }
7711 else
7713 "Virtual link to %s could now also use DV!\n",
7714 GNUNET_i2s (&dv->target));
7715 }
7716}

References VirtualLink::available_fc_window_size, VirtualLink::burst_addr, check_link_down(), VirtualLink::confirmed, consider_sending_fc(), VirtualLink::core_recv_window, cores_send_connect_info(), DEFAULT_WINDOW_SIZE, VirtualLink::dv, DistanceVectorHop::dv, GNUNET_break, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multipeermap_put(), GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u64(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_new, GNUNET_NO, GNUNET_SCHEDULER_add_at(), GNUNET_YES, VirtualLink::incoming_fc_window_size, links, lookup_virtual_link(), VirtualLink::message_uuid_ctr, DistanceVectorHop::path_valid_until, RECV_WINDOW_SIZE, send_msg_from_cache(), VirtualLink::target, DistanceVector::target, VirtualLink::visibility_task, and DistanceVector::vl.

Referenced by learn_dv_path().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ learn_dv_path()

static int learn_dv_path ( const struct GNUNET_PeerIdentity path,
unsigned int  path_len,
struct GNUNET_TIME_Relative  network_latency,
struct GNUNET_TIME_Absolute  path_valid_until 
)
static

We have learned a path through the network to some other peer, add it to our DV data structure (returning GNUNET_YES on success).

We do not add paths if we have a sufficient number of shorter paths to this target already (returning GNUNET_NO).

We also do not add problematic paths, like those where we lack the first hop in our neighbour list (i.e. due to a topology change) or where some non-first hop is in our neighbour list (returning GNUNET_SYSERR).

Parameters
paththe path we learned, path[0] should be us, and then path contains a valid path from us to path[path_len-1] path[1] should be a direct neighbour (we should check!)
path_lennumber of entries on the path, at least three!
network_latencyhow long does the message take from us to path[path_len-1]? set to "forever" if unknown
path_valid_untilhow long is this path considered validated? Maybe be zero.
Returns
GNUNET_YES on success, GNUNET_NO if we have better path(s) to the target GNUNET_SYSERR if the path is useless and/or invalid (i.e. path[1] not a direct neighbour or path[i+1] is a direct neighbour for i>0)

Definition at line 7745 of file gnunet-service-transport.c.

7749{
7750 struct DistanceVectorHop *hop;
7751 struct DistanceVector *dv;
7752 struct Neighbour *next_hop;
7753 unsigned int shorter_distance;
7754
7755 if (path_len < 3)
7756 {
7757 /* what a boring path! not allowed! */
7758 GNUNET_break (0);
7759 return GNUNET_SYSERR;
7760 }
7761 GNUNET_assert (0 == GNUNET_memcmp (GST_my_identity, &path[0]));
7762 next_hop = lookup_neighbour (&path[1]);
7763 if (NULL == next_hop)
7764 {
7765 /* next hop must be a neighbour, otherwise this whole thing is useless! */
7766 GNUNET_break (0);
7767 return GNUNET_SYSERR;
7768 }
7769 for (unsigned int i = 2; i < path_len; i++)
7770 {
7771 struct Neighbour *n = lookup_neighbour (&path[i]);
7772 struct GNUNET_TIME_Absolute q_timeout;
7773
7774 if (NULL != n)
7775 {
7776 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
7777 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
7778 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
7780 "remaining %lu to %s\n",
7781 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout)
7782 .rel_value_us,
7783 GNUNET_i2s (&n->pid));
7784 if (0 != GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
7785 {
7786 /* Useless path: we have a direct active connection to some hop
7787 in the middle of the path, so this one is not even
7788 terribly useful for redundancy */
7790 "Path of %u hops useless: directly link to hop %u (%s)\n",
7791 path_len,
7792 i,
7793 GNUNET_i2s (&path[i]));
7795 "# Useless DV path ignored: hop is neighbour",
7796 1,
7797 GNUNET_NO);
7798 return GNUNET_SYSERR;
7799 }
7800 }
7801 }
7802 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
7803 if (NULL == dv)
7804 {
7805 dv = GNUNET_new (struct DistanceVector);
7806 dv->target = path[path_len - 1];
7809 dv);
7812 dv_routes,
7813 &dv->target,
7814 dv,
7816 }
7817 /* Check if we have this path already! */
7818 shorter_distance = 0;
7819 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
7820 pos = pos->next_dv)
7821 {
7822 if (pos->distance < path_len - 3)
7823 shorter_distance++;
7824 /* Note that the distances in 'pos' excludes us (path[0]),
7825 the next_hop (path[1]) and the target so we need to subtract three
7826 and check next_hop explicitly */
7827 if ((pos->distance == path_len - 3) && (pos->next_hop == next_hop))
7828 {
7829 int match = GNUNET_YES;
7830
7831 for (unsigned int i = 0; i < pos->distance; i++)
7832 {
7833 if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
7834 {
7835 match = GNUNET_NO;
7836 break;
7837 }
7838 }
7839 if (GNUNET_YES == match)
7840 {
7841 struct GNUNET_TIME_Relative last_timeout;
7842
7843 /* Re-discovered known path, update timeout */
7845 "# Known DV path refreshed",
7846 1,
7847 GNUNET_NO);
7848 last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
7849 pos->timeout =
7851 pos->path_valid_until =
7852 GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
7853 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
7854 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
7855 if (0 <
7858 if (last_timeout.rel_value_us <
7861 .rel_value_us)
7862 {
7863 /* Some peer send DV learn messages too often, we are learning
7864 the same path faster than it would be useful; do not forward! */
7866 "Rediscovered path too quickly, not forwarding further\n")
7867 ;
7868 return GNUNET_NO;
7869 }
7871 "Refreshed known path to %s valid until %s, forwarding further\n",
7872 GNUNET_i2s (&dv->target),
7874 pos->path_valid_until));
7875 return GNUNET_YES;
7876 }
7877 }
7878 }
7879 /* Count how many shorter paths we have (incl. direct
7880 neighbours) before simply giving up on this one! */
7881 if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
7882 {
7883 /* We have a shorter path already! */
7885 "Have many shorter DV paths %s, not forwarding further\n",
7886 GNUNET_i2s (&dv->target));
7887 return GNUNET_NO;
7888 }
7889 /* create new DV path entry */
7891 "Discovered new DV path to %s valid until %s\n",
7892 GNUNET_i2s (&dv->target),
7893 GNUNET_STRINGS_absolute_time_to_string (path_valid_until));
7894 hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
7895 + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7896 hop->next_hop = next_hop;
7897 hop->dv = dv;
7898 hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
7899 memcpy (&hop[1],
7900 &path[2],
7901 sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7903 hop->path_valid_until = path_valid_until;
7904 hop->distance = path_len - 3;
7905 hop->pd.aged_rtt = network_latency;
7906 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
7908 next_hop->dv_head,
7909 next_hop->dv_tail,
7910 hop);
7911 if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
7913 return GNUNET_YES;
7914}

References activate_core_visible_dv_path(), PerformanceData::aged_rtt, DistanceVectorHop::distance, DistanceVectorHop::dv, DistanceVector::dv_head, Neighbour::dv_head, DV_PATH_DISCOVERY_FREQUENCY, DV_PATH_VALIDITY_TIMEOUT, dv_routes, DistanceVector::dv_tail, Neighbour::dv_tail, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_MDLL_insert, GNUNET_CONTAINER_MDLL_remove, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multipeermap_get(), GNUNET_CONTAINER_multipeermap_put(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_i2s(), GNUNET_log, GNUNET_malloc, GNUNET_memcmp, GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_delayed(), GNUNET_STATISTICS_update(), GNUNET_STRINGS_absolute_time_to_string(), GNUNET_SYSERR, GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_absolute_max(), GNUNET_TIME_relative_subtract(), GNUNET_TIME_relative_to_absolute(), GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_YES, GST_my_identity, GST_stats, lookup_neighbour(), MAX_DV_PATHS_TO_TARGET, DistanceVectorHop::next_hop, DistanceVectorHop::path, path_cleanup_cb(), DistanceVectorHop::path_valid_until, DistanceVectorHop::pd, Neighbour::pid, q, Neighbour::queue_head, GNUNET_TIME_Relative::rel_value_us, DistanceVector::target, DistanceVectorHop::timeout, and DistanceVector::timeout_task.

Referenced by handle_dv_learn().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_dv_learn()

static int check_dv_learn ( void *  cls,
const struct TransportDVLearnMessage dvl 
)
static

Communicator gave us a DV learn message.

Check the message.

Parameters
clsa struct CommunicatorMessageContext
dvlthe send message that was sent
Returns
GNUNET_YES if message is well-formed

Definition at line 7925 of file gnunet-service-transport.c.

7926{
7927 uint16_t size = ntohs (dvl->header.size);
7928 uint16_t num_hops = ntohs (dvl->num_hops);
7929 const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
7930
7931 (void) cls;
7932 if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
7933 {
7934 GNUNET_break_op (0);
7935 return GNUNET_SYSERR;
7936 }
7937 if (num_hops > MAX_DV_HOPS_ALLOWED)
7938 {
7939 GNUNET_break_op (0);
7940 return GNUNET_SYSERR;
7941 }
7942 for (unsigned int i = 0; i < num_hops; i++)
7943 {
7944 if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
7945 {
7946 GNUNET_break_op (0);
7947 return GNUNET_SYSERR;
7948 }
7949 if (0 == GNUNET_memcmp (GST_my_identity, &hops[i].hop))
7950 {
7951 GNUNET_break_op (0);
7952 return GNUNET_SYSERR;
7953 }
7954 }
7955 return GNUNET_YES;
7956}

References GNUNET_break_op, GNUNET_memcmp, GNUNET_SYSERR, GNUNET_YES, GST_my_identity, TransportDVLearnMessage::header, DVPathEntryP::hop, TransportDVLearnMessage::initiator, MAX_DV_HOPS_ALLOWED, TransportDVLearnMessage::num_hops, GNUNET_MessageHeader::size, and size.

◆ sign_dhp_cp()

static void sign_dhp_cp ( void *  cls,
const struct GNUNET_PeerIdentity pid,
const struct GNUNET_CRYPTO_EddsaSignature sig 
)
static

Definition at line 7970 of file gnunet-service-transport.c.

7973{
7974 struct SignDhpCls *sign_dhp_cls = cls;
7975 struct VirtualLink *vl;
7976 struct DVPathEntryP *dhops = sign_dhp_cls->dhops;
7977 uint16_t nhops = sign_dhp_cls->nhops;
7978 const struct GNUNET_PeerIdentity *next_hop = sign_dhp_cls->next_hop;
7979 struct TransportDVLearnMessage *fwd = sign_dhp_cls->fwd;
7980 struct Neighbour *n;
7981
7982 sign_dhp_cls->pr->op = NULL;
7985 sign_dhp_cls->pr);
7986 GNUNET_free (sign_dhp_cls->pr);
7987 dhops[nhops].hop_sig = *sig;
7988
7989 /*route_control_message_without_fc (next_hop,
7990 &fwd->header,
7991 RMO_UNCONFIRMED_ALLOWED);*/
7992 vl = lookup_virtual_link (next_hop);
7993 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
7994 {
7996 &fwd->header,
7998 }
7999 else
8000 {
8001 /* Use route via neighbour */
8002 n = lookup_neighbour (next_hop);
8003 if (NULL != n)
8005 n,
8006 &fwd->header,
8008 }
8009 GNUNET_free (sign_dhp_cls);
8010}

References VirtualLink::confirmed, SignDhpCls::dhops, SignDhpCls::fwd, GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_YES, TransportDVLearnMessage::header, DVPathEntryP::hop_sig, lookup_neighbour(), lookup_virtual_link(), SignDhpCls::next_hop, SignDhpCls::nhops, PilsRequest::op, pils_requests_head, pils_requests_tail, SignDhpCls::pr, RMO_UNCONFIRMED_ALLOWED, route_control_message_without_fc(), route_via_neighbour(), and Neighbour::vl.

Referenced by forward_dv_learn().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ forward_dv_learn()

static void forward_dv_learn ( const struct GNUNET_PeerIdentity next_hop,
const struct TransportDVLearnMessage msg,
uint16_t  bi_history,
uint16_t  nhops,
const struct DVPathEntryP hops,
struct GNUNET_TIME_Absolute  in_time 
)
static

Build and forward a DV learn message to next_hop.

Parameters
next_hoppeer to send the message to
msgmessage received
bi_historybitmask specifying hops on path that were bidirectional
nhopslength of the hops array
hopspath the message traversed so far
in_timewhen did we receive the message, used to calculate network delay

Definition at line 8025 of file gnunet-service-transport.c.

8031{
8032 struct DVPathEntryP *dhops;
8033 char buf[sizeof(struct TransportDVLearnMessage)
8034 + (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
8035 struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
8036 struct GNUNET_TIME_Relative nnd;
8037
8038 /* compute message for forwarding */
8040 "Forwarding DV learn message originating from %s to %s\n",
8041 GNUNET_i2s (&msg->initiator),
8042 GNUNET_i2s2 (next_hop));
8045 fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
8046 + (nhops + 1) * sizeof(struct DVPathEntryP));
8047 fwd->num_hops = htons (nhops + 1);
8048 fwd->bidirectional = htons (bi_history);
8051 msg->non_network_delay));
8053 fwd->init_sig = msg->init_sig;
8054 fwd->initiator = msg->initiator;
8055 fwd->challenge = msg->challenge;
8056 fwd->monotonic_time = msg->monotonic_time;
8057 dhops = (struct DVPathEntryP *) &fwd[1];
8058 GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
8059 dhops[nhops].hop = *GST_my_identity;
8060 {
8061 struct DvHopPS dhp = {
8063 .purpose.size = htonl (sizeof(dhp)),
8064 .pred = (0 == nhops) ? msg->initiator : dhops[nhops - 1].hop,
8065 .succ = *next_hop,
8067 };
8068 struct SignDhpCls *sign_dhp_cls = GNUNET_new (struct SignDhpCls);
8069 sign_dhp_cls->dhops = dhops;
8070 sign_dhp_cls->nhops = nhops;
8071 sign_dhp_cls->next_hop = next_hop;
8072 sign_dhp_cls->fwd = fwd;
8073 sign_dhp_cls->pr = GNUNET_new (struct PilsRequest);
8076 sign_dhp_cls->pr);
8077 sign_dhp_cls->pr->op =
8079 &dhp.purpose,
8081 sign_dhp_cls);
8082 }
8083}

References TransportDVLearnMessage::bidirectional, TransportDVLearnMessage::challenge, SignDhpCls::dhops, SignDhpCls::fwd, GNUNET_ALIGN, GNUNET_assert, GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_i2s2(), GNUNET_log, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN, GNUNET_new, GNUNET_PILS_sign_by_peer_identity(), GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP, GNUNET_TIME_absolute_get_duration(), GNUNET_TIME_relative_add(), GNUNET_TIME_relative_hton(), GNUNET_TIME_relative_ntoh(), GST_my_identity, TransportDVLearnMessage::header, DVPathEntryP::hop, TransportDVLearnMessage::init_sig, TransportDVLearnMessage::initiator, MAX_DV_HOPS_ALLOWED, TransportDVLearnMessage::monotonic_time, msg, SignDhpCls::next_hop, SignDhpCls::nhops, TransportDVLearnMessage::non_network_delay, TransportDVLearnMessage::num_hops, PilsRequest::op, pils, pils_requests_head, pils_requests_tail, SignDhpCls::pr, GNUNET_CRYPTO_EccSignaturePurpose::purpose, DvHopPS::purpose, sign_dhp_cp(), GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

Referenced by dv_neighbour_transmission(), and handle_dv_learn().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ validate_dv_initiator_signature()

static int validate_dv_initiator_signature ( struct GNUNET_TIME_AbsoluteNBO  sender_monotonic_time,
const struct GNUNET_PeerIdentity init,
const struct GNUNET_CRYPTO_ChallengeNonceP challenge,
const struct GNUNET_CRYPTO_EddsaSignature init_sig 
)
static

Check signature of type GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.

Parameters
sender_monotonic_timemonotonic time of the initiator
initthe signer
challengethe challenge that was signed
init_sigsignature presumably by init
Returns
GNUNET_OK if the signature is valid

Definition at line 8096 of file gnunet-service-transport.c.

8101{
8102 struct DvInitPS ip = { .purpose.purpose = htonl (
8104 .purpose.size = htonl (sizeof(ip)),
8105 .monotonic_time = sender_monotonic_time,
8106 .challenge = *challenge };
8107
8108 if (
8109 GNUNET_OK !=
8111 &ip,
8112 init_sig,
8113 &init->public_key))
8114 {
8115 GNUNET_break_op (0);
8116 return GNUNET_SYSERR;
8117 }
8118 return GNUNET_OK;
8119}

References DvInitPS::challenge, GNUNET_break_op, GNUNET_CRYPTO_eddsa_verify, GNUNET_OK, GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR, GNUNET_SYSERR, init, GNUNET_CRYPTO_EccSignaturePurpose::purpose, and DvInitPS::purpose.

Referenced by handle_dv_learn().

Here is the caller graph for this function:

◆ dv_neighbour_selection()

static int dv_neighbour_selection ( void *  cls,
const struct GNUNET_PeerIdentity pid,
void *  value 
)
static

Function called for each neighbour during handle_dv_learn.

Parameters
clsa struct NeighbourSelectionContext *
pididentity of the peer
valuea struct Neighbour
Returns
GNUNET_YES (always)

Definition at line 8178 of file gnunet-service-transport.c.

8181{
8182 struct NeighbourSelectionContext *nsc = cls;
8183
8184 (void) value;
8185 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8186 return GNUNET_YES; /* skip initiator */
8187 for (unsigned int i = 0; i < nsc->nhops; i++)
8188 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8189 return GNUNET_YES;
8190 /* skip peers on path */
8191 nsc->num_eligible++;
8192 return GNUNET_YES;
8193}

References NeighbourSelectionContext::dvl, GNUNET_memcmp, GNUNET_YES, DVPathEntryP::hop, NeighbourSelectionContext::hops, TransportDVLearnMessage::initiator, NeighbourSelectionContext::nhops, NeighbourSelectionContext::num_eligible, pid, and value.

Referenced by handle_dv_learn().

Here is the caller graph for this function:

◆ dv_neighbour_transmission()

static int dv_neighbour_transmission ( void *  cls,
const struct GNUNET_PeerIdentity pid,
void *  value 
)
static

Function called for each neighbour during handle_dv_learn.

We call forward_dv_learn() on the neighbour(s) selected during dv_neighbour_selection().

Parameters
clsa struct NeighbourSelectionContext *
pididentity of the peer
valuea struct Neighbour
Returns
GNUNET_YES (always)

Definition at line 8207 of file gnunet-service-transport.c.

8210{
8211 struct NeighbourSelectionContext *nsc = cls;
8212
8214 "transmission %s\n",
8215 GNUNET_i2s (pid));
8216 (void) value;
8217 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8218 return GNUNET_YES; /* skip initiator */
8219 for (unsigned int i = 0; i < nsc->nhops; i++)
8220 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8221 return GNUNET_YES;
8222 /* skip peers on path */
8223 for (unsigned int i = 0; i < nsc->num_selections; i++)
8224 {
8225 if (nsc->selections[i] == nsc->num_eligible)
8226 {
8228 nsc->dvl,
8229 nsc->bi_history,
8230 nsc->nhops,
8231 nsc->hops,
8232 nsc->in_time);
8233 break;
8234 }
8235 }
8236 nsc->num_eligible++;
8237 return GNUNET_YES;
8238}

References NeighbourSelectionContext::bi_history, NeighbourSelectionContext::dvl, forward_dv_learn(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_memcmp, GNUNET_YES, DVPathEntryP::hop, NeighbourSelectionContext::hops, NeighbourSelectionContext::in_time, TransportDVLearnMessage::initiator, NeighbourSelectionContext::nhops, NeighbourSelectionContext::num_eligible, NeighbourSelectionContext::num_selections, pid, NeighbourSelectionContext::selections, and value.

Referenced by handle_dv_learn().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ calculate_fork_degree()

static unsigned int calculate_fork_degree ( unsigned int  hops_taken,
unsigned int  neighbour_count,
unsigned int  eligible_count 
)
static

Computes the number of neighbours we should forward a DVInit message to given that it has so far taken hops_taken hops though the network and that the number of neighbours we have in total is neighbour_count, out of which eligible_count are not yet on the path.

NOTE: technically we might want to include NSE in the formula to get a better grip on the overall network size. However, for now using NSE here would create a dependency issue in the build system. => Left for later, hardcoded to 50 for now.

The goal of the formula is that we want to reach a total of LOG(NSE) peers via DV (target_total). We want the reach to be spread out over various distances to the origin, with a bias towards shorter distances.

We make the strong assumption that the network topology looks "similar" at other hops, in particular the neighbour_count should be comparable at other hops.

If the local neighbourhood is densely connected, we expect that eligible_count is close to neighbour_count minus hops_taken as a lot of the path is already known. In that case, we should forward to few(er) peers to try to find a path out of the neighbourhood. OTOH, if eligible_count is close to neighbour_count, we should forward to many peers as we are either still close to the origin (i.e. hops_taken is small) or because we managed to get beyond a local cluster. We express this as the boost_factor using the square of the fraction of eligible neighbours (so if only 50% are eligible, we boost by 1/4, but if 99% are eligible, the 'boost' will be almost 1).

Second, the more hops we have taken, the larger the problem of an exponential traffic explosion gets. So we take the target_total, and compute our degree such that at each distance d 2^{-d} peers are selected (corrected by the boost_factor).

Parameters
hops_takennumber of hops DVInit has travelled so far
neighbour_countnumber of neighbours we have in total
eligible_countnumber of neighbours we could in theory forward to

Definition at line 8285 of file gnunet-service-transport.c.

8288{
8289 double target_total = 50.0; /* FIXME: use LOG(NSE)? */
8290 double eligible_ratio =
8291 ((double) eligible_count) / ((double) neighbour_count);
8292 double boost_factor = eligible_ratio * eligible_ratio;
8293 unsigned int rnd;
8294 double left;
8295
8296 if (hops_taken >= 64)
8297 {
8298 GNUNET_break (0);
8299 return 0; /* precaution given bitshift below */
8300 }
8301 for (unsigned int i = 1; i < hops_taken; i++)
8302 {
8303 /* For each hop, subtract the expected number of targets
8304 reached at distance d (so what remains divided by 2^d) */
8305 target_total -= (target_total * boost_factor / (1LLU << i));
8306 }
8307 rnd =
8308 (unsigned int) floor (target_total * boost_factor / (1LLU << hops_taken));
8309 /* round up or down probabilistically depending on how close we were
8310 when floor()ing to rnd */
8311 left = target_total - (double) rnd;
8312 if (UINT32_MAX * left >
8314 rnd++; /* round up */
8316 "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
8317 hops_taken,
8318 rnd,
8319 eligible_count,
8320 neighbour_count);
8321 return rnd;
8322}

References GNUNET_break, GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u64(), GNUNET_ERROR_TYPE_DEBUG, and GNUNET_log.

Referenced by handle_dv_learn().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ neighbour_store_dvmono_cb()

static void neighbour_store_dvmono_cb ( void *  cls,
int  success 
)
static

Function called when peerstore is done storing a DV monotonic time.

Parameters
clsa struct Neighbour
successGNUNET_YES if peerstore was successful

Definition at line 8332 of file gnunet-service-transport.c.

8333{
8334 struct Neighbour *n = cls;
8335
8336 n->sc = NULL;
8337 if (GNUNET_YES != success)
8339 "Failed to store other peer's monotonic time in peerstore!\n");
8340}

References GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_YES, and Neighbour::sc.

Referenced by handle_dv_learn().

Here is the caller graph for this function:

◆ get_network_latency()

static struct GNUNET_TIME_Relative get_network_latency ( const struct TransportDVLearnMessage dvl)
static

Definition at line 8344 of file gnunet-service-transport.c.

8345{
8346 struct GNUNET_TIME_Relative host_latency_sum;
8347 struct GNUNET_TIME_Relative latency;
8348 struct GNUNET_TIME_Relative network_latency;
8349 uint16_t nhops = ntohs (dvl->num_hops);;
8350
8351 /* We initiated this, learn the forward path! */
8352 host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
8353
8354 // Need also something to lookup initiation time
8355 // to compute RTT! -> add RTT argument here?
8357 dvl->monotonic_time));
8358 GNUNET_assert (latency.rel_value_us >= host_latency_sum.rel_value_us);
8359 // latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
8360 // (based on dvl->challenge, we can identify time of origin!)
8361
8362 network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
8363 /* assumption: latency on all links is the same */
8364 network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
8365
8366 return network_latency;
8367}

References GNUNET_assert, GNUNET_TIME_absolute_get_duration(), GNUNET_TIME_absolute_ntoh(), GNUNET_TIME_relative_divide(), GNUNET_TIME_relative_ntoh(), GNUNET_TIME_relative_subtract(), and GNUNET_TIME_Relative::rel_value_us.

Referenced by handle_dv_learn().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_dv_learn()

static void handle_dv_learn ( void *  cls,
const struct TransportDVLearnMessage dvl 
)
static

Communicator gave us a DV learn message.

Process the request.

Parameters
clsa struct CommunicatorMessageContext (must call finish_cmc_handling() when done)
dvlthe message that was received

Definition at line 8378 of file gnunet-service-transport.c.

8379{
8380 struct CommunicatorMessageContext *cmc = cls;
8382 int bi_hop;
8383 uint16_t nhops;
8384 uint16_t bi_history;
8385 const struct DVPathEntryP *hops;
8386 int do_fwd;
8387 int did_initiator;
8388 struct GNUNET_TIME_Absolute in_time;
8389 struct Neighbour *n;
8390
8391 nhops = ntohs (dvl->num_hops); /* 0 = sender is initiator */
8392 bi_history = ntohs (dvl->bidirectional);
8393 hops = (const struct DVPathEntryP *) &dvl[1];
8394 if (0 == nhops)
8395 {
8396 /* sanity check */
8397 if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
8398 {
8399 GNUNET_break (0);
8400 finish_cmc_handling (cmc);
8401 return;
8402 }
8403 }
8404 else
8405 {
8407 "handle dv learn message last hop %s\n",
8408 GNUNET_i2s (&hops[nhops - 1].hop));
8409 /* sanity check */
8410 if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
8411 {
8412 GNUNET_break (0);
8413 finish_cmc_handling (cmc);
8414 return;
8415 }
8416 }
8417
8419 cc = cmc->tc->details.communicator.cc;
8420 bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
8421 cc); // FIXME: add bi-directional flag to cc?
8422 in_time = GNUNET_TIME_absolute_get ();
8423
8424 /* continue communicator here, everything else can happen asynchronous! */
8425 finish_cmc_handling (cmc);
8426
8427 n = lookup_neighbour (&dvl->initiator);
8428 if (NULL != n)
8429 {
8430 if ((n->dv_monotime_available == GNUNET_YES) &&
8433 {
8435 "DV learn from %s discarded due to time travel",
8436 GNUNET_i2s (&dvl->initiator));
8438 "# DV learn discarded due to time travel",
8439 1,
8440 GNUNET_NO);
8441 return;
8442 }
8444 &dvl->initiator,
8445 &dvl->challenge,
8446 &dvl->init_sig))
8447 {
8449 "DV learn signature from %s invalid\n",
8450 GNUNET_i2s (&dvl->initiator));
8451 GNUNET_break_op (0);
8452 return;
8453 }
8456 {
8457 if (NULL != n->sc)
8458 {
8460 "store cancel\n");
8462 }
8463 n->sc =
8465 "transport",
8466 &dvl->initiator,
8468 &dvl->monotonic_time,
8469 sizeof(dvl->monotonic_time),
8473 n);
8474 }
8475 }
8476 /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
8477 If signature verification load too high, implement random drop strategy */
8478 for (unsigned int i = 0; i < nhops; i++)
8479 {
8480 struct DvHopPS dhp = { .purpose.purpose =
8482 .purpose.size = htonl (sizeof(dhp)),
8483 .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
8484 .succ = (nhops == i + 1) ? *GST_my_identity
8485 : hops[i + 1].hop,
8486 .challenge = dvl->challenge };
8487
8488 if (GNUNET_OK !=
8490 &dhp,
8491 &hops[i].hop_sig,
8492 &hops[i].hop.public_key))
8493 {
8495 "DV learn from %s signature of hop %u invalid\n",
8496 GNUNET_i2s (&dvl->initiator),
8497 i);
8499 "signature of hop %s invalid\n",
8500 GNUNET_i2s (&hops[i].hop));
8502 "pred %s\n",
8503 GNUNET_i2s (&dhp.pred));
8505 "succ %s\n",
8506 GNUNET_i2s (&dhp.succ));
8508 "hash %s\n",
8509 GNUNET_sh2s (&dhp.challenge.value));
8510 GNUNET_break_op (0);
8511 return;
8512 }
8513 }
8514 if (GNUNET_EXTRA_LOGGING > 0)
8515 {
8516 char *path;
8517
8518 path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
8519 for (unsigned int i = 0; i < nhops; i++)
8520 {
8521 char *tmp;
8522
8523 GNUNET_asprintf (&tmp,
8524 "%s%s%s",
8525 path,
8526 (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
8527 GNUNET_i2s (&hops[i].hop));
8528 GNUNET_free (path);
8529 path = tmp;
8530 }
8532 "Received DVInit via %s%s%s\n",
8533 path,
8534 bi_hop ? "<->" : "-->",
8536 GNUNET_free (path);
8537 }
8538 do_fwd = GNUNET_YES;
8539 if (0 == GNUNET_memcmp (GST_my_identity, &dvl->initiator))
8540 {
8541 struct GNUNET_PeerIdentity path[nhops + 1];
8542 struct GNUNET_TIME_Relative network_latency;
8543
8544 /* We initiated this, learn the forward path! */
8545 path[0] = *GST_my_identity;
8546 path[1] = hops[0].hop;
8547
8548 network_latency = get_network_latency (dvl);
8549
8550 for (unsigned int i = 2; i <= nhops; i++)
8551 {
8552 struct GNUNET_TIME_Relative ilat;
8553
8554 /* assumption: linear latency increase per hop */
8555 ilat = GNUNET_TIME_relative_multiply (network_latency, i);
8556 path[i] = hops[i - 1].hop;
8558 "Learned path with %u hops to %s with latency %s\n",
8559 i,
8560 GNUNET_i2s (&path[i]),
8562 learn_dv_path (path,
8563 i + 1,
8564 ilat,
8567 }
8568 /* as we initiated, do not forward again (would be circular!) */
8569 do_fwd = GNUNET_NO;
8570 return;
8571 }
8572 if (bi_hop)
8573 {
8574 /* last hop was bi-directional, we could learn something here! */
8575 struct GNUNET_PeerIdentity path[nhops + 2];
8576 struct GNUNET_TIME_Relative ilat;
8577 struct GNUNET_TIME_Relative network_latency;
8578
8579 path[0] = *GST_my_identity;
8580 path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
8581 for (unsigned int i = 0; i < nhops; i++)
8582 {
8583 int iret;
8584
8585 if (0 == (bi_history & (1 << i)))
8586 break; /* i-th hop not bi-directional, stop learning! */
8587 if (i == nhops - 1)
8588 {
8589 path[i + 2] = dvl->initiator;
8590 }
8591 else
8592 {
8593 path[i + 2] = hops[nhops - i - 2].hop;
8594 }
8595
8597 "Learned inverse path with %u hops to %s\n",
8598 i + 2,
8599 GNUNET_i2s (&path[i + 2]));
8600 network_latency = get_network_latency (dvl);
8601 ilat = GNUNET_TIME_relative_multiply (network_latency, i + 2);
8602 iret = learn_dv_path (path,
8603 i + 3,
8604 ilat,
8607 if (GNUNET_SYSERR == iret)
8608 {
8609 /* path invalid or too long to be interesting for US, thus should also
8610 not be interesting to our neighbours, cut path when forwarding to
8611 'i' hops, except of course for the one that goes back to the
8612 initiator */
8614 "# DV learn not forwarded due invalidity of path",
8615 1,
8616 GNUNET_NO);
8617 do_fwd = GNUNET_NO;
8618 break;
8619 }
8620 if ((GNUNET_NO == iret) && (nhops == i + 1))
8621 {
8622 /* we have better paths, and this is the longest target,
8623 so there cannot be anything interesting later */
8625 "# DV learn not forwarded, got better paths",
8626 1,
8627 GNUNET_NO);
8628 do_fwd = GNUNET_NO;
8629 break;
8630 }
8631 }
8632 }
8633 if (MAX_DV_HOPS_ALLOWED == nhops)
8634 {
8635 /* At limit, we're out of here! */
8636 return;
8637 }
8638
8639 /* Forward to initiator, if path non-trivial and possible */
8640 bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
8641 did_initiator = GNUNET_NO;
8642 if ((1 <= nhops) &&
8643 (GNUNET_YES ==
8645 {
8646 /* send back to origin! */
8648 "Sending DVL back to initiator %s\n",
8649 GNUNET_i2s (&dvl->initiator));
8650 forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
8651 did_initiator = GNUNET_YES;
8652 }
8653 /* We forward under two conditions: either we still learned something
8654 ourselves (do_fwd), or the path was darn short and thus the initiator is
8655 likely to still be very interested in this (and we did NOT already
8656 send it back to the initiator) */
8657 if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
8658 (GNUNET_NO == did_initiator)))
8659 {
8660 /* Pick random neighbours that are not yet on the path */
8661 struct NeighbourSelectionContext nsc;
8662 unsigned int n_cnt;
8663
8665 nsc.nhops = nhops;
8666 nsc.dvl = dvl;
8667 nsc.bi_history = bi_history;
8668 nsc.hops = hops;
8669 nsc.in_time = in_time;
8670 nsc.num_eligible = 0;
8673 &nsc);
8674 if (0 == nsc.num_eligible)
8675 return; /* done here, cannot forward to anyone else */
8676 nsc.num_selections = calculate_fork_degree (nhops, n_cnt, nsc.num_eligible);
8677 nsc.num_selections =
8678 GNUNET_MIN (MAX_DV_DISCOVERY_SELECTION, nsc.num_selections);
8680 "Forwarding DVL to %u other peers\n",
8681 nsc.num_selections);
8682 for (unsigned int i = 0; i < nsc.num_selections; i++)
8683 nsc.selections[i] =
8684 (nsc.num_selections == n_cnt)
8685 ? i /* all were selected, avoid collisions by chance */
8687 nsc.num_eligible = 0;
8690 &nsc);
8691 }
8692}

References GNUNET_TIME_Absolute::abs_value_us, ADDRESS_VALIDATION_LIFETIME, NeighbourSelectionContext::bi_history, TransportDVLearnMessage::bidirectional, calculate_fork_degree(), TransportClient::cc, DvHopPS::challenge, TransportDVLearnMessage::challenge, TransportClient::communicator, CT_COMMUNICATOR, TransportClient::details, Neighbour::dv_monotime_available, dv_neighbour_selection(), dv_neighbour_transmission(), NeighbourSelectionContext::dvl, finish_cmc_handling(), forward_dv_learn(), get_network_latency(), GNUNET_asprintf(), GNUNET_assert, GNUNET_break, GNUNET_break_op, GNUNET_CONTAINER_multipeermap_contains(), GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_CONTAINER_multipeermap_size(), GNUNET_CRYPTO_eddsa_verify, GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u32(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_EXTRA_LOGGING, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_memcmp, GNUNET_MIN, GNUNET_NO, GNUNET_OK, GNUNET_PEERSTORE_store(), GNUNET_PEERSTORE_store_cancel(), GNUNET_PEERSTORE_STOREOPTION_REPLACE, GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME, GNUNET_sh2s(), GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP, GNUNET_STATISTICS_update(), GNUNET_strdup, GNUNET_STRINGS_relative_time_to_string(), GNUNET_SYSERR, GNUNET_TIME_absolute_get(), GNUNET_TIME_absolute_ntoh(), GNUNET_TIME_relative_multiply(), GNUNET_TIME_relative_to_absolute(), GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_TRANSPORT_CC_RELIABLE, GNUNET_YES, GST_my_identity, GST_stats, DVPathEntryP::hop, NeighbourSelectionContext::hops, CommunicatorMessageContext::im, NeighbourSelectionContext::in_time, TransportDVLearnMessage::init_sig, TransportDVLearnMessage::initiator, Neighbour::last_dv_learn_monotime, learn_dv_path(), lookup_neighbour(), MAX_DV_DISCOVERY_SELECTION, MAX_DV_HOPS_ALLOWED, MIN_DV_PATH_LENGTH_FOR_INITIATOR, TransportDVLearnMessage::monotonic_time, neighbour_store_dvmono_cb(), neighbours, NeighbourSelectionContext::nhops, NeighbourSelectionContext::num_eligible, TransportDVLearnMessage::num_hops, NeighbourSelectionContext::num_selections, peerstore, DvHopPS::pred, GNUNET_CRYPTO_EccSignaturePurpose::purpose, DvHopPS::purpose, Neighbour::sc, NeighbourSelectionContext::selections, GNUNET_TRANSPORT_IncomingMessage::sender, DvHopPS::succ, CommunicatorMessageContext::tc, TransportClient::type, validate_dv_initiator_signature(), and GNUNET_CRYPTO_ChallengeNonceP::value.

Here is the call graph for this function:

◆ check_dv_box()

static int check_dv_box ( void *  cls,
const struct TransportDVBoxMessage dvb 
)
static

Communicator gave us a DV box.

Check the message.

Parameters
clsa struct CommunicatorMessageContext
dvbthe send message that was sent
Returns
GNUNET_YES if message is well-formed

Definition at line 8703 of file gnunet-service-transport.c.

8704{
8705 uint16_t size = ntohs (dvb->header.size);
8706 uint16_t num_hops = ntohs (dvb->num_hops);
8707 const struct GNUNET_PeerIdentity *hops =
8708 (const struct GNUNET_PeerIdentity *) &dvb[1];
8709
8710 (void) cls;
8711 if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
8712 + sizeof(struct GNUNET_MessageHeader))
8713 {
8714 GNUNET_break_op (0);
8715 return GNUNET_SYSERR;
8716 }
8717 /* This peer must not be on the path */
8718 for (unsigned int i = 0; i < num_hops; i++)
8719 if (0 == GNUNET_memcmp (&hops[i], GST_my_identity))
8720 {
8721 GNUNET_break_op (0);
8722 return GNUNET_SYSERR;
8723 }
8724 return GNUNET_YES;
8725}

References GNUNET_break_op, GNUNET_memcmp, GNUNET_SYSERR, GNUNET_YES, GST_my_identity, TransportDVBoxMessage::header, TransportDVBoxMessage::num_hops, GNUNET_MessageHeader::size, and size.

◆ forward_dv_box()

static void forward_dv_box ( struct Neighbour next_hop,
struct TransportDVBoxMessage hdr,
uint16_t  total_hops,
uint16_t  num_hops,
const struct GNUNET_PeerIdentity hops,
const void *  enc_payload,
uint16_t  enc_payload_size 
)
static

Create a DV Box message and queue it for transmission to next_hop.

Parameters
next_hoppeer to receive the message next
total_hopshow many hops did the message take so far
num_hopslength of the hops array
originorigin of the message
hopsnext peer(s) to the destination, including destination
payloadpayload of the box
payload_sizenumber of bytes in payload

Definition at line 8741 of file gnunet-service-transport.c.

8748{
8749 struct VirtualLink *vl = next_hop->vl;
8750 struct PendingMessage *pm;
8751 size_t msg_size = sizeof(struct TransportDVBoxMessage)
8752 + num_hops * sizeof(struct GNUNET_PeerIdentity)
8753 + enc_payload_size;
8754 char *buf;
8755 char msg_buf[msg_size] GNUNET_ALIGN;
8756 struct GNUNET_PeerIdentity *dhops;
8757
8758 hdr->num_hops = htons (num_hops);
8759 hdr->total_hops = htons (total_hops);
8760 hdr->header.size = htons (msg_size);
8761 memcpy (msg_buf, hdr, sizeof(*hdr));
8762 dhops = (struct GNUNET_PeerIdentity *) &msg_buf[sizeof(struct
8764 ;
8765 memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
8766 memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
8767
8768 if (GNUNET_YES == ntohs (hdr->without_fc))
8769 {
8771 "Forwarding control message (payload size %u) in DV Box to next hop %s (%u/%u) \n",
8772 enc_payload_size,
8773 GNUNET_i2s (&next_hop->pid),
8774 (unsigned int) num_hops,
8775 (unsigned int) total_hops);
8776 route_via_neighbour (next_hop, (const struct
8777 GNUNET_MessageHeader *) msg_buf,
8779 }
8780 else
8781 {
8782 pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
8784 "2 created pm %p storing vl %p \n",
8785 pm,
8786 vl);
8787 pm->pmt = PMT_DV_BOX;
8788 pm->vl = vl;
8789 pm->target = next_hop->pid;
8791 pm->logging_uuid = logging_uuid_gen++;
8793 pm->bytes_msg = msg_size;
8794 buf = (char *) &pm[1];
8795 memcpy (buf, msg_buf, msg_size);
8796
8798 "Created pending message %" PRIu64
8799 " for DV Box with next hop %s (%u/%u)\n",
8800 pm->logging_uuid,
8801 GNUNET_i2s (&next_hop->pid),
8802 (unsigned int) num_hops,
8803 (unsigned int) total_hops);
8804
8805 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
8806 {
8808 vl->pending_msg_head,
8809 vl->pending_msg_tail,
8810 pm);
8811
8813 }
8814 else
8815 {
8817 "The virtual link is not ready for forwarding a DV Box with payload, storing PendingMessage in ring buffer.\n");
8818
8820 {
8822
8823 GNUNET_free (pm_old);
8824 }
8827 {
8830 }
8831 else
8833
8835 "%u items stored in DV ring buffer\n",
8838 }
8839 }
8840}

References check_vl_transmission(), VirtualLink::confirmed, DV_FORWARD_TIMEOUT, GNUNET_ALIGN, GNUNET_CONTAINER_MDLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_malloc, GNUNET_MQ_PRIO_BACKGROUND, GNUNET_TIME_relative_to_absolute(), GNUNET_YES, TransportDVBoxMessage::header, is_ring_buffer_dv_full, logging_uuid_gen, TransportDVBoxMessage::num_hops, VirtualLink::pending_msg_head, VirtualLink::pending_msg_tail, Neighbour::pid, pm, PMT_DV_BOX, ring_buffer_dv, ring_buffer_dv_head, RING_BUFFER_SIZE, RMO_ANYTHING_GOES, route_via_neighbour(), GNUNET_MessageHeader::size, VirtualLink::target, TransportDVBoxMessage::total_hops, Neighbour::vl, and TransportDVBoxMessage::without_fc.

Referenced by handle_dv_box().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_backtalker()

static void free_backtalker ( struct Backtalker b)
static

Free data structures associated with b.

Parameters
bdata structure to release

Definition at line 8849 of file gnunet-service-transport.c.

8850{
8851 if (NULL != b->get)
8852 {
8854 b->get = NULL;
8855 GNUNET_assert (NULL != b->cmc);
8857 b->cmc = NULL;
8858 }
8859 if (NULL != b->task)
8860 {
8862 b->task = NULL;
8863 }
8864 if (NULL != b->sc)
8865 {
8867 "store cancel\n");
8869 b->sc = NULL;
8870 }
8872 "Removing backtalker for %s\n",
8873 GNUNET_i2s (&b->pid));
8875 GNUNET_YES ==
8877 GNUNET_free (b);
8878}

References backtalkers, Backtalker::cmc, finish_cmc_handling(), Backtalker::get, GNUNET_assert, GNUNET_CONTAINER_multipeermap_remove(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_PEERSTORE_iteration_stop(), GNUNET_PEERSTORE_store_cancel(), GNUNET_SCHEDULER_cancel(), GNUNET_YES, Backtalker::pid, Backtalker::sc, and Backtalker::task.

Referenced by backtalker_timeout_cb(), and free_backtalker_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_backtalker_cb()

static int free_backtalker_cb ( void *  cls,
const struct GNUNET_PeerIdentity pid,
void *  value 
)
static

Callback to free backtalker records.

Parameters
clsNULL
pidunused
valuea struct Backtalker
Returns
GNUNET_OK (always)

Definition at line 8890 of file gnunet-service-transport.c.

8893{
8894 struct Backtalker *b = value;
8895
8896 (void) cls;
8897 (void) pid;
8898 free_backtalker (b);
8899 return GNUNET_OK;
8900}

References free_backtalker(), GNUNET_OK, pid, and value.

Referenced by do_shutdown().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ backtalker_timeout_cb()

static void backtalker_timeout_cb ( void *  cls)
static

Function called when it is time to clean up a backtalker.

Parameters
clsa struct Backtalker

Definition at line 8909 of file gnunet-service-transport.c.

8910{
8911 struct Backtalker *b = cls;
8912
8914 "backtalker timeout.\n");
8915 b->task = NULL;
8917 {
8919 return;
8920 }
8921 GNUNET_assert (NULL == b->sc);
8922 free_backtalker (b);
8923}

References backtalker_timeout_cb(), free_backtalker(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_SCHEDULER_add_at(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_Relative::rel_value_us, Backtalker::sc, Backtalker::task, and Backtalker::timeout.

Referenced by backtalker_monotime_store_cb(), backtalker_timeout_cb(), and decaps_dv_box_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ backtalker_monotime_cb()

static void backtalker_monotime_cb ( void *  cls,
const struct GNUNET_PEERSTORE_Record record,
const char *  emsg 
)
static

Function called with the monotonic time of a backtalker by PEERSTORE.

Updates the time and continues processing.

Parameters
clsa struct Backtalker
recordthe information found, NULL for the last call
emsgerror message

Definition at line 8935 of file gnunet-service-transport.c.

8938{
8939 struct Backtalker *b = cls;
8940 struct GNUNET_TIME_AbsoluteNBO *mtbe;
8941 struct GNUNET_TIME_Absolute mt;
8942
8943 (void) emsg;
8944 if (NULL == record)
8945 {
8946 /* we're done with #backtalker_monotime_cb() invocations,
8947 continue normal processing */
8948 b->get = NULL;
8949 GNUNET_assert (NULL != b->cmc);
8950 b->cmc->mh = (const struct GNUNET_MessageHeader *) &b[1];
8951 if (0 != b->body_size)
8953 else
8955 b->cmc = NULL;
8956 return;
8957 }
8958 if (sizeof(*mtbe) != record->value_size)
8959 {
8961 GNUNET_break (0);
8962 return;
8963 }
8964 mtbe = record->value;
8965 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
8966 if (mt.abs_value_us > b->monotonic_time.abs_value_us)
8967 {
8969 "Backtalker message from %s dropped, monotime in the past\n",
8970 GNUNET_i2s (&b->pid));
8972 GST_stats,
8973 "# Backchannel messages dropped: monotonic time not increasing",
8974 1,
8975 GNUNET_NO);
8976 b->monotonic_time = mt;
8977 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
8978 */
8979 b->body_size = 0;
8980 }
8982}

References GNUNET_TIME_Absolute::abs_value_us, Backtalker::body_size, Backtalker::cmc, demultiplex_with_cmc(), finish_cmc_handling(), Backtalker::get, GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_PEERSTORE_iteration_next(), GNUNET_STATISTICS_update(), GNUNET_TIME_absolute_ntoh(), GST_stats, CommunicatorMessageContext::mh, Backtalker::monotonic_time, Backtalker::pid, and record().

Referenced by decaps_dv_box_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ backtalker_monotime_store_cb()

static void backtalker_monotime_store_cb ( void *  cls,
int  success 
)
static

Function called by PEERSTORE when the store operation of a backtalker's monotonic time is complete.

Parameters
clsthe struct Backtalker
successGNUNET_OK on success

Definition at line 8993 of file gnunet-service-transport.c.

8994{
8995 struct Backtalker *b = cls;
8996
8997 if (GNUNET_OK != success)
8998 {
9000 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
9001 }
9002 b->sc = NULL;
9003 if (NULL != b->task)
9004 {
9006 b->task = NULL;
9007 }
9009}

References backtalker_timeout_cb(), GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_OK, GNUNET_SCHEDULER_add_at(), GNUNET_SCHEDULER_cancel(), Backtalker::sc, Backtalker::task, and Backtalker::timeout.

Referenced by update_backtalker_monotime().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_backtalker_monotime()

static void update_backtalker_monotime ( struct Backtalker b)
static

The backtalker b monotonic time changed.

Update PEERSTORE.

Parameters
ba backtalker with updated monotonic time

Definition at line 9018 of file gnunet-service-transport.c.

9019{
9020 struct GNUNET_TIME_AbsoluteNBO mtbe;
9021
9022 if (NULL != b->sc)
9023 {
9025 "store cancel before store with sc %p\n",
9026 b->sc);
9027 /*GNUNET_PEERSTORE_store_cancel (b->sc);
9028 b->sc = NULL;*/
9030 "store cancel before store with sc %p is null\n",
9031 b->sc);
9032 }
9033 else
9034 {
9036 b->task = NULL;
9037 }
9039 b->sc =
9041 "transport",
9042 &b->pid,
9044 &mtbe,
9045 sizeof(mtbe),
9049 b);
9050}

References backtalker_monotime_store_cb(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_PEERSTORE_store(), GNUNET_PEERSTORE_STOREOPTION_REPLACE, GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME, GNUNET_SCHEDULER_cancel(), GNUNET_TIME_absolute_hton(), GNUNET_TIME_UNIT_FOREVER_ABS, Backtalker::monotonic_time, peerstore, Backtalker::pid, Backtalker::sc, and Backtalker::task.

Referenced by decaps_dv_box_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ decaps_dv_box_cb()

static void decaps_dv_box_cb ( void *  cls,
const struct GNUNET_ShortHashCode km 
)
static

Definition at line 9062 of file gnunet-service-transport.c.

9063{
9064 struct DecapsDvBoxCls *decaps_dv_box_cls = cls;
9065 struct CommunicatorMessageContext *cmc = decaps_dv_box_cls->cmc;
9066 const struct TransportDVBoxMessage *dvb = dvb;
9067 struct DVKeyState key;
9068 const char *hdr;
9069 size_t hdr_len;
9070 struct GNUNET_HashCode hmac;
9071
9072 decaps_dv_box_cls->pr->op = NULL;
9075 decaps_dv_box_cls->pr);
9076 GNUNET_free (decaps_dv_box_cls->pr);
9077 if (NULL == km)
9078 {
9079 GNUNET_break_op (0);
9080 finish_cmc_handling (cmc);
9081 return;
9082 }
9083 dv_setup_key_state_from_km (km, &dvb->iv, &key);
9084 hdr = (const char *) &dvb[1];
9085 hdr_len = ntohs (dvb->orig_size) - sizeof(*dvb) - sizeof(struct
9087 * ntohs (dvb->total_hops);
9088
9089 dv_hmac (&key, &hmac, hdr, hdr_len);
9090 if (0 != GNUNET_memcmp (&hmac, &dvb->hmac))
9091 {
9092 /* HMAC mismatch, discard! */
9093 GNUNET_break_op (0);
9094 finish_cmc_handling (cmc);
9095 return;
9096 }
9097 /* begin actual decryption */
9098 {
9099 struct Backtalker *b;
9100 struct GNUNET_TIME_Absolute monotime;
9101 struct TransportDVBoxPayloadP ppay;
9102 char body[hdr_len - sizeof(ppay)] GNUNET_ALIGN;
9103 const struct GNUNET_MessageHeader *mh;
9104
9105 GNUNET_assert (hdr_len >=
9106 sizeof(ppay) + sizeof(struct GNUNET_MessageHeader));
9107 if (GNUNET_OK != dv_decrypt (&key, &ppay, hdr, sizeof(ppay)))
9108 {
9110 "Error decrypting DV payload header\n");
9111 GNUNET_break_op (0);
9112 finish_cmc_handling (cmc);
9113 return;
9114 }
9115 if (GNUNET_OK != dv_decrypt (&key, body,
9116 &hdr[sizeof(ppay)], hdr_len - sizeof(ppay)))
9117 {
9119 "Error decrypting DV payload\n");
9120 GNUNET_break_op (0);
9121 finish_cmc_handling (cmc);
9122 return;
9123 }
9124 mh = (const struct GNUNET_MessageHeader *) body;
9125 dv_key_clean (&key);
9126 if (ntohs (mh->size) != sizeof(body))
9127 {
9128 GNUNET_break_op (0);
9129 finish_cmc_handling (cmc);
9130 return;
9131 }
9132 /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
9133 switch (ntohs (mh->type))
9134 {
9136 GNUNET_break_op (0);
9137 finish_cmc_handling (cmc);
9138 return;
9139
9141 GNUNET_break_op (0);
9142 finish_cmc_handling (cmc);
9143 return;
9144
9145 default:
9146 /* permitted, continue */
9147 break;
9148 }
9149 monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time);
9151 "Decrypted backtalk from %s\n",
9152 GNUNET_i2s (&ppay.sender));
9154 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
9155 {
9157 GST_stats,
9158 "# Backchannel messages dropped: monotonic time not increasing",
9159 1,
9160 GNUNET_NO);
9161 finish_cmc_handling (cmc);
9162 return;
9163 }
9164 if ((NULL == b) ||
9165 (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
9166 {
9167 /* Check signature */
9168 struct EphemeralConfirmationPS ec;
9169
9171 ec.target = *GST_my_identity;
9172 ec.ephemeral_key = dvb->ephemeral_key;
9173 ec.purpose.size = htonl (sizeof(ec));
9174 ec.sender_monotonic_time = ppay.monotonic_time;
9175 if (
9176 GNUNET_OK !=
9179 &ec,
9180 &ppay.sender_sig,
9181 &ppay.sender.public_key))
9182 {
9183 /* Signature invalid, discard! */
9184 GNUNET_break_op (0);
9185 finish_cmc_handling (cmc);
9186 return;
9187 }
9188 }
9189 /* Update sender, we now know the real origin! */
9191 "DVBox received for me from %s via %s\n",
9192 GNUNET_i2s2 (&ppay.sender),
9193 GNUNET_i2s (&cmc->im.sender));
9194 cmc->im.sender = ppay.sender;
9195
9196 if (NULL != b)
9197 {
9198 /* update key cache and mono time */
9199 b->last_ephemeral = dvb->ephemeral_key;
9200 b->monotonic_time = monotime;
9202 b->timeout =
9204 cmc->mh = mh;
9206 return;
9207 }
9208 /* setup data structure to cache signature AND check
9209 monotonic time with PEERSTORE before forwarding backchannel payload */
9210 b = GNUNET_malloc (sizeof(struct Backtalker) + sizeof(body));
9211 b->pid = ppay.sender;
9212 b->body_size = sizeof(body);
9213 memcpy (&b[1], body, sizeof(body));
9217 &b->pid,
9218 b,
9220 b->monotonic_time = monotime; /* NOTE: to be checked still! */
9221 b->cmc = cmc;
9222 b->timeout =
9225 b->get =
9227 "transport",
9228 &b->pid,
9231 b);
9232 } /* end actual decryption */
9233}

References GNUNET_TIME_Absolute::abs_value_us, BACKCHANNEL_INACTIVITY_TIMEOUT, backtalker_monotime_cb(), backtalker_timeout_cb(), backtalkers, Backtalker::body_size, Backtalker::cmc, DecapsDvBoxCls::cmc, demultiplex_with_cmc(), dv_decrypt(), dv_hmac(), dv_key_clean(), dv_setup_key_state_from_km(), EphemeralConfirmationPS::ephemeral_key, TransportDVBoxMessage::ephemeral_key, finish_cmc_handling(), Backtalker::get, GNUNET_ALIGN, GNUNET_assert, GNUNET_break_op, GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multipeermap_get(), GNUNET_CONTAINER_multipeermap_put(), GNUNET_CRYPTO_eddsa_verify, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_i2s(), GNUNET_i2s2(), GNUNET_log, GNUNET_malloc, GNUNET_memcmp, GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX, GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN, GNUNET_NO, GNUNET_OK, GNUNET_PEERSTORE_iteration_start(), GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME, GNUNET_SCHEDULER_add_at(), GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL, GNUNET_STATISTICS_update(), GNUNET_TIME_absolute_ntoh(), GNUNET_TIME_relative_to_absolute(), GNUNET_YES, GST_my_identity, GST_stats, TransportDVBoxMessage::hmac, CommunicatorMessageContext::im, TransportDVBoxMessage::iv, key, Backtalker::last_ephemeral, mh, CommunicatorMessageContext::mh, TransportDVBoxPayloadP::monotonic_time, Backtalker::monotonic_time, PilsRequest::op, TransportDVBoxMessage::orig_size, peerstore, Backtalker::pid, pils_requests_head, pils_requests_tail, DecapsDvBoxCls::pr, GNUNET_PeerIdentity::public_key, GNUNET_CRYPTO_EccSignaturePurpose::purpose, EphemeralConfirmationPS::purpose, TransportDVBoxPayloadP::sender, GNUNET_TRANSPORT_IncomingMessage::sender, EphemeralConfirmationPS::sender_monotonic_time, TransportDVBoxPayloadP::sender_sig, GNUNET_CRYPTO_EccSignaturePurpose::size, EphemeralConfirmationPS::target, Backtalker::task, Backtalker::timeout, TransportDVBoxMessage::total_hops, and update_backtalker_monotime().

Referenced by handle_dv_box().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_dv_box()

static void handle_dv_box ( void *  cls,
const struct TransportDVBoxMessage dvb 
)
static

Communicator gave us a DV box.

Process the request.

Parameters
clsa struct CommunicatorMessageContext (must call finish_cmc_handling() when done)
dvbthe message that was received

Definition at line 9244 of file gnunet-service-transport.c.

9245{
9246 struct CommunicatorMessageContext *cmc = cls;
9247 uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
9248 uint16_t num_hops = ntohs (dvb->num_hops);
9249 const struct GNUNET_PeerIdentity *hops =
9250 (const struct GNUNET_PeerIdentity *) &dvb[1];
9251 const char *enc_payload = (const char *) &hops[num_hops];
9252 uint16_t enc_payload_size =
9253 size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
9254 struct DecapsDvBoxCls *decaps_dv_box_cls;
9255
9256 if (GNUNET_EXTRA_LOGGING > 0)
9257 {
9258 char *path;
9259
9261 for (unsigned int i = 0; i < num_hops; i++)
9262 {
9263 char *tmp;
9264
9265 GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
9266 GNUNET_free (path);
9267 path = tmp;
9268 }
9270 "Received DVBox with remaining path %s\n",
9271 path);
9272 GNUNET_free (path);
9273 }
9274
9275 if (num_hops > 0)
9276 {
9277 /* We're trying from the end of the hops array, as we may be
9278 able to find a shortcut unknown to the origin that way */
9279 for (int i = num_hops - 1; i >= 0; i--)
9280 {
9281 struct Neighbour *n;
9282
9283 if (0 == GNUNET_memcmp (&hops[i], GST_my_identity))
9284 {
9285 GNUNET_break_op (0);
9286 finish_cmc_handling (cmc);
9287 return;
9288 }
9289 n = lookup_neighbour (&hops[i]);
9290 if (NULL == n)
9291 continue;
9293 "Skipping %u/%u hops ahead while routing DV Box\n",
9294 i,
9295 num_hops);
9296
9297 forward_dv_box (n,
9298 (struct TransportDVBoxMessage *) dvb,
9299 ntohs (dvb->total_hops) + 1,
9300 num_hops - i - 1, /* number of hops left */
9301 &hops[i + 1], /* remaining hops */
9302 enc_payload,
9303 enc_payload_size);
9305 "# DV hops skipped routing boxes",
9306 i,
9307 GNUNET_NO);
9309 "# DV boxes routed (total)",
9310 1,
9311 GNUNET_NO);
9312 finish_cmc_handling (cmc);
9313 return;
9314 }
9315 /* Woopsie, next hop not in neighbours, drop! */
9317 "# DV Boxes dropped: next hop unknown",
9318 1,
9319 GNUNET_NO);
9320 finish_cmc_handling (cmc);
9321 return;
9322 }
9323 /* We are the target. Unbox and handle message. */
9325 "# DV boxes opened (ultimate target)",
9326 1,
9327 GNUNET_NO);
9328 cmc->total_hops = ntohs (dvb->total_hops);
9329
9330 {
9331 // DH key derivation with received DV, could be garbage.
9332 decaps_dv_box_cls = GNUNET_new (struct DecapsDvBoxCls);
9333 decaps_dv_box_cls->cmc = cmc;
9334 decaps_dv_box_cls->dvb = dvb;
9335 decaps_dv_box_cls->pr = GNUNET_new (struct PilsRequest);
9336
9339 decaps_dv_box_cls->pr);
9340 decaps_dv_box_cls->pr->op = GNUNET_PILS_kem_decaps (pils,
9341 &dvb->ephemeral_key,
9343 decaps_dv_box_cls);
9344 }
9345 // TODO keep track of cls and potentially clean
9346}

References DecapsDvBoxCls::cmc, decaps_dv_box_cb(), DecapsDvBoxCls::dvb, TransportDVBoxMessage::ephemeral_key, finish_cmc_handling(), forward_dv_box(), GNUNET_asprintf(), GNUNET_break_op, GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_EXTRA_LOGGING, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_memcmp, GNUNET_new, GNUNET_NO, GNUNET_PILS_kem_decaps(), GNUNET_STATISTICS_update(), GNUNET_strdup, GST_my_identity, GST_stats, TransportDVBoxMessage::header, lookup_neighbour(), TransportDVBoxMessage::num_hops, PilsRequest::op, pils, pils_requests_head, pils_requests_tail, DecapsDvBoxCls::pr, GNUNET_MessageHeader::size, size, TransportDVBoxMessage::total_hops, and CommunicatorMessageContext::total_hops.

Here is the call graph for this function:

◆ check_incoming_msg()

static int check_incoming_msg ( void *  cls,
const struct GNUNET_TRANSPORT_IncomingMessage im 
)
static

Client notified us about transmission from a peer.

Process the request.

Parameters
clsa struct TransportClient which sent us the message
imthe send message that was sent
Returns
GNUNET_YES if message is well-formed

Definition at line 9357 of file gnunet-service-transport.c.

9359{
9360 struct TransportClient *tc = cls;
9361
9362 if (CT_COMMUNICATOR != tc->type)
9363 {
9364 GNUNET_break (0);
9365 return GNUNET_SYSERR;
9366 }
9368 return GNUNET_OK;
9369}

References CT_COMMUNICATOR, GNUNET_break, GNUNET_MQ_check_boxed_message, GNUNET_OK, GNUNET_SYSERR, and tc.

◆ check_known_address()

static int check_known_address ( void *  cls,
const struct GNUNET_PeerIdentity pid,
void *  value 
)
static

Test if the validation state in value matches the address from cls.

Parameters
clsa struct CheckKnownAddressContext
pidunused (must match though)
valuea struct ValidationState
Returns
GNUNET_OK if not matching, GNUNET_NO if match found

Definition at line 9399 of file gnunet-service-transport.c.

9402{
9403 struct CheckKnownAddressContext *ckac = cls;
9404 struct ValidationState *vs = value;
9405
9406 (void) pid;
9407 if (0 != strcmp (vs->address, ckac->address))
9408 return GNUNET_OK;
9409 ckac->vs = vs;
9410 return GNUNET_NO;
9411}

References CheckKnownAddressContext::address, GNUNET_NO, GNUNET_OK, pid, value, and CheckKnownAddressContext::vs.

Referenced by start_address_validation().

Here is the caller graph for this function:

◆ validation_start_cb()

static void validation_start_cb ( void *  cls)
static

Task run periodically to validate some address based on validation_heap.

Parameters
clsNULL

Definition at line 12067 of file gnunet-service-transport.c.

12068{
12069 struct ValidationState *vs;
12070 struct Queue *q;
12072 GST_cfg);
12073
12074 (void) cls;
12075 validation_task = NULL;
12077 /* drop validations past their expiration */
12078 while (
12079 (NULL != vs) &&
12081 {
12083 "Validation response %s cleaned up\n",
12084 GNUNET_sh2s (&vs->challenge.value));
12087 }
12088 if (NULL == vs)
12089 {
12091 "Address validation task not scheduled anymore, nothing to do\n");
12092 return; /* woopsie, no more addresses known, should only
12093 happen if we're really a lonely peer */
12094 }
12095 q = find_queue (&vs->pid, vs->address);
12096 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
12097 {
12099 "To early to start next address validation for challenge %s\n",
12100 GNUNET_sh2s (&vs->challenge.value));
12101 return;
12102 }
12103 if (NULL == q)
12104 {
12105 vs->awaiting_queue = GNUNET_YES;
12106 suggest_to_connect (&vs->pid, vs->address);
12107 }
12108 else
12110 /* Finally, reschedule next attempt */
12111 vs->challenge_backoff =
12112 GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
12115 "Address validation task will run again in %s\n",
12116 GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
12117 GNUNET_YES));
12120 vs->challenge_backoff));
12121}

References find_queue(), free_validation_state(), GNUNET_CONTAINER_heap_peek(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_sh2s(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_absolute_cmp, GNUNET_TIME_absolute_get_monotonic(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_randomized_backoff(), GNUNET_TIME_relative_to_absolute(), GNUNET_YES, GST_cfg, MAX_VALIDATION_CHALLENGE_FREQ, ValidationState::pid, q, GNUNET_TIME_Relative::rel_value_us, suggest_to_connect(), update_next_challenge_time(), ValidationState::valid_until, validation_heap, validation_task, and validation_transmit_on_queue().

Referenced by update_next_challenge_time().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_next_challenge_time()

static void update_next_challenge_time ( struct ValidationState vs,
struct GNUNET_TIME_Absolute  new_time 
)
static

Set the time for next_challenge of vs to new_time.

Updates the heap and if necessary reschedules the job.

Parameters
vsvalidation state to update
new_timenew time for revalidation

Definition at line 9431 of file gnunet-service-transport.c.

9433{
9435
9436 if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
9437 return; /* be lazy */
9438 vs->next_challenge = new_time;
9439 if (NULL == vs->hn)
9440 vs->hn =
9442 else
9445 (NULL != validation_task))
9446 return;
9447 if (NULL != validation_task)
9449 /* randomize a bit */
9452 MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
9453 new_time = GNUNET_TIME_absolute_add (new_time, delta);
9456}

References GNUNET_TIME_Absolute::abs_value_us, delta, GNUNET_CONTAINER_heap_insert(), GNUNET_CONTAINER_heap_peek(), GNUNET_CONTAINER_heap_update_cost(), GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u64(), GNUNET_SCHEDULER_add_at(), GNUNET_SCHEDULER_cancel(), GNUNET_TIME_absolute_add(), MIN_DELAY_ADDRESS_VALIDATION, GNUNET_TIME_Relative::rel_value_us, validation_heap, validation_start_cb(), and validation_task.

Referenced by handle_validation_response(), revalidation_start_cb(), start_address_validation(), and validation_start_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ start_address_validation()

static void start_address_validation ( const struct GNUNET_PeerIdentity pid,
const char *  address 
)
static

Start address validation.

Parameters
pidpeer the address is for
addressan address to reach pid (presumably)

Definition at line 9466 of file gnunet-service-transport.c.

9468{
9469 struct GNUNET_TIME_Absolute now;
9470 struct ValidationState *vs;
9471 struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
9472
9474 pid,
9476 &ckac);
9477 if (NULL != (vs = ckac.vs))
9478 {
9479 /* if 'vs' is not currently valid, we need to speed up retrying the
9480 * validation */
9481 if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
9482 {
9483 /* reduce backoff as we got a fresh advertisement */
9484 vs->challenge_backoff =
9487 vs->challenge_backoff,
9488 2));
9491 vs->challenge_backoff));
9492 }
9493 return;
9494 }
9496 vs = GNUNET_new (struct ValidationState);
9497 vs->pid = *pid;
9498 vs->valid_until =
9500 vs->first_challenge_use = now;
9501 vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
9503 &vs->challenge,
9504 sizeof(vs->challenge));
9505 vs->address = GNUNET_strdup (address);
9506 GNUNET_CRYPTO_hash (vs->address, strlen (vs->address), &vs->hc);
9508 "Starting address validation `%s' of peer %s using challenge %s\n",
9509 address,
9510 GNUNET_i2s (pid),
9511 GNUNET_sh2s (&vs->challenge.value));
9515 &vs->pid,
9516 vs,
9519}

References GNUNET_TIME_Absolute::abs_value_us, address, CheckKnownAddressContext::address, ADDRESS_VALIDATION_LIFETIME, check_known_address(), FAST_VALIDATION_CHALLENGE_FREQ, GNUNET_assert, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE, GNUNET_CONTAINER_multipeermap_get_multiple(), GNUNET_CONTAINER_multipeermap_put(), GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_QUALITY_NONCE, GNUNET_CRYPTO_random_block(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_new, GNUNET_sh2s(), GNUNET_strdup, GNUNET_TIME_absolute_get_monotonic(), GNUNET_TIME_relative_divide(), GNUNET_TIME_relative_min(), GNUNET_TIME_relative_to_absolute(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, GST_cfg, ValidationState::pid, pid, update_next_challenge_time(), ValidationState::valid_until, ValidationState::validated_until, validation_map, and CheckKnownAddressContext::vs.

Referenced by handle_add_queue_message(), handle_request_hello_validation(), hello_for_client_cb(), hello_for_incoming_cb(), and sign_t_validation_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_queue()

static struct Queue * find_queue ( const struct GNUNET_PeerIdentity pid,
const char *  address 
)
static

Find the queue matching pid and address.

Parameters
pidpeer the queue must go to
addressaddress the queue must use
Returns
NULL if no such queue exists

Definition at line 9842 of file gnunet-service-transport.c.

9843{
9844 struct Neighbour *n;
9845
9846 n = lookup_neighbour (pid);
9847 if (NULL == n)
9848 return NULL;
9849 for (struct Queue *pos = n->queue_head; NULL != pos;
9850 pos = pos->next_neighbour)
9851 {
9852 if (0 == strcmp (pos->address, address))
9853 return pos;
9854 }
9855 return NULL;
9856}

References address, lookup_neighbour(), pid, and Neighbour::queue_head.

Referenced by handle_request_hello_validation(), handle_validation_response(), hello_for_client_cb(), hello_for_incoming_cb(), revalidation_start_cb(), and validation_start_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ suggest_to_connect()

static void suggest_to_connect ( const struct GNUNET_PeerIdentity pid,
const char *  address 
)
static

Signature of a function called with a communicator address of a peer pid that an application wants us to connect to.

Parameters
pidtarget peer
addressthe address to try

Definition at line 11963 of file gnunet-service-transport.c.

11964{
11965 static uint32_t idgen = 0;
11966 struct TransportClient *tc;
11967 char *prefix;
11968 struct GNUNET_TRANSPORT_CreateQueue *cqm;
11969 struct GNUNET_MQ_Envelope *env;
11970 size_t alen;
11971
11973 if (NULL == prefix)
11974 {
11975 GNUNET_break (0); /* We got an invalid address!? */
11976 return;
11977 }
11979 if (NULL == tc)
11980 {
11982 "# Suggestions ignored due to missing communicator",
11983 1,
11984 GNUNET_NO);
11986 "Cannot connect to %s at `%s', no matching communicator present\n",
11987 GNUNET_i2s (pid),
11988 address);
11990 return;
11991 }
11992 /* forward suggestion for queue creation to communicator */
11994 "Request #%u for `%s' communicator to create queue to `%s' at `%s'\n",
11995 (unsigned int) idgen,
11996 prefix,
11997 GNUNET_i2s (pid),
11998 address);
12000 alen = strlen (address) + 1;
12001 env =
12003 cqm->request_id = htonl (idgen++);
12004 cqm->receiver = *pid;
12005 memcpy (&cqm[1], address, alen);
12006 GNUNET_MQ_send (tc->mq, env);
12007}

References address, env, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_HELLO_address_to_prefix(), GNUNET_i2s(), GNUNET_log, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_NO, GNUNET_STATISTICS_update(), GST_stats, lookup_communicator(), pid, prefix, GNUNET_TRANSPORT_CreateQueue::receiver, GNUNET_TRANSPORT_CreateQueue::request_id, and tc.

Referenced by handle_request_hello_validation(), hello_for_client_cb(), hello_for_incoming_cb(), revalidation_start_cb(), and validation_start_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ hello_for_incoming_cb()

static void hello_for_incoming_cb ( void *  cls,
const struct GNUNET_PeerIdentity pid,
const char *  uri 
)
static

Definition at line 9531 of file gnunet-service-transport.c.

9534{
9535 struct Queue *q;
9536 int pfx_len;
9537 const char *eou;
9538 char *address;
9539 (void) cls;
9540
9541 eou = strstr (uri,
9542 "://");
9543 pfx_len = eou - uri;
9544 eou += 3;
9546 "%.*s-%s",
9547 pfx_len,
9548 uri,
9549 eou);
9550
9552 "helo for client %s\n",
9553 address);
9554 q = find_queue (pid, address);
9555 if (NULL == q)
9556 {
9558 }
9559 else
9562}

References address, find_queue(), GNUNET_asprintf(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, pid, q, start_address_validation(), suggest_to_connect(), and uri.

Referenced by handle_hello_for_incoming().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_hello_for_incoming()

static void handle_hello_for_incoming ( void *  cls,
const struct GNUNET_PEERSTORE_Record record,
const char *  emsg 
)
static

Function called by PEERSTORE for each matching record.

Parameters
clsclosure, a struct IncomingRequest
recordpeerstore record information
emsgerror message, or NULL if no errors

Definition at line 9573 of file gnunet-service-transport.c.

9576{
9577 struct IncomingRequest *ir = cls;
9579 struct GNUNET_MessageHeader *hello;
9580
9581 if (NULL != emsg)
9582 {
9584 "Got failure from PEERSTORE: %s\n",
9585 emsg);
9586 return;
9587 }
9588 hello = record->value;
9589 if (0 == GNUNET_memcmp (&record->peer, GST_my_identity))
9590 {
9592 return;
9593 }
9597 NULL);
9598 GNUNET_HELLO_parser_free (parser);
9599}

References GNUNET_ERROR_TYPE_WARNING, GNUNET_HELLO_parser_free(), GNUNET_HELLO_parser_from_msg(), GNUNET_HELLO_parser_iterate(), GNUNET_log, GNUNET_memcmp, GNUNET_PEERSTORE_monitor_next(), GST_my_identity, hello_for_incoming_cb(), IncomingRequest::nc, and record().

Referenced by sign_t_validation_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ hello_for_incoming_error_cb()

static void hello_for_incoming_error_cb ( void *  cls)
static

Definition at line 9603 of file gnunet-service-transport.c.

9604{
9606 "Error in PEERSTORE monitoring\n");
9607}

References GNUNET_ERROR_TYPE_WARNING, and GNUNET_log.

Referenced by sign_t_validation_cb().

Here is the caller graph for this function:

◆ hello_for_incoming_sync_cb()

static void hello_for_incoming_sync_cb ( void *  cls)
static

Definition at line 9611 of file gnunet-service-transport.c.

9612{
9614 "Done with initial PEERSTORE iteration during monitoring\n");
9615}

References GNUNET_ERROR_TYPE_WARNING, and GNUNET_log.

Referenced by sign_t_validation_cb().

Here is the caller graph for this function:

◆ sign_t_validation_cb()

static void sign_t_validation_cb ( void *  cls,
const struct GNUNET_PeerIdentity pid,
const struct GNUNET_CRYPTO_EddsaSignature sig 
)
static

Definition at line 9627 of file gnunet-service-transport.c.

9630{
9631 struct SignTValidationCls *sign_t_validation_cls = cls;
9632 struct CommunicatorMessageContext *cmc = sign_t_validation_cls->cmc;
9633 struct TransportValidationResponseMessage tvr = sign_t_validation_cls->tvr;
9634 struct VirtualLink *vl;
9635 struct Neighbour *n;
9636 struct IncomingRequest *ir;
9637 struct GNUNET_PeerIdentity sender;
9638
9639 sign_t_validation_cls->pr->op = NULL;
9642 sign_t_validation_cls->pr);
9643 GNUNET_free (sign_t_validation_cls->pr);
9644 tvr.signature = *sig;
9645 sender = cmc->im.sender;
9646 vl = lookup_virtual_link (&sender);
9647 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9648 {
9649 // route_control_message_without_fc (&cmc->im.sender,
9651 &tvr.header,
9653 }
9654 else
9655 {
9656 /* Use route via neighbour */
9657 n = lookup_neighbour (&sender);
9658 if (NULL != n)
9659 route_via_neighbour (n, &tvr.header,
9662 }
9663
9664 finish_cmc_handling (cmc);
9665 if (NULL != vl)
9666 return;
9667
9668 /* For us, the link is still down, but we need bi-directional
9669 connections (for flow-control and for this to be useful for
9670 CORE), so we must try to bring the link up! */
9671
9672 /* (1) Check existing queues, if any, we may be lucky! */
9673 n = lookup_neighbour (&sender);
9674 if (NULL != n)
9675 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
9676 start_address_validation (&sender, q->address);
9677 /* (2) Also try to see if we have addresses in PEERSTORE for this peer
9678 we could use */
9679 for (ir = ir_head; NULL != ir; ir = ir->next)
9680 if (0 == GNUNET_memcmp (&ir->pid, &sender))
9681 return;
9682 /* we are already trying */
9683 ir = GNUNET_new (struct IncomingRequest);
9684 ir->pid = sender;
9686
9688 GNUNET_YES,
9689 "peerstore",
9690 NULL,
9693 NULL,
9695 NULL,
9697 ir);
9698 ir_total++;
9699 /* Bound attempts we do in parallel here, might otherwise get excessive */
9702};

References SignTValidationCls::cmc, VirtualLink::confirmed, finish_cmc_handling(), free_incoming_request(), GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_memcmp, GNUNET_new, GNUNET_PEERSTORE_HELLO_KEY, GNUNET_PEERSTORE_monitor_start(), GNUNET_YES, GST_cfg, handle_hello_for_incoming(), TransportValidationResponseMessage::header, hello_for_incoming_error_cb(), hello_for_incoming_sync_cb(), CommunicatorMessageContext::im, ir_head, ir_tail, ir_total, lookup_neighbour(), lookup_virtual_link(), MAX_INCOMING_REQUEST, IncomingRequest::nc, IncomingRequest::next, PilsRequest::op, IncomingRequest::pid, pils_requests_head, pils_requests_tail, SignTValidationCls::pr, q, Neighbour::queue_head, RMO_ANYTHING_GOES, RMO_REDUNDANT, RMO_UNCONFIRMED_ALLOWED, route_control_message_without_fc(), route_via_neighbour(), GNUNET_TRANSPORT_IncomingMessage::sender, TransportValidationResponseMessage::signature, start_address_validation(), and SignTValidationCls::tvr.

Referenced by handle_validation_challenge().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_validation_challenge()

static void handle_validation_challenge ( void *  cls,
const struct TransportValidationChallengeMessage tvc 
)
static

Communicator gave us a transport address validation challenge.

Process the request.

Parameters
clsa struct CommunicatorMessageContext (must call finish_cmc_handling() when done)
tvcthe message that was received

Definition at line 9714 of file gnunet-service-transport.c.

9717{
9718 struct CommunicatorMessageContext *cmc = cls;
9720 struct GNUNET_TIME_RelativeNBO validity_duration;
9721
9722 /* DV-routed messages are not allowed for validation challenges */
9723 if (cmc->total_hops > 0)
9724 {
9725 GNUNET_break_op (0);
9726 finish_cmc_handling (cmc);
9727 return;
9728 }
9729 validity_duration = cmc->im.expected_address_validity;
9731 "Received address validation challenge %s\n",
9732 GNUNET_sh2s (&tvc->challenge.value));
9733 /* If we have a virtual link, we use this mechanism to signal the
9734 size of the flow control window, and to allow the sender
9735 to ask for increases. If for us the virtual link is still down,
9736 we will always give a window size of zero. */
9737 tvr.header.type =
9739 tvr.header.size = htons (sizeof(tvr));
9740 tvr.reserved = htonl (0);
9741 tvr.challenge = tvc->challenge;
9742 tvr.origin_time = tvc->sender_time;
9743 tvr.validity_duration = validity_duration;
9744 {
9745 /* create signature */
9746 struct TransportValidationPS tvp = {
9748 .purpose.size = htonl (sizeof(tvp)),
9749 .validity_duration = validity_duration,
9750 .challenge = tvc->challenge
9751 };
9752 struct SignTValidationCls *sign_t_validation_cls;
9753
9754 sign_t_validation_cls = GNUNET_new (struct SignTValidationCls);
9755 sign_t_validation_cls->cmc = cmc;
9756 sign_t_validation_cls->tvr = tvr;
9757 sign_t_validation_cls->pr = GNUNET_new (struct PilsRequest);
9760 sign_t_validation_cls->pr);
9761 sign_t_validation_cls->pr->op =
9763 &tvp.purpose,
9765 sign_t_validation_cls);
9766 }
9767}

References TransportValidationChallengeMessage::challenge, TransportValidationResponseMessage::challenge, SignTValidationCls::cmc, GNUNET_TRANSPORT_IncomingMessage::expected_address_validity, finish_cmc_handling(), GNUNET_break_op, GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE, GNUNET_new, GNUNET_PILS_sign_by_peer_identity(), GNUNET_sh2s(), GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE, TransportValidationResponseMessage::header, CommunicatorMessageContext::im, PilsRequest::op, pils, pils_requests_head, pils_requests_tail, SignTValidationCls::pr, GNUNET_CRYPTO_EccSignaturePurpose::purpose, TransportValidationPS::purpose, TransportValidationResponseMessage::reserved, TransportValidationChallengeMessage::sender_time, sign_t_validation_cb(), GNUNET_MessageHeader::size, CommunicatorMessageContext::total_hops, SignTValidationCls::tvr, GNUNET_MessageHeader::type, TransportValidationPS::validity_duration, and GNUNET_CRYPTO_ChallengeNonceP::value.

Here is the call graph for this function:

◆ check_known_challenge()

static int check_known_challenge ( void *  cls,
const struct GNUNET_PeerIdentity pid,
void *  value 
)
static

Test if the validation state in value matches the challenge from cls.

Parameters
clsa struct CheckKnownChallengeContext
pidunused (must match though)
valuea struct ValidationState
Returns
GNUNET_OK if not matching, GNUNET_NO if match found

Definition at line 9797 of file gnunet-service-transport.c.

9800{
9801 struct CheckKnownChallengeContext *ckac = cls;
9802 struct ValidationState *vs = value;
9803
9804 (void) pid;
9805 if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
9806 return GNUNET_OK;
9807 ckac->vs = vs;
9808 return GNUNET_NO;
9809}

References CheckKnownChallengeContext::challenge, GNUNET_memcmp, GNUNET_NO, GNUNET_OK, pid, value, and CheckKnownChallengeContext::vs.

Referenced by handle_validation_response().

Here is the caller graph for this function:

◆ peerstore_store_validation_cb()

static void peerstore_store_validation_cb ( void *  cls,
int  success 
)
static

Function called when peerstore is done storing a validated address.

Parameters
clsa struct ValidationState
successGNUNET_YES on success

Definition at line 9820 of file gnunet-service-transport.c.

9821{
9822 struct ValidationState *vs = cls;
9823
9824 vs->sc = NULL;
9825 if (GNUNET_YES == success)
9826 return;
9828 "# Peerstore failed to store foreign address",
9829 1,
9830 GNUNET_NO);
9831}

References GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_YES, and GST_stats.

Referenced by handle_validation_response().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ validation_transmit_on_queue()

static void validation_transmit_on_queue ( struct Queue q,
struct ValidationState vs 
)
static

The queue q (which matches the peer and address in vs) is ready for queueing.

We should now queue the validation request.

Parameters
qqueue to send on
vsstate to derive validation challenge from

Definition at line 12018 of file gnunet-service-transport.c.

12019{
12021 struct GNUNET_TIME_Absolute monotonic_time;
12022
12023 if (NULL != vs->revalidation_task)
12024 {
12025 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
12026 vs->revalidation_task = NULL;
12027 }
12028 /*memcpy (&hkey,
12029 &hc,
12030 sizeof (hkey));*/
12032 "Remove key %s for address %s map size %u contains %u\n",
12033 GNUNET_h2s (&vs->hc),
12034 vs->address,
12037 &vs->hc));
12039
12041 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
12042 vs->last_challenge_use.abs_value_us)
12043 {
12044 vs->first_challenge_use = monotonic_time;
12045 }
12046 vs->last_challenge_use = monotonic_time;
12047 tvc.header.type =
12049 tvc.header.size = htons (sizeof(tvc));
12050 tvc.reserved = htonl (0);
12051 tvc.challenge = vs->challenge;
12052 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
12054 "Sending address validation challenge %s to %s\n",
12055 GNUNET_sh2s (&tvc.challenge.value),
12056 GNUNET_i2s (&q->neighbour->pid));
12057 queue_send_msg (q, NULL, &tvc, sizeof(tvc));
12058}

References TransportValidationChallengeMessage::challenge, GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_CONTAINER_multihashmap_size(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_h2s(), GNUNET_i2s(), GNUNET_log, GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE, GNUNET_SCHEDULER_cancel(), GNUNET_sh2s(), GNUNET_TIME_absolute_get_monotonic(), GNUNET_TIME_absolute_hton(), GNUNET_TIME_UNIT_ZERO_ABS, GST_cfg, TransportValidationChallengeMessage::header, q, queue_send_msg(), TransportValidationChallengeMessage::reserved, revalidation_map, TransportValidationChallengeMessage::sender_time, GNUNET_MessageHeader::size, GNUNET_MessageHeader::type, and GNUNET_CRYPTO_ChallengeNonceP::value.

Referenced by check_validation_request_pending(), revalidation_start_cb(), and validation_start_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ revalidation_start_cb()

static void revalidation_start_cb ( void *  cls)
static

Definition at line 9863 of file gnunet-service-transport.c.

9864{
9865 struct ValidationState *vs = cls;
9866 struct Queue *q;
9867 struct GNUNET_TIME_Absolute now;
9868
9869 vs->revalidation_task = NULL;
9870 q = find_queue (&vs->pid, vs->address);
9871 if (NULL == q)
9872 {
9873 now = GNUNET_TIME_absolute_get ();
9874 vs->awaiting_queue = GNUNET_YES;
9875 suggest_to_connect (&vs->pid, vs->address);
9877 }
9878 else
9880}

References find_queue(), GNUNET_TIME_absolute_get(), GNUNET_YES, ValidationState::pid, q, suggest_to_connect(), update_next_challenge_time(), and validation_transmit_on_queue().

Referenced by handle_validation_response().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ revalidate_map_it()

static enum GNUNET_GenericReturnValue revalidate_map_it ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Definition at line 9884 of file gnunet-service-transport.c.

9888{
9889 (void) cls;
9891 "Key in revalidate map %s \n",
9892 GNUNET_h2s (key));
9893 return GNUNET_YES;
9894}

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_YES, and key.

Referenced by handle_validation_response().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_validation_response()

static void handle_validation_response ( void *  cls,
const struct TransportValidationResponseMessage tvr 
)
static

Communicator gave us a transport address validation response.

Process the request.

Parameters
clsa struct CommunicatorMessageContext (must call finish_cmc_handling() when done)
tvrthe message that was received

Definition at line 9906 of file gnunet-service-transport.c.

9909{
9910 struct CommunicatorMessageContext *cmc = cls;
9911 struct ValidationState *vs;
9912 struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
9913 .vs = NULL};
9914 struct GNUNET_TIME_Absolute origin_time;
9915 struct Queue *q;
9916 struct Neighbour *n;
9917 struct VirtualLink *vl;
9919 GST_cfg);
9920
9921 /* check this is one of our challenges */
9923 &cmc->im.sender,
9925 &ckac);
9926 if (NULL == (vs = ckac.vs))
9927 {
9928 /* This can happen simply if we 'forgot' the challenge by now,
9929 i.e. because we received the validation response twice */
9931 "# Validations dropped, challenge unknown",
9932 1,
9933 GNUNET_NO);
9935 "Validation response %s dropped, challenge unknown\n",
9936 GNUNET_sh2s (&tvr->challenge.value));
9937 finish_cmc_handling (cmc);
9938 return;
9939 }
9940
9941 /* sanity check on origin time */
9942 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
9943 if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
9944 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
9945 {
9947 "Diff first use %" PRIu64 " and last use %" PRIu64 "\n",
9948 vs->first_challenge_use.abs_value_us - origin_time.abs_value_us,
9949 origin_time.abs_value_us - vs->last_challenge_use.abs_value_us);
9950 GNUNET_break_op (0);
9951 finish_cmc_handling (cmc);
9952 return;
9953 }
9954
9955 {
9956 /* check signature */
9957 struct TransportValidationPS tvp = {
9959 .purpose.size = htonl (sizeof(tvp)),
9960 .validity_duration = tvr->validity_duration,
9961 .challenge = tvr->challenge
9962 };
9963
9964 if (
9965 GNUNET_OK !=
9967 &tvp,
9968 &tvr->signature,
9969 &cmc->im.sender.public_key))
9970 {
9971 GNUNET_break_op (0);
9972 finish_cmc_handling (cmc);
9973 return;
9974 }
9975 }
9976
9977 /* validity is capped by our willingness to keep track of the
9978 validation entry and the maximum the other peer allows */
9981 tvr->validity_duration),
9983 vs->validated_until =
9987 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
9988 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
9990 &vs->challenge,
9991 sizeof(vs->challenge));
9992 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
9993 vs->validated_until,
9994 GNUNET_TIME_relative_multiply (vs->validation_rtt,
9996 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, <, now))
9997 {
9999 "First challenge use is now %" PRIu64 " %s \n",
10000 vs->first_challenge_use.abs_value_us,
10001 GNUNET_sh2s (&vs->challenge.value));
10002 vs->first_challenge_use = now;
10003 }
10004 else
10006 "First challenge use is later %" PRIu64 " %s \n",
10007 vs->first_challenge_use.abs_value_us,
10008 GNUNET_sh2s (&vs->challenge.value));
10009 vs->last_challenge_use =
10010 GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
10011 update_next_challenge_time (vs, vs->first_challenge_use);
10013 "Validation response %s from %s accepted, address valid until %s\n",
10014 GNUNET_sh2s (&tvr->challenge.value),
10015 GNUNET_i2s (&cmc->im.sender),
10017 /*memcpy (&hkey,
10018 &hc,
10019 sizeof (hkey));*/
10021 "Key %s for address %s map size %u contains %u\n",
10022 GNUNET_h2s (&vs->hc),
10023 vs->address,
10026 &vs->hc));
10030 &vs->hc,
10031 vs,
10035 NULL);
10036 vs->revalidation_task =
10041 "transport",
10042 &cmc->im.sender,
10044 vs->address,
10045 strlen (vs->address) + 1,
10046 vs->valid_until,
10049 vs);
10050 finish_cmc_handling (cmc);
10051
10052 /* Finally, we now possibly have a confirmed (!) working queue,
10053 update queue status (if queue still is around) */
10054 q = find_queue (&vs->pid, vs->address);
10055 if (NULL == q)
10056 {
10058 "# Queues lost at time of successful validation",
10059 1,
10060 GNUNET_NO);
10061 return;
10062 }
10063 q->validated_until = vs->validated_until;
10064 q->pd.aged_rtt = vs->validation_rtt;
10065 n = q->neighbour;
10066 vl = lookup_virtual_link (&vs->pid);
10067 if (NULL == vl)
10068 {
10069 vl = GNUNET_new (struct VirtualLink);
10071 "Creating new virtual link %p to %s using direct neighbour!\n",
10072 vl,
10073 GNUNET_i2s (&vs->pid));
10074 vl->burst_addr = NULL;
10075 vl->confirmed = GNUNET_YES;
10076 vl->message_uuid_ctr =
10078 vl->target = n->pid;
10084 links,
10085 &vl->target,
10086 vl,
10088 vl->n = n;
10089 n->vl = vl;
10090 q->idle = GNUNET_YES;
10091 vl->visibility_task =
10092 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
10094 /* We lacked a confirmed connection to the target
10095 before, so tell CORE about it (finally!) */
10098 }
10099 else
10100 {
10101 /* Link was already up, remember n is also now available and we are done */
10102 if (NULL == vl->n)
10103 {
10104 vl->n = n;
10105 n->vl = vl;
10106 if (GNUNET_YES == vl->confirmed)
10108 "Virtual link to %s could now also use direct neighbour!\n",
10109 GNUNET_i2s (&vs->pid));
10110 }
10111 else
10112 {
10113 GNUNET_assert (n == vl->n);
10114 }
10115 if (GNUNET_NO == vl->confirmed)
10116 {
10117 vl->confirmed = GNUNET_YES;
10118 q->idle = GNUNET_YES;
10119 vl->visibility_task =
10120 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
10122 /* We lacked a confirmed connection to the target
10123 before, so tell CORE about it (finally!) */
10126 }
10127 }
10128}

References GNUNET_TIME_Absolute::abs_value_us, ADDRESS_VALIDATION_LIFETIME, VirtualLink::available_fc_window_size, VirtualLink::burst_addr, TransportValidationResponseMessage::challenge, CheckKnownChallengeContext::challenge, check_known_challenge(), check_link_down(), VirtualLink::confirmed, consider_sending_fc(), VirtualLink::core_recv_window, cores_send_connect_info(), DEFAULT_WINDOW_SIZE, find_queue(), finish_cmc_handling(), GNUNET_assert, GNUNET_break, GNUNET_break_op, GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_multihashmap_size(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multipeermap_get_multiple(), GNUNET_CONTAINER_multipeermap_put(), GNUNET_CRYPTO_eddsa_verify, GNUNET_CRYPTO_QUALITY_NONCE, GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_block(), GNUNET_CRYPTO_random_u64(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_i2s(), GNUNET_log, GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_PEERSTORE_store(), GNUNET_PEERSTORE_STOREOPTION_MULTIPLE, GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY, GNUNET_SCHEDULER_add_at(), GNUNET_sh2s(), GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE, GNUNET_STATISTICS_update(), GNUNET_STRINGS_absolute_time_to_string(), GNUNET_TIME_absolute_cmp, GNUNET_TIME_absolute_get_duration(), GNUNET_TIME_absolute_get_monotonic(), GNUNET_TIME_absolute_min(), GNUNET_TIME_absolute_ntoh(), GNUNET_TIME_absolute_subtract(), GNUNET_TIME_relative_min(), GNUNET_TIME_relative_multiply(), GNUNET_TIME_relative_ntoh(), GNUNET_TIME_relative_to_absolute(), GNUNET_TIME_UNIT_MINUTES, GNUNET_TIME_UNIT_ZERO, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_YES, GST_cfg, GST_stats, CommunicatorMessageContext::im, VirtualLink::incoming_fc_window_size, links, lookup_virtual_link(), MAX_ADDRESS_VALID_UNTIL, VirtualLink::message_uuid_ctr, VirtualLink::n, peerstore, peerstore_store_validation_cb(), Neighbour::pid, ValidationState::pid, GNUNET_PeerIdentity::public_key, GNUNET_CRYPTO_EccSignaturePurpose::purpose, TransportValidationPS::purpose, q, RECV_WINDOW_SIZE, revalidate_map_it(), revalidation_map, revalidation_start_cb(), send_msg_from_cache(), GNUNET_TRANSPORT_IncomingMessage::sender, TransportValidationResponseMessage::signature, VirtualLink::target, update_next_challenge_time(), ValidationState::valid_until, ValidationState::validated_until, validation_map, VALIDATION_RTT_BUFFER_FACTOR, GNUNET_CRYPTO_ChallengeNonceP::value, VirtualLink::visibility_task, Neighbour::vl, and CheckKnownChallengeContext::vs.

Here is the call graph for this function:

◆ handle_incoming_msg()

static void handle_incoming_msg ( void *  cls,
const struct GNUNET_TRANSPORT_IncomingMessage im 
)
static

Incoming message.

Process the request.

Parameters
imthe send message that was received

Definition at line 10137 of file gnunet-service-transport.c.

10139{
10140 struct TransportClient *tc = cls;
10141 struct CommunicatorMessageContext *cmc =
10143
10144 cmc->tc = tc;
10145 cmc->im = *im;
10147 "Received message with size %u and flow control id %" PRIu64
10148 " via communicator from peer %s\n",
10149 ntohs (im->header.size),
10150 im->fc_id,
10151 GNUNET_i2s (&im->sender));
10152 cmc->im.neighbour_sender = cmc->im.sender;
10153 cmc->mh = (const struct GNUNET_MessageHeader *) &im[1];
10155}

References demultiplex_with_cmc(), GNUNET_TRANSPORT_IncomingMessage::fc_id, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_new, GNUNET_TRANSPORT_IncomingMessage::header, CommunicatorMessageContext::im, CommunicatorMessageContext::mh, GNUNET_TRANSPORT_IncomingMessage::neighbour_sender, GNUNET_TRANSPORT_IncomingMessage::sender, GNUNET_MessageHeader::size, tc, and CommunicatorMessageContext::tc.

Here is the call graph for this function:

◆ check_flow_control()

static int check_flow_control ( void *  cls,
const struct TransportFlowControlMessage fc 
)
static

Communicator gave us a transport address validation response.

Check the request.

Parameters
clsa struct CommunicatorMessageContext
fcthe message that was received
Returns
GNUNET_YES if message is well-formed

Definition at line 10167 of file gnunet-service-transport.c.

10168{
10169 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10170 (void) cls;
10171
10173 "Flow control header size %u size of addresses %u number of addresses %u size of message struct %lu second struct %lu\n",
10174 ntohs (fc->header.size),
10175 ntohl (fc->size_of_addresses),
10176 ntohl (fc->number_of_addresses),
10177 sizeof(struct TransportFlowControlMessage),
10178 sizeof (struct TransportGlobalNattedAddress));
10179
10180 if (0 == number_of_addresses || ntohs (fc->header.size) == sizeof(struct
10182 + ntohl (fc->number_of_addresses) * sizeof (struct
10184 + ntohl (fc->size_of_addresses))
10185 return GNUNET_OK;
10186 else
10187 {
10188 GNUNET_break_op (0);
10189 return GNUNET_SYSERR;
10190 }
10191}

References GNUNET_break_op, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_OK, GNUNET_SYSERR, TransportFlowControlMessage::header, TransportFlowControlMessage::number_of_addresses, GNUNET_MessageHeader::size, and TransportFlowControlMessage::size_of_addresses.

◆ iterate_address_start_burst()

static void iterate_address_start_burst ( void *  cls,
const struct GNUNET_PeerIdentity pid,
const char *  uri 
)
static

Definition at line 10222 of file gnunet-service-transport.c.

10225{
10226 struct VirtualLink *vl = cls;
10227 const char *slash;
10228 char *address_uri;
10229 char *prefix;
10230 char *uri_without_port;
10231
10232 slash = strrchr (uri, '/');
10233 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
10234 GNUNET_assert (NULL != slash);
10235 slash++;
10236 GNUNET_asprintf (&address_uri,
10237 "%s-%s",
10238 prefix,
10239 slash);
10240
10241 uri_without_port = get_address_without_port (address_uri);
10243 "iterate_address_start_burst %s %s %s %s\n",
10244 uri_without_port,
10245 uri,
10246 address_uri,
10247 slash);
10248 if (0 == strcmp (uri_without_port, slash))
10249 {
10250 vl->burst_addr = GNUNET_strndup (uri_without_port, strlen (uri_without_port)
10251 );
10252 }
10253 else
10254 vl->burst_addr = NULL;
10255
10257 GNUNET_free (uri_without_port);
10258}

References VirtualLink::burst_addr, get_address_without_port(), GNUNET_asprintf(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_strndup, prefix, and uri.

Referenced by check_for_burst_address().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_for_burst_address()

static void check_for_burst_address ( void *  cls,
const struct GNUNET_PEERSTORE_Record record,
const char *  emsg 
)
static

Definition at line 10262 of file gnunet-service-transport.c.

10265{
10266 struct GNUNET_StartBurstCls *sb_cls = cls;
10267 struct VirtualLink *vl = sb_cls->vl;
10268 struct GNUNET_MessageHeader *hello;
10270
10271 if (NULL != emsg)
10272 {
10274 "Got failure from PEERSTORE: %s\n",
10275 emsg);
10276 return;
10277 }
10278 if (NULL == record)
10279 {
10281 "Hello iteration end for %s\n",
10282 GNUNET_i2s (&vl->target));
10283 vl->ic = NULL;
10284 GNUNET_free (sb_cls);
10285 return;
10286 }
10287
10289 "check_for_burst_address\n");
10290 hello = record->value;
10294 vl);
10295 GNUNET_HELLO_parser_free (parser);
10296
10298 GNUNET_free (sb_cls);
10299}

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_HELLO_parser_free(), GNUNET_HELLO_parser_from_msg(), GNUNET_HELLO_parser_iterate(), GNUNET_i2s(), GNUNET_log, GNUNET_PEERSTORE_iteration_stop(), VirtualLink::ic, iterate_address_start_burst(), record(), VirtualLink::sb_cls, VirtualLink::target, and GNUNET_StartBurstCls::vl.

Referenced by queue_burst().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ burst_timeout()

static void burst_timeout ( void *  cls)
static

Definition at line 10303 of file gnunet-service-transport.c.

10304{
10306}

References burst_running, and GNUNET_NO.

Referenced by start_burst().

Here is the caller graph for this function:

◆ start_burst()

static void start_burst ( void *  cls)
static

Definition at line 10310 of file gnunet-service-transport.c.

10311{
10312 struct GNUNET_StartBurstCls *sb_cls = cls;
10313 struct VirtualLink *vl = sb_cls->vl;
10314 struct GNUNET_TRANSPORT_StartBurst *sb;
10315 struct GNUNET_MQ_Envelope *env;
10316 char *uri_without_port = vl->burst_addr;
10317
10318 burst_task = NULL;
10319 /*char buf[strlen (uri_without_port) + 1];
10320
10321 GNUNET_memcpy (buf, uri_without_port, strlen (uri_without_port));
10322 buf[strlen (uri_without_port)] = '\0';*/
10323 env =
10325 strlen (uri_without_port) + 1,
10327 sb->rtt = GNUNET_TIME_relative_hton (sb_cls->rtt);
10328 sb->pid = vl->target;
10329 memcpy (&sb[1], uri_without_port, strlen (uri_without_port) + 1);
10330 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
10331 {
10333 "iterate_address_start_burst client tc prefix %s\n",
10334 tc->details.communicator.address_prefix);
10335 if (CT_COMMUNICATOR != tc->type)
10336 continue;
10337 if (GNUNET_YES == tc->details.communicator.can_burst)
10338 {
10340 "iterate_address_start_burst %s call %lu %u rtt %lu\n",
10341 uri_without_port,
10342 strlen (uri_without_port),
10343 ntohs (sb->header.size),
10344 (unsigned long) sb_cls->rtt.rel_value_us);
10345 GNUNET_MQ_send (tc->mq, env);
10349 60),
10351 NULL);
10352 // TODO We need some algo to choose from available communicators. Can we run two bursts at once? Atm we only implemented udp burst.
10353 break;
10354 }
10355 }
10356 GNUNET_free (env);
10357 GNUNET_free (sb_cls);
10358}

References VirtualLink::burst_addr, burst_running, burst_task, burst_timeout(), burst_timeout_task, clients_head, CT_COMMUNICATOR, env, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_MESSAGE_TYPE_TRANSPORT_START_BURST, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_SCHEDULER_add_delayed(), GNUNET_TIME_relative_hton(), GNUNET_TIME_relative_multiply(), GNUNET_TIME_UNIT_SECONDS, GNUNET_YES, GNUNET_TRANSPORT_StartBurst::header, GNUNET_TRANSPORT_StartBurst::pid, GNUNET_TIME_Relative::rel_value_us, GNUNET_StartBurstCls::rtt, GNUNET_TRANSPORT_StartBurst::rtt, VirtualLink::sb_cls, GNUNET_MessageHeader::size, VirtualLink::target, tc, and GNUNET_StartBurstCls::vl.

Referenced by queue_burst().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ queue_burst()

static void queue_burst ( void *  cls)
static

Definition at line 10362 of file gnunet-service-transport.c.

10363{
10364 struct GNUNET_StartBurstCls *sb_cls = cls;
10365 struct VirtualLink *vl = sb_cls->vl;
10366
10367 if (GNUNET_YES != use_burst)
10368 return;
10370 "burst_task %p ready %s burst addr %s (%p)\n",
10371 burst_task,
10372 sb_cls->sync_ready ? "yes" : "no",
10373 vl->burst_addr,
10374 vl->burst_addr);
10375 if (NULL != burst_task && GNUNET_NO == sb_cls->sync_ready)
10376 {
10378 burst_task = NULL;
10380 return;
10381 }
10382 if (GNUNET_NO == burst_running && NULL != vl->burst_addr && NULL == burst_task
10383 )
10384 {
10386 &start_burst,
10387 sb_cls);
10388 }
10389 else if (NULL == vl->burst_addr)
10390 {
10392 "peerstore",
10393 &vl->target,
10396 sb_cls);
10397 }
10398}

References VirtualLink::burst_addr, burst_running, burst_task, check_for_burst_address(), GNUNET_StartBurstCls::delay, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_NO, GNUNET_PEERSTORE_HELLO_KEY, GNUNET_PEERSTORE_iteration_start(), GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_cancel(), GNUNET_YES, VirtualLink::ic, peerstore, VirtualLink::sb_cls, start_burst(), GNUNET_StartBurstCls::sync_ready, VirtualLink::target, use_burst, and GNUNET_StartBurstCls::vl.

Referenced by handle_flow_control().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_flow_control()

static void handle_flow_control ( void *  cls,
const struct TransportFlowControlMessage fc 
)
static

Communicator gave us a transport address validation response.

Process the request.

Parameters
clsa struct CommunicatorMessageContext (must call finish_cmc_handling() when done)
fcthe message that was received

Definition at line 10410 of file gnunet-service-transport.c.

10411{
10412 struct CommunicatorMessageContext *cmc = cls;
10413 struct VirtualLink *vl;
10415 uint32_t seq;
10416 struct GNUNET_TIME_Absolute st;
10417 uint64_t os;
10418 uint64_t wnd;
10419 uint32_t random;
10420
10422 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
10423 vl = lookup_virtual_link (&cmc->im.sender);
10424 if (NULL == vl)
10425 {
10426 vl = GNUNET_new (struct VirtualLink);
10428 "No virtual link for %p FC creating new unconfirmed virtual link to %s!\n",
10429 vl,
10430 GNUNET_i2s (&cmc->im.sender));
10431 vl->burst_addr = NULL;
10432 vl->confirmed = GNUNET_NO;
10433 vl->message_uuid_ctr =
10435 vl->target = cmc->im.sender;
10441 links,
10442 &vl->target,
10443 vl,
10445 }
10446 if (NULL != vl->n)
10447 {
10448 for (struct Queue *q = vl->n->queue_head; NULL != q; q = q->next_neighbour)
10449 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
10450 }
10451
10453 "remaining %lu timeout for neighbour %p\n",
10454 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout).
10455 rel_value_us,
10456 vl->n);
10457 if (NULL == vl->n ||
10458 0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
10459 {
10460 struct GNUNET_TIME_Relative rtt;
10461 struct GNUNET_BurstSync burst_sync;
10462 struct GNUNET_StartBurstCls *bcls;
10463
10464 bcls = GNUNET_new (struct GNUNET_StartBurstCls);
10465 bcls->vl = vl;
10466 vl->sb_cls = bcls;
10467 if (NULL != vl->dv)
10468 rtt = calculate_rtt (vl->dv);
10469 else
10471 burst_sync.rtt_average = fc->rtt;
10472 bcls->rtt = GNUNET_TIME_relative_ntoh (burst_sync.rtt_average);
10473 burst_sync.sync_ready = fc->sync_ready;
10474
10476 &burst_sync,
10477 &queue_burst,
10478 bcls);
10479 }
10480 if (0 != ntohl (fc->number_of_addresses))
10481 {
10482 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10483 const char *tgnas;
10484 unsigned int off = 0;
10485
10486 tgnas = (const char *) &fc[1];
10487
10488 for (int i = 1; i <= number_of_addresses; i++)
10489 {
10490 struct TransportGlobalNattedAddress *tgna;
10491 char *addr;
10492 unsigned int address_length;
10493
10494 tgna = (struct TransportGlobalNattedAddress*) &tgnas[off];
10495 addr = (char *) &tgna[1];
10496 address_length = ntohl (tgna->address_length);
10497 off += sizeof(struct TransportGlobalNattedAddress) + address_length;
10498
10500 "received address %s length %u\n",
10501 addr,
10502 ntohl (tgna->address_length));
10503
10504 GNUNET_NAT_add_global_address (nh, addr, ntohl (tgna->address_length));
10505 }
10506 }
10508 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
10509 {
10511 "FC dropped: Message out of order\n");
10512 /* out of order, drop */
10514 "# FC dropped: message out of order",
10515 1,
10516 GNUNET_NO);
10517 finish_cmc_handling (cmc);
10518 return;
10519 }
10520 seq = ntohl (fc->seq);
10521 if (seq < vl->last_fc_seq)
10522 {
10523 /* Wrap-around/reset of other peer; start all counters from zero */
10525 }
10526 vl->last_fc_seq = seq;
10527 vl->last_fc_timestamp = st;
10529 os = GNUNET_ntohll (fc->outbound_sent);
10531 (int64_t) (os - vl->incoming_fc_window_size_used);
10533 "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
10534 GNUNET_i2s (&vl->target),
10535 (unsigned int) seq,
10536 (unsigned long long) vl->outbound_fc_window_size,
10537 (long long) vl->incoming_fc_window_size_loss);
10540 UINT32_MAX);
10541 if ((GNUNET_YES == vl->confirmed) && ((wnd < vl->incoming_fc_window_size
10545 != wnd) ||
10546 (0 == random
10548 {
10550 "Consider re-sending our FC message, as clearly the other peer's idea of the window is not up-to-date (%llu vs %llu) or %llu last received differs, or random reply %u\n",
10551 (unsigned long long) wnd,
10552 (unsigned long long) vl->incoming_fc_window_size,
10553 (unsigned long long) vl->last_outbound_window_size_received,
10556 }
10557 if ((wnd == vl->incoming_fc_window_size
10561 (NULL != vl->fc_retransmit_task))
10562 {
10564 "Stopping FC retransmission to %s: peer is current at window %llu\n",
10565 GNUNET_i2s (&vl->target),
10566 (unsigned long long) wnd);
10568 vl->fc_retransmit_task = NULL;
10569 vl->fc_retransmit_count = 0;
10570 }
10572 /* FC window likely increased, check transmission possibilities! */
10574 finish_cmc_handling (cmc);
10575}

References GNUNET_TIME_Absolute::abs_value_us, TransportGlobalNattedAddress::address_length, VirtualLink::available_fc_window_size, VirtualLink::burst_addr, calculate_rtt(), check_vl_transmission(), VirtualLink::confirmed, consider_sending_fc(), VirtualLink::core_recv_window, DEFAULT_WINDOW_SIZE, VirtualLink::dv, FC_NO_CHANGE_REPLY_PROBABILITY, VirtualLink::fc_retransmit_count, VirtualLink::fc_retransmit_task, finish_cmc_handling(), GNUNET_break, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multipeermap_put(), GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u32(), GNUNET_CRYPTO_random_u64(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_is_burst_ready(), GNUNET_log, GNUNET_NAT_add_global_address(), GNUNET_new, GNUNET_NO, GNUNET_ntohll(), GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_update(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_absolute_max(), GNUNET_TIME_absolute_ntoh(), GNUNET_TIME_relative_ntoh(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_YES, GST_stats, CommunicatorMessageContext::im, TransportFlowControlMessage::inbound_window_size, VirtualLink::incoming_fc_window_size, VirtualLink::incoming_fc_window_size_loss, VirtualLink::incoming_fc_window_size_used, VirtualLink::last_fc_seq, VirtualLink::last_fc_timestamp, VirtualLink::last_outbound_window_size_received, links, lookup_virtual_link(), VirtualLink::message_uuid_ctr, VirtualLink::n, nh, TransportFlowControlMessage::number_of_addresses, VirtualLink::outbound_fc_window_size, VirtualLink::outbound_fc_window_size_used, TransportFlowControlMessage::outbound_sent, TransportFlowControlMessage::outbound_window_size, q, queue_burst(), Neighbour::queue_head, RECV_WINDOW_SIZE, GNUNET_StartBurstCls::rtt, TransportFlowControlMessage::rtt, GNUNET_BurstSync::rtt_average, VirtualLink::sb_cls, GNUNET_TRANSPORT_IncomingMessage::sender, TransportFlowControlMessage::sender_time, TransportFlowControlMessage::seq, st, GNUNET_BurstSync::sync_ready, TransportFlowControlMessage::sync_ready, VirtualLink::target, and GNUNET_StartBurstCls::vl.

Here is the call graph for this function:

◆ check_add_queue_message()

static int check_add_queue_message ( void *  cls,
const struct GNUNET_TRANSPORT_AddQueueMessage aqm 
)
static

New queue became available.

Check message.

Parameters
clsthe client
aqmthe send message that was sent

Definition at line 10658 of file gnunet-service-transport.c.

10660{
10661 struct TransportClient *tc = cls;
10662
10663 if (CT_COMMUNICATOR != tc->type)
10664 {
10665 GNUNET_break (0);
10666 return GNUNET_SYSERR;
10667 }
10669 return GNUNET_OK;
10670}

References CT_COMMUNICATOR, GNUNET_break, GNUNET_MQ_check_zero_termination, GNUNET_OK, GNUNET_SYSERR, and tc.

◆ set_pending_message_uuid()

static void set_pending_message_uuid ( struct PendingMessage pm)
static

If necessary, generates the UUID for a pm.

Parameters
pmpending message to generate UUID for.

Definition at line 10679 of file gnunet-service-transport.c.

10680{
10681 if (pm->msg_uuid_set)
10682 return;
10683 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
10684 pm->msg_uuid_set = GNUNET_YES;
10685}

References GNUNET_YES, and pm.

Referenced by extract_box_cb(), fragment_message(), and reliability_box_message().

Here is the caller graph for this function:

◆ prepare_pending_acknowledgement()

static struct PendingAcknowledgement * prepare_pending_acknowledgement ( struct Queue queue,
struct DistanceVectorHop dvh,
struct PendingMessage pm 
)
static

Setup data structure waiting for acknowledgements.

Parameters
queuequeue the pm will be sent over
dvhpath the message will take, may be NULL
pmthe pending message for transmission
Returns
corresponding fresh pending acknowledgement

Definition at line 10697 of file gnunet-service-transport.c.

10700{
10701 struct PendingAcknowledgement *pa;
10702
10703 pa = GNUNET_new (struct PendingAcknowledgement);
10704 pa->queue = queue;
10705 pa->dvh = dvh;
10706 pa->pm = pm;
10707 do
10708 {
10710 &pa->ack_uuid,
10711 sizeof(pa->ack_uuid));
10712 }
10715 &pa->ack_uuid.value,
10716 pa,
10718 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
10719 GNUNET_CONTAINER_MDLL_insert (pm, pm->pa_head, pm->pa_tail, pa);
10720 if (NULL != dvh)
10723 pa->message_size = pm->bytes_msg;
10725 "Waiting for ACKnowledgment `%s' for <%" PRIu64 ">\n",
10727 pm->logging_uuid);
10728 return pa;
10729}

References PendingAcknowledgement::ack_uuid, PendingAcknowledgement::dvh, GNUNET_CONTAINER_MDLL_insert, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multiuuidmap_put(), GNUNET_CRYPTO_QUALITY_NONCE, GNUNET_CRYPTO_random_block(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_new, GNUNET_TIME_absolute_get(), GNUNET_uuid2s(), GNUNET_YES, PendingAcknowledgement::message_size, DistanceVectorHop::pa_head, DistanceVectorHop::pa_tail, pending_acks, PendingAcknowledgement::pm, pm, queue(), PendingAcknowledgement::queue, PendingAcknowledgement::transmission_time, and AcknowledgementUUIDP::value.

Referenced by fragment_message(), and reliability_box_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fragment_message()

static struct PendingMessage * fragment_message ( struct Queue queue,
struct DistanceVectorHop dvh,
struct PendingMessage pm 
)
static

Fragment the given pm to the given mtu.

Adds additional fragments to the neighbour as well. If the mtu is too small, generates and error for the pm and returns NULL.

Parameters
queuewhich queue to fragment for
dvhpath the message will take, or NULL
pmpending message to fragment for transmission
Returns
new message to transmit

Definition at line 10744 of file gnunet-service-transport.c.

10747{
10748 struct PendingAcknowledgement *pa;
10749 struct PendingMessage *ff;
10750 uint16_t mtu;
10751 uint16_t msize;
10752
10753 mtu = (UINT16_MAX == queue->mtu)
10754 ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
10755 : queue->mtu;
10757 "Fragmenting message <%" PRIu64
10758 "> with size %u to %s for MTU %u\n",
10759 pm->logging_uuid,
10760 pm->bytes_msg,
10761 GNUNET_i2s (&pm->vl->target),
10762 (unsigned int) mtu);
10765 "Fragmenting message %" PRIu64 " <%" PRIu64
10766 "> with size %u to %s for MTU %u\n",
10767 pm->msg_uuid.uuid,
10768 pm->logging_uuid,
10769 pm->bytes_msg,
10770 GNUNET_i2s (&pm->vl->target),
10771 (unsigned int) mtu);
10772
10773 /* This invariant is established in #handle_add_queue_message() */
10774 GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
10775
10776 /* select fragment for transmission, descending the tree if it has
10777 been expanded until we are at a leaf or at a fragment that is small
10778 enough
10779 */
10780 ff = pm;
10781 msize = ff->bytes_msg;
10782
10783 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
10784 (ff->frag_off == msize) && (NULL != ff->head_frag))
10785 {
10786 ff = ff->head_frag; /* descent into fragmented fragments */
10787 msize = ff->bytes_msg - sizeof(struct TransportFragmentBoxMessage);
10788 }
10789
10790 if (((ff->bytes_msg > mtu) || (pm == ff)) && (ff->frag_off < msize))
10791 {
10792 /* Did not yet calculate all fragments, calculate next fragment */
10793 struct PendingMessage *frag;
10794 struct TransportFragmentBoxMessage tfb;
10795 const char *orig;
10796 char *msg;
10797 uint16_t fragmax;
10798 uint16_t fragsize;
10799 uint16_t msize_ff;
10800 uint16_t xoff = 0;
10801 pm->frag_count++;
10802
10803 orig = (const char *) &ff[1];
10804 msize_ff = ff->bytes_msg;
10805 if (pm != ff)
10806 {
10807 const struct TransportFragmentBoxMessage *tfbo;
10808
10809 tfbo = (const struct TransportFragmentBoxMessage *) orig;
10810 orig += sizeof(struct TransportFragmentBoxMessage);
10811 msize_ff -= sizeof(struct TransportFragmentBoxMessage);
10812 xoff = ntohs (tfbo->frag_off);
10813 }
10814 fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
10815 fragsize = GNUNET_MIN (msize_ff - ff->frag_off, fragmax);
10816 frag =
10817 GNUNET_malloc (sizeof(struct PendingMessage)
10818 + sizeof(struct TransportFragmentBoxMessage) + fragsize);
10820 "3 created pm %p from pm %p storing vl %p from pm %p\n",
10821 frag,
10822 ff,
10823 pm->vl,
10824 pm);
10826 frag->vl = pm->vl;
10827 frag->frag_parent = ff;
10828 frag->timeout = pm->timeout;
10829 frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
10830 frag->pmt = PMT_FRAGMENT_BOX;
10831 msg = (char *) &frag[1];
10832 tfb.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT);
10833 tfb.header.size =
10834 htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
10835 pa = prepare_pending_acknowledgement (queue, dvh, frag);
10836 tfb.ack_uuid = pa->ack_uuid;
10837 tfb.msg_uuid = pm->msg_uuid;
10838 tfb.frag_off = htons (ff->frag_off + xoff);
10839 tfb.msg_size = htons (pm->bytes_msg);
10840 memcpy (msg, &tfb, sizeof(tfb));
10841 memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
10843 ff->tail_frag, frag);
10844 ff->frag_off += fragsize;
10845 ff = frag;
10846 }
10847
10848 /* Move head to the tail and return it */
10852 ff);
10856 ff);
10857
10858 return ff;
10859}

References TransportFragmentBoxMessage::ack_uuid, PendingAcknowledgement::ack_uuid, PendingMessage::bytes_msg, TransportFragmentBoxMessage::frag_off, PendingMessage::frag_off, PendingMessage::frag_parent, GNUNET_assert, GNUNET_CONTAINER_MDLL_insert, GNUNET_CONTAINER_MDLL_insert_tail, GNUNET_CONTAINER_MDLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_malloc, GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT, GNUNET_MIN, PendingMessage::head_frag, TransportFragmentBoxMessage::header, PendingMessage::logging_uuid, logging_uuid_gen, msg, TransportFragmentBoxMessage::msg_size, TransportFragmentBoxMessage::msg_uuid, pm, PendingMessage::pmt, PMT_FRAGMENT_BOX, prepare_pending_acknowledgement(), queue(), set_pending_message_uuid(), GNUNET_MessageHeader::size, PendingMessage::tail_frag, PendingMessage::timeout, GNUNET_MessageHeader::type, and PendingMessage::vl.

Referenced by transmit_on_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ reliability_box_message()

static struct PendingMessage * reliability_box_message ( struct Queue queue,
struct DistanceVectorHop dvh,
struct PendingMessage pm 
)
static

Reliability-box the given pm.

On error (can there be any), NULL may be returned, otherwise the "replacement" for pm (which should then be added to the respective neighbour's queue instead of pm). If the pm is already fragmented or reliability boxed, or itself an ACK, this function simply returns pm.

Parameters
queuewhich queue to prepare transmission for
dvhpath the message will take, or NULL
pmpending message to box for transmission over unreliabile queue
Returns
new message to transmit

Definition at line 10875 of file gnunet-service-transport.c.

10878{
10880 struct PendingAcknowledgement *pa;
10881 struct PendingMessage *bpm;
10882 char *msg;
10883
10884 if ((PMT_CORE != pm->pmt) && (PMT_DV_BOX != pm->pmt))
10885 return pm; /* already fragmented or reliability boxed, or control message:
10886 do nothing */
10887 if (NULL != pm->bpm)
10888 return pm->bpm; /* already computed earlier: do nothing */
10889 // TODO I guess we do not need this assertion. We might have a DLL with
10890 // fragments, because the MTU changed, and we do not need to fragment anymore.
10891 // But we should keep the fragments until message was completed, because
10892 // the MTU might change again.
10893 // GNUNET_assert (NULL == pm->head_frag);
10894 if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
10895 {
10896 /* failed hard */
10897 GNUNET_break (0);
10899 return NULL;
10900 }
10901
10903
10904 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
10905 + pm->bytes_msg);
10907 "4 created pm %p storing vl %p from pm %p\n",
10908 bpm,
10909 pm->vl,
10910 pm);
10912 bpm->vl = pm->vl;
10913 bpm->frag_parent = pm;
10914 // Why was this needed?
10915 // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
10916 bpm->timeout = pm->timeout;
10918 bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
10920 rbox.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX);
10921 rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
10922 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
10923
10924 rbox.ack_uuid = pa->ack_uuid;
10925 msg = (char *) &bpm[1];
10926 memcpy (msg, &rbox, sizeof(rbox));
10927 memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
10928 pm->bpm = bpm;
10930 "Preparing reliability box for message <%" PRIu64
10931 "> of size %d (%d) to %s on queue %s\n",
10932 pm->logging_uuid,
10933 pm->bytes_msg,
10934 ntohs (((const struct GNUNET_MessageHeader *) &pm[1])->size),
10935 GNUNET_i2s (&pm->vl->target),
10936 queue->address);
10937 return bpm;
10938}

References TransportReliabilityBoxMessage::ack_countdown, TransportReliabilityBoxMessage::ack_uuid, PendingAcknowledgement::ack_uuid, PendingMessage::bpm, PendingMessage::bytes_msg, client_send_response(), PendingMessage::frag_parent, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_malloc, GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX, TransportReliabilityBoxMessage::header, PendingMessage::logging_uuid, logging_uuid_gen, msg, pm, PendingMessage::pmt, PMT_CORE, PMT_DV_BOX, PMT_RELIABILITY_BOX, prepare_pending_acknowledgement(), queue(), set_pending_message_uuid(), GNUNET_MessageHeader::size, size, PendingMessage::timeout, GNUNET_MessageHeader::type, and PendingMessage::vl.

Referenced by transmit_on_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ reorder_root_pm()

static void reorder_root_pm ( struct PendingMessage pm,
struct GNUNET_TIME_Absolute  next_attempt 
)
static

Definition at line 10942 of file gnunet-service-transport.c.

10944{
10945 struct VirtualLink *vl = pm->vl;
10946 struct PendingMessage *pos;
10947
10948 /* re-insert sort in neighbour list */
10952 pm);
10953 pos = vl->pending_msg_tail;
10954 while ((NULL != pos) &&
10956 pos = pos->prev_vl;
10960 pos,
10961 pm);
10962}

References GNUNET_TIME_Absolute::abs_value_us, GNUNET_CONTAINER_MDLL_insert_after, GNUNET_CONTAINER_MDLL_remove, PendingMessage::next_attempt, VirtualLink::pending_msg_head, VirtualLink::pending_msg_tail, pm, PendingMessage::prev_vl, and PendingMessage::vl.

Referenced by update_pm_next_attempt().

Here is the caller graph for this function:

◆ check_next_attempt_tree()

static unsigned int check_next_attempt_tree ( struct PendingMessage pm,
struct PendingMessage root 
)
static

Definition at line 10966 of file gnunet-service-transport.c.

10967{
10968 struct PendingMessage *pos;
10970
10971 pos = pm->head_frag;
10972 while (NULL != pos)
10973 {
10974 if (pos->frags_in_flight_round == pm->frags_in_flight_round ||
10975 GNUNET_NO == check_next_attempt_tree (pos, root))
10977 else
10978 {
10980 break;
10981 }
10982 pos = pos->next_frag;
10983 }
10984
10985 return frags_in_flight;
10986}

References check_next_attempt_tree(), PendingMessage::frags_in_flight, PendingMessage::frags_in_flight_round, GNUNET_NO, GNUNET_YES, PendingMessage::head_frag, PendingMessage::next_frag, and pm.

Referenced by check_next_attempt_tree(), and update_pm_next_attempt().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ harmonize_flight_round()

static void harmonize_flight_round ( struct PendingMessage pm)
static

Definition at line 10990 of file gnunet-service-transport.c.

10991{
10992 struct PendingMessage *pos;
10993
10994 pos = pm->head_frag;
10995 while (NULL != pos)
10996 {
10997 pos->frags_in_flight_round = pm->frags_in_flight_round;
10999 pos = pos->next_frag;
11000 }
11001}

References PendingMessage::frags_in_flight_round, harmonize_flight_round(), PendingMessage::head_frag, PendingMessage::next_frag, and pm.

Referenced by harmonize_flight_round(), and update_pm_next_attempt().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_pm_next_attempt()

static void update_pm_next_attempt ( struct PendingMessage pm,
struct GNUNET_TIME_Absolute  next_attempt 
)
static

Change the value of the next_attempt field of pm to next_attempt and re-order pm in the transmission list as required by the new timestamp.

Parameters
pma pending message to update
next_attempttimestamp to use

Definition at line 11013 of file gnunet-service-transport.c.

11015{
11016 if (NULL == pm->frag_parent)
11017 {
11018 pm->next_attempt = next_attempt;
11020 "Next attempt for message <%" PRIu64 "> set to %" PRIu64 "\n",
11021 pm->logging_uuid,
11022 next_attempt.abs_value_us);
11023 reorder_root_pm (pm, next_attempt);
11024 }
11025 else if ((PMT_RELIABILITY_BOX == pm->pmt) || (PMT_DV_BOX == pm->pmt))// || (PMT_FRAGMENT_BOX == pm->pmt))
11026 {
11027 struct PendingMessage *root = pm->frag_parent;
11028
11029 while (NULL != root->frag_parent)
11030 root = root->frag_parent;
11032 "Next attempt for root message <%" PRIu64 "> set to %s\n",
11033 root->logging_uuid,
11035 root->next_attempt = next_attempt;
11037 }
11038 else
11039 {
11040 struct PendingMessage *root = pm->frag_parent;
11041
11042 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11043 root = root->frag_parent;
11044
11046 "frag_count next attempt %u\n",
11047 root->frag_count);
11048
11049 if (GNUNET_NO == root->frags_in_flight)
11050 {
11051 root->next_attempt = next_attempt;
11053 root->frags_in_flight_round++;
11055 "Next attempt for fragmented message <%" PRIu64 "> (<%" PRIu64
11056 ">)set to %" PRIu64 "\n",
11057 pm->logging_uuid,
11058 root->logging_uuid,
11060 }
11061
11062 pm->next_attempt = root->next_attempt;
11063 pm->frags_in_flight_round = root->frags_in_flight_round;
11065
11066 if (root->bytes_msg == root->frag_off)
11067 root->frags_in_flight = check_next_attempt_tree (root, root);
11068 else
11070
11071 if (GNUNET_NO == root->frags_in_flight)
11072 {
11074 "We have no fragments in flight for message %" PRIu64
11075 ", reorder root! Next attempt is %" PRIu64 "\n",
11076 root->logging_uuid,
11078 if (PMT_DV_BOX == root->pmt)
11079 root = root->frag_parent;
11080 reorder_root_pm (root, root->next_attempt);
11081 // root->next_attempt = GNUNET_TIME_UNIT_ZERO_ABS;
11082 }
11083 else
11084 {
11085 double factor = ((double) root->frag_count - 1)
11086 / (double) root->frag_count;
11087 struct GNUNET_TIME_Relative s1;
11088 struct GNUNET_TIME_Relative s2;
11089 struct GNUNET_TIME_Relative plus_mean =
11092 next_attempt);
11093
11095 "frag_count %u after factor\n",
11096 root->frag_count);
11098 factor);
11099 s2 = GNUNET_TIME_relative_divide (plus,
11100 root->frag_count);
11101 plus_mean = GNUNET_TIME_relative_add (s1, s2);
11104 "We have fragments in flight for message %" PRIu64
11105 ", do not reorder root! Actual next attempt %" PRIu64 "\n",
11106 root->logging_uuid,
11108 }
11109 }
11110}

References GNUNET_TIME_Absolute::abs_value_us, PendingMessage::bytes_msg, check_next_attempt_tree(), PendingMessage::frag_count, PendingMessage::frag_off, PendingMessage::frag_parent, PendingMessage::frags_in_flight, PendingMessage::frags_in_flight_round, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_STRINGS_absolute_time_to_string(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_relative_add(), GNUNET_TIME_relative_divide(), GNUNET_TIME_relative_multiply_double(), GNUNET_TIME_relative_to_absolute(), GNUNET_YES, harmonize_flight_round(), PendingMessage::logging_uuid, PendingMessage::next_attempt, pm, PendingMessage::pmt, PMT_DV_BOX, PMT_RELIABILITY_BOX, and reorder_root_pm().

Referenced by transmit_on_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ select_best_pending_from_link()

static void select_best_pending_from_link ( struct PendingMessageScoreContext sc,
struct Queue queue,
struct VirtualLink vl,
struct DistanceVectorHop dvh,
size_t  overhead 
)
static

Select the best pending message from vl for transmission via queue.

Parameters
[in,out]scbest message so far (NULL for none), plus scoring data
queuethe queue that will be used for transmission
vlthe virtual link providing the messages
dvhpath we are currently considering, or NULL for none
overheadnumber of bytes of overhead to be expected from DV encapsulation (0 for without DV)

Definition at line 11177 of file gnunet-service-transport.c.

11182{
11183 struct GNUNET_TIME_Absolute now;
11184
11185 now = GNUNET_TIME_absolute_get ();
11186 sc->to_early = GNUNET_NO;
11187 sc->frags_in_flight = GNUNET_NO;
11188 for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
11189 pos = pos->next_vl)
11190 {
11191 size_t real_overhead = overhead;
11192 int frag;
11193 int relb;
11194
11195 if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
11196 {
11198 "DV messages must not be DV-routed to next hop!\n");
11199 continue; /* DV messages must not be DV-routed to next hop! */
11200 }
11201 if (pos->next_attempt.abs_value_us > now.abs_value_us)
11202 {
11203 if (GNUNET_YES == pos->frags_in_flight)
11204 {
11205 sc->frags_in_flight = GNUNET_YES;
11207 "Fragments in flight for message %" PRIu64 "\n",
11208 pos->logging_uuid);
11209 }
11210 else
11211 {
11213 "Maybe too early, because message are sorted by next_attempt, if there are no fragments in flight.Checked message %"
11214 PRIu64 "\n",
11215 pos->logging_uuid);
11216 sc->to_early = GNUNET_YES;
11217 sc->to_early_retry_delay = GNUNET_TIME_absolute_get_remaining (
11218 pos->next_attempt);
11219 continue;
11220 }
11221 // break; /* too early for all messages, they are sorted by next_attempt */
11222 }
11223 if (NULL != pos->qe)
11224 {
11226 "not eligible\n");
11227 continue; /* not eligible */
11228 }
11229 sc->consideration_counter++;
11230 /* determine if we have to fragment, if so add fragmentation
11231 overhead! */
11233 "check %" PRIu64 " for sc->best\n",
11234 pos->logging_uuid);
11235 frag = GNUNET_NO;
11236 if (((0 != queue->mtu) &&
11237 (pos->bytes_msg + real_overhead > queue->mtu)) ||
11238 (pos->bytes_msg > UINT16_MAX - sizeof(struct
11240 ||
11241 (NULL != pos->head_frag /* fragments already exist, should
11242 respect that even if MTU is UINT16_MAX for
11243 this queue */))
11244 {
11246 "fragment msg with size %u, realoverhead is %lu\n",
11247 pos->bytes_msg,
11248 real_overhead);
11249 frag = GNUNET_YES;
11250 if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
11251 {
11252 /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
11253 header without the ACK UUID when using a *reliable* channel! */
11254 }
11255 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11256 }
11257 /* determine if we have to reliability-box, if so add reliability box
11258 overhead */
11259 relb = GNUNET_NO;
11260 if ((GNUNET_NO == frag) &&
11261 (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
11262 (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
11263 {
11264 real_overhead += sizeof(struct TransportReliabilityBoxMessage);
11265
11266 if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu))
11267 {
11268 frag = GNUNET_YES;
11269 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11270 }
11271 else
11272 {
11273 relb = GNUNET_YES;
11274 }
11276 "Create reliability box of msg with size %u, realoverhead is %lu %u %u %u\n",
11277 pos->bytes_msg,
11278 real_overhead,
11279 queue->mtu,
11280 frag,
11281 relb);
11282 }
11283
11284 /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
11285 message would beat it! */
11286 if (GNUNET_NO == sc->frags_in_flight && NULL != sc->best)
11287 {
11288 /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
11289 OPTIMIZE-ME: This is a heuristic, which so far has NOT been
11290 experimentally validated. There may be some huge potential for
11291 improvement here. Also, we right now only compare how well the
11292 given message fits _this_ queue, and do not consider how well other
11293 queues might suit the message. Taking other queues into consideration
11294 may further improve the result, but could also be expensive
11295 in terms of CPU time. */
11296 long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
11297 long long pm_score = frag * 40 + relb * 20 + real_overhead;
11298 long long time_delta =
11299 (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
11300 / 1000LL;
11301
11302 /* "time_delta" considers which message has been 'ready' for transmission
11303 for longer, if a message has a preference for low latency, increase
11304 the weight of the time_delta by 10x if it is favorable for that message */
11305 if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11306 (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
11307 time_delta *= 10; /* increase weight (always, both are low latency) */
11308 else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11309 (time_delta > 0))
11310 time_delta *= 10; /* increase weight, favors 'pos', which is low latency */
11311 else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11312 (time_delta < 0))
11313 time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */
11314 if (0 != queue->mtu)
11315 {
11316 /* Grant bonus if we are below MTU, larger bonus the closer we will
11317 be to the MTU */
11318 if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
11319 sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
11320 if (queue->mtu > real_overhead + pos->bytes_msg)
11321 pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
11322 }
11323 if (sc_score + time_delta > pm_score)
11324 {
11326 "sc_score of %" PRIu64 " larger, keep sc->best %" PRIu64
11327 "\n",
11328 pos->logging_uuid,
11329 sc->best->logging_uuid);
11330 continue; /* sc_score larger, keep sc->best */
11331 }
11332 }
11333 sc->best = pos;
11334 sc->dvh = dvh;
11335 sc->frag = frag;
11336 sc->relb = relb;
11337 sc->real_overhead = real_overhead;
11338 }
11339}

References GNUNET_TIME_Absolute::abs_value_us, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MQ_PREF_LOW_LATENCY, GNUNET_MQ_PREF_UNRELIABLE, GNUNET_NO, GNUNET_TIME_absolute_get(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TRANSPORT_CC_RELIABLE, GNUNET_YES, VirtualLink::pending_msg_head, PMT_DV_BOX, queue(), and sc.

Referenced by transmit_on_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ extract_box_cb()

static void extract_box_cb ( void *  cls,
struct Neighbour next_hop,
const struct GNUNET_MessageHeader hdr,
enum RouteMessageOptions  options 
)
static

Function to call to further operate on the now DV encapsulated message hdr, forwarding it via next_hop under respect of options.

Parameters
clsa struct PendingMessageScoreContext
next_hopnext hop of the DV path
hdrencapsulated message, technically a struct TransportDVBoxMessage
optionsoptions of the original message

Definition at line 11353 of file gnunet-service-transport.c.

11357{
11358 struct PendingMessageScoreContext *sc = cls;
11359 struct PendingMessage *pm = sc->best;
11360 struct PendingMessage *bpm;
11361 uint16_t bsize = ntohs (hdr->size);
11362
11363 GNUNET_assert (NULL == pm->bpm);
11364 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
11366 "5 created pm %p storing vl %p from pm %p\n",
11367 bpm,
11368 pm->vl,
11369 pm);
11371 bpm->pmt = PMT_DV_BOX;
11372 bpm->vl = pm->vl;
11373 bpm->timeout = pm->timeout;
11374 bpm->bytes_msg = bsize;
11375 bpm->frag_parent = pm;
11378 "Creating DV Box %" PRIu64 " for original message %" PRIu64
11379 " (next hop is %s)\n",
11381 pm->logging_uuid,
11382 GNUNET_i2s (&next_hop->pid));
11383 memcpy (&bpm[1], hdr, bsize);
11384 pm->bpm = bpm;
11385}

References PendingMessage::bpm, bsize, PendingMessage::bytes_msg, PendingMessage::frag_parent, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_malloc, PendingMessage::logging_uuid, logging_uuid_gen, Neighbour::pid, pm, PendingMessage::pmt, PMT_DV_BOX, sc, set_pending_message_uuid(), GNUNET_MessageHeader::size, PendingMessage::timeout, and PendingMessage::vl.

Referenced by transmit_on_queue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_del_queue_message()

static void handle_del_queue_message ( void *  cls,
const struct GNUNET_TRANSPORT_DelQueueMessage dqm 
)
static

Queue to a peer went down.

Process the request.

Parameters
clsthe client
dqmthe send message that was sent

Definition at line 11660 of file gnunet-service-transport.c.

11662{
11663 struct TransportClient *tc = cls;
11664
11665 if (CT_COMMUNICATOR != tc->type)
11666 {
11667 GNUNET_break (0);
11669 return;
11670 }
11671 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11672 queue = queue->next_client)
11673 {
11674 struct Neighbour *neighbour = queue->neighbour;
11675
11676 if ((ntohl (dqm->qid) != queue->qid) ||
11677 (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
11678 continue;
11680 "Dropped queue %s to peer %s\n",
11681 queue->address,
11682 GNUNET_i2s (&neighbour->pid));
11683 free_queue (queue);
11685 return;
11686 }
11687 GNUNET_break (0);
11689}

References CT_COMMUNICATOR, free_queue(), GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_memcmp, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), Neighbour::pid, GNUNET_TRANSPORT_DelQueueMessage::qid, queue(), GNUNET_TRANSPORT_DelQueueMessage::receiver, and tc.

Here is the call graph for this function:

◆ handle_send_message_ack()

static void handle_send_message_ack ( void *  cls,
const struct GNUNET_TRANSPORT_SendMessageToAck sma 
)
static

Message was transmitted.

Process the request.

Parameters
clsthe client
smathe send message that was sent

Definition at line 11790 of file gnunet-service-transport.c.

11792{
11793 struct TransportClient *tc = cls;
11794 struct QueueEntry *qe;
11795
11796 if (CT_COMMUNICATOR != tc->type)
11797 {
11798 GNUNET_break (0);
11800 return;
11801 }
11802
11803 /* find our queue entry matching the ACK */
11804 qe = NULL;
11806 "Looking for queue for PID %s\n",
11807 GNUNET_i2s (&sma->receiver));
11808 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11809 queue = queue->next_client)
11810 {
11811 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
11812 continue;
11814 "Found PID %s\n",
11815 GNUNET_i2s (&queue->neighbour->pid));
11816
11817
11818 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
11819 qep = qep->next)
11820 {
11821 if (qep->mid != GNUNET_ntohll (sma->mid) || queue->qid != ntohl (
11822 sma->qid))
11823 continue;
11825 "QueueEntry MID: %" PRIu64 " on queue QID: %u, Ack MID: %"
11826 PRIu64 " Ack QID %u\n",
11827 qep->mid,
11828 queue->qid,
11829 GNUNET_ntohll (sma->mid),
11830 ntohl (sma->qid));
11831 qe = qep;
11832 if ((NULL != qe->pm) && (qe->pm->qe != qe))
11834 "For pending message %" PRIu64 " we had retransmissions.\n",
11835 qe->pm->logging_uuid);
11836 break;
11837 }
11838 }
11839 if (NULL == qe)
11840 {
11842 "No QueueEntry found for Ack MID %" PRIu64 " QID: %u\n",
11843 GNUNET_ntohll (sma->mid),
11844 ntohl (sma->qid));
11845 // TODO I guess this can happen, if the Ack from the peer comes before the Ack from the queue.
11846 // Update: Maybe QueueEntry was accidentally freed during freeing PendingMessage.
11847 /* this should never happen */
11848 // GNUNET_break (0);
11849 // GNUNET_SERVICE_client_drop (tc->client);
11851 return;
11852 }
11855}

References CT_COMMUNICATOR, free_queue_entry(), GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_memcmp, GNUNET_ntohll(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_TRANSPORT_SendMessageToAck::mid, qe, GNUNET_TRANSPORT_SendMessageToAck::qid, queue(), GNUNET_TRANSPORT_SendMessageToAck::receiver, and tc.

Here is the call graph for this function:

◆ handle_burst_finished()

static void handle_burst_finished ( void *  cls,
const struct GNUNET_TRANSPORT_BurstFinished bf 
)
static

The burst finished.

Parameters
clsthe client

Definition at line 11864 of file gnunet-service-transport.c.

11866{
11868}

References burst_running, and GNUNET_NO.

◆ notify_client_queues()

static int notify_client_queues ( void *  cls,
const struct GNUNET_PeerIdentity pid,
void *  value 
)
static

Iterator telling new MONITOR client about all existing queues to peers.

Parameters
clsthe new struct TransportClient
pida connected peer
valuethe struct Neighbour with more information
Returns
GNUNET_OK (continue to iterate)

Definition at line 11881 of file gnunet-service-transport.c.

11884{
11885 struct TransportClient *tc = cls;
11886 struct Neighbour *neighbour = value;
11887
11888 GNUNET_assert (CT_MONITOR == tc->type);
11889 for (struct Queue *q = neighbour->queue_head; NULL != q;
11890 q = q->next_neighbour)
11891 {
11892 struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
11893 .cs = q->cs,
11894 .num_msg_pending = q->num_msg_pending,
11895 .num_bytes_pending = q->num_bytes_pending };
11896
11897 notify_monitor (tc, pid, q->address, q->nt, &me);
11898 }
11899 return GNUNET_OK;
11900}

References CT_MONITOR, GNUNET_assert, GNUNET_OK, me, notify_monitor(), pid, q, Neighbour::queue_head, tc, and value.

Referenced by handle_monitor_start().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_monitor_start()

static void handle_monitor_start ( void *  cls,
const struct GNUNET_TRANSPORT_MonitorStart start 
)
static

Initialize a monitor client.

Parameters
clsthe client
startthe start message that was sent

Definition at line 11910 of file gnunet-service-transport.c.

11912{
11913 struct TransportClient *tc = cls;
11914
11915 if (CT_NONE != tc->type)
11916 {
11917 GNUNET_break (0);
11919 return;
11920 }
11921 tc->type = CT_MONITOR;
11922 tc->details.monitor.peer = start->peer;
11923 tc->details.monitor.one_shot = ntohl (start->one_shot);
11927}

References CT_MONITOR, CT_NONE, GNUNET_break, GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_SERVICE_client_mark_monitor(), neighbours, notify_client_queues(), start, and tc.

Here is the call graph for this function:

◆ lookup_communicator()

static struct TransportClient * lookup_communicator ( const char *  prefix)
static

Find transport client providing communication service for the protocol prefix.

Parameters
prefixcommunicator name
Returns
NULL if no such transport client is available

Definition at line 11938 of file gnunet-service-transport.c.

11939{
11940 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
11941 {
11942 if (CT_COMMUNICATOR != tc->type)
11943 continue;
11944 if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
11945 return tc;
11946 }
11947 GNUNET_log (
11949 "Someone suggested use of communicator for `%s', but we do not have such a communicator!\n",
11950 prefix);
11951 return NULL;
11952}

References clients_head, CT_COMMUNICATOR, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, prefix, and tc.

Referenced by suggest_to_connect().

Here is the caller graph for this function:

◆ check_connection_quality()

static int check_connection_quality ( void *  cls,
const struct GNUNET_PeerIdentity pid,
void *  value 
)
static

Check whether any queue to the given neighbour is of a good "quality" and if so, increment the counter.

Also counts the total number of queues, and returns the k-th queue found.

Parameters
clsa struct QueueQualityContext * with counters
pidpeer this is about
valuea struct Neighbour
Returns
GNUNET_OK (continue to iterate)

Definition at line 12164 of file gnunet-service-transport.c.

12167{
12168 struct QueueQualityContext *ctx = cls;
12169 struct Neighbour *n = value;
12170 int do_inc;
12171
12172 (void) pid;
12173 do_inc = GNUNET_NO;
12174 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
12175 {
12176 ctx->num_queues++;
12177 if (0 == ctx->k--)
12178 ctx->q = q;
12179 /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
12180 statistics and consider those as well here? */
12181 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
12182 do_inc = GNUNET_YES;
12183 }
12184 if (GNUNET_YES == do_inc)
12185 ctx->quality_count++;
12186 return GNUNET_OK;
12187}

References ctx, DV_QUALITY_RTT_THRESHOLD, GNUNET_NO, GNUNET_OK, GNUNET_YES, pid, q, Neighbour::queue_head, and value.

Referenced by sign_dv_init_cb(), and start_dv_learn().

Here is the caller graph for this function:

◆ start_dv_learn()

static void start_dv_learn ( void *  cls)
static

Task run when we CONSIDER initiating a DV learn process.

We first check that sending out a message is even possible (queues exist), then that it is desirable (if not, reschedule the task for later), and finally we may then begin the job. If there are too many entries in the dvlearn_map, we purge the oldest entry using lle_tail.

Parameters
clsNULL

Definition at line 12268 of file gnunet-service-transport.c.

12269{
12270 struct LearnLaunchEntry *lle;
12271 struct QueueQualityContext qqc;
12272 struct TransportDVLearnMessage dvl;
12273
12274 (void) cls;
12275 dvlearn_task = NULL;
12277 return; /* lost all connectivity, cannot do learning */
12278 qqc.quality_count = 0;
12279 qqc.num_queues = 0;
12283 &qqc);
12284 if (qqc.quality_count > DV_LEARN_QUALITY_THRESHOLD)
12285 {
12286 struct GNUNET_TIME_Relative delay;
12287 unsigned int factor;
12288
12289 /* scale our retries by how far we are above the threshold */
12290 factor = qqc.quality_count / DV_LEARN_QUALITY_THRESHOLD;
12293 "At connection quality %u, will launch DV learn in %s\n",
12294 qqc.quality_count,
12297 return;
12298 }
12299 /* remove old entries in #dvlearn_map if it has grown too big */
12300 while (MAX_DV_LEARN_PENDING <=
12302 {
12303 lle = lle_tail;
12306 &lle->challenge.value,
12307 lle));
12309 GNUNET_free (lle);
12310 }
12311 /* setup data structure for learning */
12312 lle = GNUNET_new (struct LearnLaunchEntry);
12314 &lle->challenge,
12315 sizeof(lle->challenge));
12317 "Starting launch DV learn with challenge %s\n",
12318 GNUNET_sh2s (&lle->challenge.value));
12323 &lle->challenge.value,
12324 lle,
12326 dvl.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN);
12327 dvl.header.size = htons (sizeof(dvl));
12328 dvl.num_hops = htons (0);
12329 dvl.bidirectional = htons (0);
12330 dvl.non_network_delay = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO);
12331 dvl.monotonic_time =
12333 {
12334 struct DvInitPS dvip = {
12335 .purpose.purpose = htonl (
12337 .purpose.size = htonl (sizeof(dvip)),
12338 .monotonic_time = dvl.monotonic_time,
12339 .challenge = lle->challenge
12340 };
12341 struct SignDvInitCls *sign_dv_init_cls;
12342
12343 sign_dv_init_cls = GNUNET_new (struct SignDvInitCls);
12344 sign_dv_init_cls->dvl = dvl;
12345 sign_dv_init_cls->lle = lle;
12346 sign_dv_init_cls->qqc = qqc;
12347 sign_dv_init_cls->pr = GNUNET_new (struct PilsRequest);
12350 sign_dv_init_cls->pr);
12351 sign_dv_init_cls->pr->op =
12353 &dvip.purpose,
12355 sign_dv_init_cls);
12356 }
12357}

References TransportDVLearnMessage::bidirectional, LearnLaunchEntry::challenge, check_connection_quality(), DV_LEARN_BASE_FREQUENCY, DV_LEARN_QUALITY_THRESHOLD, SignDvInitCls::dvl, dvlearn_map, dvlearn_task, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_CONTAINER_multipeermap_size(), GNUNET_CONTAINER_multishortmap_put(), GNUNET_CONTAINER_multishortmap_remove(), GNUNET_CONTAINER_multishortmap_size(), GNUNET_CRYPTO_QUALITY_NONCE, GNUNET_CRYPTO_random_block(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN, GNUNET_new, GNUNET_PILS_sign_by_peer_identity(), GNUNET_SCHEDULER_add_delayed(), GNUNET_sh2s(), GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR, GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_absolute_get_monotonic(), GNUNET_TIME_absolute_hton(), GNUNET_TIME_relative_hton(), GNUNET_TIME_relative_multiply(), GNUNET_TIME_UNIT_ZERO, GNUNET_YES, GST_cfg, TransportDVLearnMessage::header, QueueQualityContext::k, SignDvInitCls::lle, lle_head, lle_tail, MAX_DV_LEARN_PENDING, TransportDVLearnMessage::monotonic_time, neighbours, TransportDVLearnMessage::non_network_delay, TransportDVLearnMessage::num_hops, QueueQualityContext::num_queues, PilsRequest::op, pils, pils_requests_head, pils_requests_tail, SignDvInitCls::pr, GNUNET_CRYPTO_EccSignaturePurpose::purpose, DvInitPS::purpose, SignDvInitCls::qqc, QueueQualityContext::quality_count, sign_dv_init_cb(), GNUNET_MessageHeader::size, start_dv_learn(), GNUNET_MessageHeader::type, and GNUNET_CRYPTO_ChallengeNonceP::value.

Referenced by handle_add_queue_message(), sign_dv_init_cb(), and start_dv_learn().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sign_dv_init_cb()

static void sign_dv_init_cb ( void *  cls,
const struct GNUNET_PeerIdentity pid,
const struct GNUNET_CRYPTO_EddsaSignature sig 
)
static

Definition at line 12215 of file gnunet-service-transport.c.

12218{
12219 struct SignDvInitCls *sign_dv_init_cls = cls;
12220 struct TransportDVLearnMessage dvl = sign_dv_init_cls->dvl;
12221 struct LearnLaunchEntry *lle = sign_dv_init_cls->lle;
12222 struct QueueQualityContext qqc = sign_dv_init_cls->qqc;
12223
12224 sign_dv_init_cls->pr->op = NULL;
12227 sign_dv_init_cls->pr);
12228 GNUNET_free (sign_dv_init_cls->pr);
12229
12230 dvl.init_sig = *sig;
12232 dvl.challenge = lle->challenge;
12233
12234 qqc.quality_count = 0;
12236 qqc.num_queues = 0;
12237 qqc.q = NULL;
12240 &qqc);
12241 GNUNET_assert (NULL != qqc.q);
12242
12243 /* Do this as close to transmission time as possible! */
12245
12246 queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
12247 /* reschedule this job, randomizing the time it runs (but no
12248 actual backoff!) */
12252 NULL);
12253}

References TransportDVLearnMessage::challenge, LearnLaunchEntry::challenge, check_connection_quality(), DV_LEARN_BASE_FREQUENCY, SignDvInitCls::dvl, dvlearn_task, GNUNET_assert, GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u32(), GNUNET_free, GNUNET_SCHEDULER_add_delayed(), GNUNET_TIME_absolute_get(), GNUNET_TIME_randomize(), GST_my_identity, TransportDVLearnMessage::init_sig, TransportDVLearnMessage::initiator, QueueQualityContext::k, LearnLaunchEntry::launch_time, SignDvInitCls::lle, neighbours, QueueQualityContext::num_queues, PilsRequest::op, pils_requests_head, pils_requests_tail, SignDvInitCls::pr, QueueQualityContext::q, SignDvInitCls::qqc, QueueQualityContext::quality_count, queue_send_msg(), and start_dv_learn().

Referenced by start_dv_learn().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_validation_request_pending()

static int check_validation_request_pending ( void *  cls,
const struct GNUNET_PeerIdentity pid,
void *  value 
)
static

A new queue has been created, check if any address validation requests have been waiting for it.

Parameters
clsa struct Queue
pidpeer concerned (unused)
valuea struct ValidationState
Returns
GNUNET_NO if a match was found and we can stop looking

Definition at line 12395 of file gnunet-service-transport.c.

12398{
12399 struct Queue *q = cls;
12400 struct ValidationState *vs = value;
12401 char *address_without_port_vs;
12402 char *address_without_port_q;
12403 int success = GNUNET_YES;
12404
12405 // TODO Check if this is really necessary.
12406 address_without_port_vs = get_address_without_port (vs->address);
12407 address_without_port_q = get_address_without_port (q->address);
12408
12410 "Check validation request pending for `%s' at `%s'/`%s' (vs)/(q)\n",
12411 GNUNET_i2s (pid),
12412 address_without_port_vs,
12413 address_without_port_q);
12414 (void) pid;
12415 if ((GNUNET_YES == vs->awaiting_queue) &&
12416 (0 == strcmp (address_without_port_vs, address_without_port_q)))
12417 {
12418
12419 vs->awaiting_queue = GNUNET_NO;
12421 success = GNUNET_NO;
12422 }
12423
12424 GNUNET_free (address_without_port_vs);
12425 GNUNET_free (address_without_port_q);
12426 return success;
12427}

References get_address_without_port(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_YES, pid, q, validation_transmit_on_queue(), and value.

Referenced by handle_add_queue_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ neighbour_dv_monotime_cb()

static void neighbour_dv_monotime_cb ( void *  cls,
const struct GNUNET_PEERSTORE_Record record,
const char *  emsg 
)
static

Function called with the monotonic time of a DV initiator by PEERSTORE.

Updates the time.

Parameters
clsa struct Neighbour
recordthe information found, NULL for the last call
emsgerror message

Definition at line 12439 of file gnunet-service-transport.c.

12442{
12443 struct Neighbour *n = cls;
12444 struct GNUNET_TIME_AbsoluteNBO *mtbe;
12445
12446 (void) emsg;
12447 if (NULL == record)
12448 {
12449 /* we're done with #neighbour_dv_monotime_cb() invocations,
12450 continue normal processing */
12451 n->get = NULL;
12453 return;
12454 }
12455 if (0 == record->value_size)
12456 {
12458 GNUNET_break (0);
12459 return;
12460 }
12461 mtbe = record->value;
12466}

References Neighbour::dv_monotime_available, Neighbour::get, GNUNET_break, GNUNET_PEERSTORE_iteration_next(), GNUNET_TIME_absolute_max(), GNUNET_TIME_absolute_ntoh(), GNUNET_YES, Neighbour::last_dv_learn_monotime, and record().

Referenced by handle_add_queue_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ iterate_address_and_compare_cb()

static void iterate_address_and_compare_cb ( void *  cls,
const struct GNUNET_PeerIdentity pid,
const char *  uri 
)
static

Definition at line 12470 of file gnunet-service-transport.c.

12473{
12474 struct Queue *queue = cls;
12475 struct sockaddr_in v4;
12476 const char *slash;
12477 char *address_uri;
12478 char *prefix;
12479 char *uri_without_port;
12480 char *address_uri_without_port;
12481
12482 slash = strrchr (uri, '/');
12483 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
12484 GNUNET_assert (NULL != slash);
12485 slash++;
12486 GNUNET_asprintf (&address_uri,
12487 "%s-%s",
12488 prefix,
12489 slash);
12490
12492 "1 not global natted_address %u %s %s %s\n",
12493 queue->is_global_natted,
12494 uri,
12495 queue->address,
12496 slash);
12497
12498 uri_without_port = get_address_without_port (address_uri);
12499 if (1 != inet_pton (AF_INET, uri_without_port, &v4.sin_addr))
12500 {
12502 GNUNET_free (address_uri);
12503 GNUNET_free (uri_without_port);
12504 return;
12505 }
12506
12508 "2 not global natted_address %u %s %s\n",
12509 queue->is_global_natted,
12510 uri,
12511 queue->address);
12512
12513 if (GNUNET_NO == queue->is_global_natted)
12514 {
12516 GNUNET_free (address_uri);
12517 GNUNET_free (uri_without_port);
12518 return;
12519 }
12520
12522 "3 not global natted_address %u %s %s\n",
12523 queue->is_global_natted,
12524 uri,
12525 queue->address);
12526
12527 if (0 == strcmp (uri_without_port, address_uri))
12528 {
12530 GNUNET_free (address_uri);
12531 GNUNET_free (uri_without_port);
12532 return;
12533 }
12534
12536 "4 not global natted_address %u %s %s\n",
12537 queue->is_global_natted,
12538 uri,
12539 queue->address);
12540
12541 address_uri_without_port = get_address_without_port (queue->address);
12542 if (0 == strcmp (uri_without_port, address_uri_without_port))
12543 {
12544 queue->is_global_natted = GNUNET_NO;
12545 }
12546
12548 "not global natted_address %u %s %s %s %s %s %u\n",
12549 queue->is_global_natted,
12550 uri,
12551 queue->address,
12552 uri_without_port,
12553 address_uri_without_port,
12554 prefix,
12555 GNUNET_NO);
12557 GNUNET_free (address_uri);
12558 GNUNET_free (address_uri_without_port);
12559 GNUNET_free (uri_without_port);
12560}

References get_address_without_port(), GNUNET_asprintf(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_NO, GNUNET_strndup, prefix, queue(), and uri.

Referenced by check_for_global_natted().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ contains_address()

static enum GNUNET_GenericReturnValue contains_address ( void *  cls,
const struct GNUNET_PeerIdentity pid,
void *  value 
)
static

Definition at line 12578 of file gnunet-service-transport.c.

12581{
12582 struct TransportGlobalNattedAddressClosure *tgna_cls = cls;
12583 struct TransportGlobalNattedAddress *tgna = value;
12584 char *addr = (char *) &tgna[1];
12585
12587 "Checking tgna %p with addr %s and length %u compare length %lu\n",
12588 tgna,
12589 addr,
12590 ntohl (tgna->address_length),
12591 strlen (tgna_cls->addr));
12592 if (strlen (tgna_cls->addr) == ntohl (tgna->address_length)
12593 && 0 == strncmp (addr, tgna_cls->addr, ntohl (tgna->address_length)))
12594 {
12595 tgna_cls->tgna = tgna;
12596 return GNUNET_NO;
12597 }
12598 return GNUNET_YES;
12599}

References TransportGlobalNattedAddressClosure::addr, TransportGlobalNattedAddress::address_length, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_YES, TransportGlobalNattedAddressClosure::tgna, and value.

Referenced by check_for_global_natted().

Here is the caller graph for this function:

◆ check_for_global_natted_error_cb()

static void check_for_global_natted_error_cb ( void *  cls)
static

Definition at line 12603 of file gnunet-service-transport.c.

12604{
12606 "Error in PEERSTORE monitoring for checking global natted\n");
12607}

References GNUNET_ERROR_TYPE_WARNING, and GNUNET_log.

Referenced by handle_add_queue_message().

Here is the caller graph for this function:

◆ check_for_global_natted_sync_cb()

static void check_for_global_natted_sync_cb ( void *  cls)
static

Definition at line 12611 of file gnunet-service-transport.c.

12612{
12614 "Done with initial PEERSTORE iteration during monitoring for checking global natted\n");
12615}

References GNUNET_ERROR_TYPE_WARNING, and GNUNET_log.

Referenced by handle_add_queue_message().

Here is the caller graph for this function:

◆ check_for_global_natted()

static void check_for_global_natted ( void *  cls,
const struct GNUNET_PEERSTORE_Record record,
const char *  emsg 
)
static

Definition at line 12619 of file gnunet-service-transport.c.

12622{
12623 struct Queue *queue = cls;
12624 struct Neighbour *neighbour = queue->neighbour;
12626 struct GNUNET_MessageHeader *hello;
12628 size_t address_len_without_port;
12629
12630 if (NULL != emsg)
12631 {
12633 "Got failure from PEERSTORE: %s\n",
12634 emsg);
12635 return;
12636 }
12637 if (0 == record->value_size)
12638 {
12640 GNUNET_break (0);
12641 return;
12642 }
12643 queue->is_global_natted = GNUNET_YES;
12644 hello = record->value;
12647 "before not global natted %u\n",
12648 queue->is_global_natted);
12651 queue);
12653 "after not global natted %u\n",
12654 queue->is_global_natted);
12655 GNUNET_HELLO_parser_free (parser);
12656
12657 tgna_cls.addr = get_address_without_port (queue->address);
12658 address_len_without_port = strlen (tgna_cls.addr);
12659 /*{
12660 char buf[address_len_without_port + 1];
12661
12662 GNUNET_memcpy (&buf, addr, address_len_without_port);
12663 buf[address_len_without_port] = '\0';
12664 GNUNET_free (addr);
12665 GNUNET_memcpy (tgna_cls.addr, buf, address_len_without_port + 1);
12666 }*/
12667 tgna_cls.tgna = NULL;
12669 &neighbour->pid,
12671 &tgna_cls);
12672 if (NULL != tgna_cls.tgna)
12674 " tgna_cls.tgna tgna %p %lu %u %u\n",
12675 tgna_cls.tgna,
12676 neighbour->size_of_global_addresses,
12677 ntohl (tgna_cls.tgna->address_length),
12678 neighbour->number_of_addresses);
12679 if (NULL == tgna_cls.tgna && GNUNET_YES == queue->is_global_natted)
12680 {
12681 struct TransportGlobalNattedAddress *tgna;
12682
12683 tgna = GNUNET_malloc (sizeof (struct TransportGlobalNattedAddress)
12684 + address_len_without_port);
12685 tgna->address_length = htonl (address_len_without_port);
12686 GNUNET_memcpy (&tgna[1], tgna_cls.addr, address_len_without_port);
12688 &neighbour->pid,
12689 tgna,
12691 neighbour->number_of_addresses++;
12692 neighbour->size_of_global_addresses += address_len_without_port + 1;
12694 "Created tgna %p with address %s and length %lu\n",
12695 tgna,
12696 tgna_cls.addr,
12697 address_len_without_port + 1);
12698 }
12699 else if (NULL != tgna_cls.tgna && GNUNET_NO == queue->is_global_natted)
12700 {
12702 &neighbour->pid,
12703 tgna_cls.tgna);
12704 GNUNET_assert (neighbour->size_of_global_addresses >= ntohl (tgna_cls.tgna->
12706 );
12707 neighbour->size_of_global_addresses -= ntohl (tgna_cls.tgna->address_length)
12708 ;
12709 GNUNET_assert (0 < neighbour->number_of_addresses);
12710 neighbour->number_of_addresses--;
12712 "removed tgna %p\n",
12713 tgna_cls.tgna);
12714 GNUNET_free (tgna_cls.tgna);
12715 }
12717 GNUNET_free (tgna_cls.addr);
12718}

References TransportGlobalNattedAddressClosure::addr, TransportGlobalNattedAddress::address_length, contains_address(), get_address_without_port(), GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE, GNUNET_CONTAINER_multipeermap_get_multiple(), GNUNET_CONTAINER_multipeermap_put(), GNUNET_CONTAINER_multipeermap_remove(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_HELLO_parser_free(), GNUNET_HELLO_parser_from_msg(), GNUNET_HELLO_parser_iterate(), GNUNET_log, GNUNET_malloc, GNUNET_memcpy, GNUNET_NO, GNUNET_PEERSTORE_monitor_next(), GNUNET_YES, iterate_address_and_compare_cb(), Neighbour::natted_addresses, Neighbour::number_of_addresses, Neighbour::pid, queue(), record(), Neighbour::size_of_global_addresses, and TransportGlobalNattedAddressClosure::tgna.

Referenced by handle_add_queue_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_add_queue_message()

static void handle_add_queue_message ( void *  cls,
const struct GNUNET_TRANSPORT_AddQueueMessage aqm 
)
static

New queue became available.

Process the request.

Parameters
clsthe client
aqmthe send message that was sent

Definition at line 12728 of file gnunet-service-transport.c.

12730{
12731 struct TransportClient *tc = cls;
12732 struct Queue *queue;
12733 struct Neighbour *neighbour;
12734 const char *addr;
12735 uint16_t addr_len;
12736
12737 if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
12738 {
12739 /* MTU so small as to be useless for transmissions,
12740 required for #fragment_message()! */
12741 GNUNET_break_op (0);
12743 return;
12744 }
12745 /* This may simply be a queue update */
12746 for (queue = tc->details.communicator.queue_head;
12747 NULL != queue;
12748 queue = queue->next_client)
12749 {
12750 if (queue->qid != ntohl (aqm->qid))
12751 continue;
12752 break;
12753 }
12754
12755 if (NULL != queue)
12756 {
12757 neighbour = queue->neighbour;
12758 }
12759 else
12760 {
12761 struct GNUNET_TIME_Absolute validated_until = GNUNET_TIME_UNIT_ZERO_ABS;
12762
12763 neighbour = lookup_neighbour (&aqm->receiver);
12764 if (NULL == neighbour)
12765 {
12766 neighbour = GNUNET_new (struct Neighbour);
12768 GNUNET_YES);
12769 neighbour->pid = aqm->receiver;
12772 neighbours,
12773 &neighbour->pid,
12774 neighbour,
12776 neighbour->get =
12778 "transport",
12779 &neighbour->pid,
12782 neighbour);
12783 }
12784 addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
12785 addr = (const char *) &aqm[1];
12787 "New queue %s to %s available with QID %u and q_len %" PRIu64
12788 " and mtu %u\n",
12789 addr,
12790 GNUNET_i2s (&aqm->receiver),
12791 ntohl (aqm->qid),
12792 GNUNET_ntohll (aqm->q_len),
12793 ntohl (aqm->mtu));
12794 queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
12795 queue->tc = tc;
12796 for (struct Queue *q = neighbour->queue_head; NULL != q; q = q->
12797 next_neighbour)
12798 validated_until = GNUNET_TIME_absolute_max (validated_until, q->
12799 validated_until);
12800 if (0 == GNUNET_TIME_absolute_get_remaining (validated_until).rel_value_us)
12801 {
12803 "New queue with QID %u inherit validated until\n",
12804 ntohl (aqm->qid));
12805 queue->validated_until = validated_until;
12806 }
12807 queue->address = (const char *) &queue[1];
12808 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
12809 queue->qid = ntohl (aqm->qid);
12810 queue->neighbour = neighbour;
12812 queue->unlimited_length = GNUNET_YES;
12813 queue->q_capacity = GNUNET_ntohll (aqm->q_len);
12814 memcpy (&queue[1], addr, addr_len);
12815 /* notify monitors about new queue */
12816 {
12817 struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
12818
12819 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
12820 }
12822 neighbour->queue_head,
12823 neighbour->queue_tail,
12824 queue);
12826 tc->details.communicator.queue_head,
12827 tc->details.communicator.queue_tail,
12828 queue);
12829
12830 }
12831 queue->mtu = ntohl (aqm->mtu);
12832 queue->nt = ntohl (aqm->nt);
12833 queue->cs = ntohl (aqm->cs);
12834 queue->idle = GNUNET_YES;
12835
12836 {
12837 struct sockaddr_in v4;
12838 char *addr_without = get_address_without_port (queue->address);
12839 if (1 == inet_pton (AF_INET, addr_without, &v4.sin_addr))
12840 {
12842 "start not global natted\n");
12844 GNUNET_YES,
12845 "peerstore",
12846 &neighbour->pid,
12848 &
12850 NULL,
12851 &
12853 NULL,
12855 queue);
12856 }
12857 GNUNET_free (addr_without);
12858 }
12859 /* check if valdiations are waiting for the queue */
12861 &aqm->receiver))
12862 {
12865 &aqm->
12866 receiver,
12867 &
12869 queue))
12870 start_address_validation (&aqm->receiver, queue->address);
12871 }
12872 else
12873 start_address_validation (&aqm->receiver, queue->address);
12874 /* look for traffic for this queue */
12875 // TODO Check whether this makes any sense at all.
12876 /*schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
12877 queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);*/
12878 /* might be our first queue, try launching DV learning */
12879 if (NULL == dvlearn_task)
12882}

References check_for_global_natted(), check_for_global_natted_error_cb(), check_for_global_natted_sync_cb(), check_validation_request_pending(), GNUNET_TRANSPORT_AddQueueMessage::cs, dvlearn_task, Neighbour::get, get_address_without_port(), GNUNET_assert, GNUNET_break_op, GNUNET_CONTAINER_MDLL_insert, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multipeermap_contains(), GNUNET_CONTAINER_multipeermap_create(), GNUNET_CONTAINER_multipeermap_get_multiple(), GNUNET_CONTAINER_multipeermap_put(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_malloc, GNUNET_new, GNUNET_ntohll(), GNUNET_OK, GNUNET_PEERSTORE_HELLO_KEY, GNUNET_PEERSTORE_iteration_start(), GNUNET_PEERSTORE_monitor_start(), GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME, GNUNET_SCHEDULER_add_now(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_SYSERR, GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_absolute_max(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED, GNUNET_YES, GST_cfg, GNUNET_TRANSPORT_AddQueueMessage::header, lookup_neighbour(), me, GNUNET_TRANSPORT_AddQueueMessage::mtu, Neighbour::natted_addresses, neighbour_dv_monotime_cb(), neighbours, notify_monitors(), GNUNET_TRANSPORT_AddQueueMessage::nt, peerstore, Neighbour::pid, q, GNUNET_TRANSPORT_AddQueueMessage::q_len, GNUNET_TRANSPORT_AddQueueMessage::qid, queue(), Neighbour::queue_head, Neighbour::queue_tail, receiver(), GNUNET_TRANSPORT_AddQueueMessage::receiver, GNUNET_TIME_Relative::rel_value_us, GNUNET_MessageHeader::size, start_address_validation(), start_dv_learn(), tc, and validation_map.

Here is the call graph for this function:

◆ handle_update_queue_message()

static void handle_update_queue_message ( void *  cls,
const struct GNUNET_TRANSPORT_UpdateQueueMessage msg 
)
static

Handle updates to queues.

Parameters
clsthe transport client.
msgMessage struct.

Definition at line 12892 of file gnunet-service-transport.c.

12895{
12896 struct TransportClient *tc = cls;
12897 struct Queue *target_queue = NULL;
12898
12900 "Received queue update message for %u with q_len %llu and mtu %u\n",
12901 ntohl (msg->qid),
12902 (unsigned long long) GNUNET_ntohll (msg->q_len),
12903 ntohl (msg->mtu));
12904 for (target_queue = tc->details.communicator.queue_head;
12905 NULL != target_queue;
12906 target_queue = target_queue->next_client)
12907 {
12908 if (ntohl (msg->qid) == target_queue->qid)
12909 break;
12910 }
12911 if (NULL == target_queue)
12912 {
12914 "Queue to update no longer exists! Discarding update.\n");
12915 return;
12916 }
12917
12918 target_queue->nt = msg->nt;
12919 target_queue->mtu = ntohl (msg->mtu);
12920 target_queue->cs = msg->cs;
12921 target_queue->priority = ntohl (msg->priority);
12922 /* The update message indicates how many messages
12923 * the queue should be able to handle.
12924 */
12926 target_queue->unlimited_length = GNUNET_YES;
12927 else
12928 target_queue->unlimited_length = GNUNET_NO;
12929 target_queue->q_capacity += GNUNET_ntohll (msg->q_len);
12930 if (0 < target_queue->q_capacity)
12932 target_queue,
12935}

References Queue::cs, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_NO, GNUNET_ntohll(), GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_SERVICE_client_continue(), GNUNET_TIME_UNIT_ZERO, GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED, GNUNET_YES, msg, Queue::mtu, Queue::next_client, Queue::nt, Queue::priority, Queue::q_capacity, Queue::qid, schedule_transmit_on_queue(), tc, and Queue::unlimited_length.

Here is the call graph for this function:

◆ handle_queue_create_ok()

static void handle_queue_create_ok ( void *  cls,
const struct GNUNET_TRANSPORT_CreateQueueResponse cqr 
)
static

Communicator tells us that our request to create a queue "worked", that is setting up the queue is now in process.

Parameters
clsthe struct TransportClient
cqrconfirmation message

Definition at line 12946 of file gnunet-service-transport.c.

12948{
12949 struct TransportClient *tc = cls;
12950
12951 if (CT_COMMUNICATOR != tc->type)
12952 {
12953 GNUNET_break (0);
12955 return;
12956 }
12958 "# Suggestions succeeded at communicator",
12959 1,
12960 GNUNET_NO);
12962 "Request #%u for communicator to create queue succeeded\n",
12963 (unsigned int) ntohs (cqr->request_id));
12965}

References CT_COMMUNICATOR, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_STATISTICS_update(), GST_stats, GNUNET_TRANSPORT_CreateQueueResponse::request_id, and tc.

Here is the call graph for this function:

◆ handle_queue_create_fail()

static void handle_queue_create_fail ( void *  cls,
const struct GNUNET_TRANSPORT_CreateQueueResponse cqr 
)
static

Communicator tells us that our request to create a queue failed.

This usually indicates that the provided address is simply invalid or that the communicator's resources are exhausted.

Parameters
clsthe struct TransportClient
cqrfailure message

Definition at line 12977 of file gnunet-service-transport.c.

12980{
12981 struct TransportClient *tc = cls;
12982
12983 if (CT_COMMUNICATOR != tc->type)
12984 {
12985 GNUNET_break (0);
12987 return;
12988 }
12990 "Request #%u for communicator to create queue failed\n",
12991 (unsigned int) ntohl (cqr->request_id));
12993 "# Suggestions failed in queue creation at communicator",
12994 1,
12995 GNUNET_NO);
12997}

References CT_COMMUNICATOR, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_STATISTICS_update(), GST_stats, GNUNET_TRANSPORT_CreateQueueResponse::request_id, and tc.

Here is the call graph for this function:

◆ handle_suggest_cancel()

static void handle_suggest_cancel ( void *  cls,
const struct ExpressPreferenceMessage msg 
)
static

We have received a struct ExpressPreferenceMessage from an application client.

Parameters
clshandle to the client
msgthe start message

Definition at line 13008 of file gnunet-service-transport.c.

13009{
13010 struct TransportClient *tc = cls;
13011 struct PeerRequest *pr;
13012
13013 if (CT_APPLICATION != tc->type)
13014 {
13015 GNUNET_break (0);
13017 return;
13018 }
13019 pr = GNUNET_CONTAINER_multipeermap_get (tc->details.application.requests,
13020 &msg->peer);
13021 if (NULL == pr)
13022 {
13023 GNUNET_break (0);
13025 return;
13026 }
13027 (void) stop_peer_request (tc, &pr->pid, pr);
13029}

References CT_APPLICATION, GNUNET_break, GNUNET_CONTAINER_multipeermap_get(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), msg, PeerRequest::pr, stop_peer_request(), and tc.

Here is the call graph for this function:

◆ hello_for_client_cb()

static void hello_for_client_cb ( void *  cls,
const struct GNUNET_PeerIdentity pid,
const char *  uri 
)
static

Definition at line 13033 of file gnunet-service-transport.c.

13036{
13037 struct Queue *q;
13038 int pfx_len;
13039 const char *eou;
13040 char *address;
13041 (void) cls;
13042
13043 eou = strstr (uri,
13044 "://");
13045 pfx_len = eou - uri;
13046 eou += 3;
13048 "%.*s-%s",
13049 pfx_len,
13050 uri,
13051 eou);
13052
13054 "hello for client %s\n",
13055 address);
13056
13057 q = find_queue (pid, address);
13058 if (NULL == q)
13059 {
13061 }
13062 else
13065}

References address, find_queue(), GNUNET_asprintf(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, pid, q, start_address_validation(), suggest_to_connect(), and uri.

Referenced by handle_hello_for_client().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_hello_for_client()

static void handle_hello_for_client ( void *  cls,
const struct GNUNET_PEERSTORE_Record record,
const char *  emsg 
)
static

Function called by PEERSTORE for each matching record.

Parameters
clsclosure, a struct PeerRequest
recordpeerstore record information
emsgerror message, or NULL if no errors

Definition at line 13076 of file gnunet-service-transport.c.

13079{
13080 struct PeerRequest *pr = cls;
13082 struct GNUNET_MessageHeader *hello;
13083
13084 if (NULL != emsg)
13085 {
13087 "Got failure from PEERSTORE: %s\n",
13088 emsg);
13089 return;
13090 }
13091 if (NULL == GST_my_identity)
13092 {
13094 "No identity given yet!\n");
13095 return;
13096 }
13097 hello = record->value;
13098 if (0 == GNUNET_memcmp (&record->peer, GST_my_identity))
13099 {
13101 return;
13102 }
13104 if (NULL == parser)
13105 {
13107 "HELLO cannot be parsed!\n");
13108 return;
13109 }
13111 "HELLO for `%s' could be parsed, iterating addresses...!\n",
13115 NULL);
13116 GNUNET_HELLO_parser_free (parser);
13117}

References GNUNET_ERROR_TYPE_WARNING, GNUNET_HELLO_parser_free(), GNUNET_HELLO_parser_from_msg(), GNUNET_HELLO_parser_get_id(), GNUNET_HELLO_parser_iterate(), GNUNET_i2s(), GNUNET_log, GNUNET_memcmp, GNUNET_PEERSTORE_monitor_next(), GST_my_identity, hello_for_client_cb(), PeerRequest::nc, PeerRequest::pr, and record().

Referenced by handle_suggest().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ hello_for_client_error_cb()

static void hello_for_client_error_cb ( void *  cls)
static

Definition at line 13121 of file gnunet-service-transport.c.

13122{
13124 "Error in PEERSTORE monitoring\n");
13125}

References GNUNET_ERROR_TYPE_WARNING, and GNUNET_log.

Referenced by handle_suggest().

Here is the caller graph for this function:

◆ hello_for_client_sync_cb()

static void hello_for_client_sync_cb ( void *  cls)
static

Definition at line 13129 of file gnunet-service-transport.c.

13130{
13132 "Done with initial PEERSTORE iteration during monitoring\n");
13133}

References GNUNET_ERROR_TYPE_WARNING, and GNUNET_log.

Referenced by handle_suggest().

Here is the caller graph for this function:

◆ handle_suggest()

static void handle_suggest ( void *  cls,
const struct ExpressPreferenceMessage msg 
)
static

We have received a struct ExpressPreferenceMessage from an application client.

Parameters
clshandle to the client
msgthe start message

Definition at line 13144 of file gnunet-service-transport.c.

13145{
13146 struct TransportClient *tc = cls;
13147 struct PeerRequest *pr;
13148
13149 if (CT_NONE == tc->type)
13150 {
13151 tc->type = CT_APPLICATION;
13152 tc->details.application.requests =
13154 }
13155 if (CT_APPLICATION != tc->type)
13156 {
13157 GNUNET_break (0);
13159 return;
13160 }
13162 "Client suggested we talk to %s with preference %d at rate %u\n",
13163 GNUNET_i2s (&msg->peer),
13164 (int) ntohl (msg->pk),
13165 (int) ntohl (msg->bw.value__));
13166 if (0 == GNUNET_memcmp (GST_my_identity, &msg->peer))
13167 {
13169 "Client suggested connection to ourselves, ignoring...\n");
13170 return;
13171 }
13172 pr = GNUNET_new (struct PeerRequest);
13173 pr->tc = tc;
13174 pr->pid = msg->peer;
13175 pr->bw = msg->bw;
13176 pr->pk = ntohl (msg->pk);
13178 tc->details.application.requests,
13179 &pr->pid,
13180 pr,
13182 {
13183 GNUNET_break (0);
13184 GNUNET_free (pr);
13186 return;
13187 }
13188 pr->nc =
13190 GNUNET_YES,
13191 "peerstore",
13192 NULL,
13195 NULL,
13197 NULL,
13199 pr);
13201}

References CT_APPLICATION, CT_NONE, GNUNET_break, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multipeermap_create(), GNUNET_CONTAINER_multipeermap_put(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_memcmp, GNUNET_new, GNUNET_PEERSTORE_HELLO_KEY, GNUNET_PEERSTORE_monitor_start(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_YES, GST_cfg, GST_my_identity, handle_hello_for_client(), hello_for_client_error_cb(), hello_for_client_sync_cb(), msg, PeerRequest::pr, and tc.

Here is the call graph for this function:

◆ check_request_hello_validation()

static int check_request_hello_validation ( void *  cls,
const struct RequestHelloValidationMessage m 
)
static

Check GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION messages.

Parameters
clsa struct TransportClient *
mmessage to verify
Returns
GNUNET_OK on success

Definition at line 13213 of file gnunet-service-transport.c.

13215{
13216 (void) cls;
13218 return GNUNET_OK;
13219}

References GNUNET_MQ_check_zero_termination, GNUNET_OK, and m.

◆ handle_request_hello_validation()

static void handle_request_hello_validation ( void *  cls,
const struct RequestHelloValidationMessage m 
)
static

A client encountered an address of another peer.

Consider validating it, and if validation succeeds, persist it to PEERSTORE.

Parameters
clsa struct TransportClient *
mmessage to verify

Definition at line 13230 of file gnunet-service-transport.c.

13232{
13233 struct TransportClient *tc = cls;
13234 struct Queue *q;
13235
13236 q = find_queue (&m->peer, (const char *) &m[1]);
13237 if (NULL == q)
13238 {
13239 suggest_to_connect (&m->peer, (const char *) &m[1]);
13240 }
13241 else
13242 start_address_validation (&m->peer, (const char *) &m[1]);
13244}

References find_queue(), GNUNET_SERVICE_client_continue(), m, q, start_address_validation(), suggest_to_connect(), and tc.

Here is the call graph for this function:

◆ free_neighbour_cb()

static int free_neighbour_cb ( void *  cls,
const struct GNUNET_PeerIdentity pid,
void *  value 
)
static

Free neighbour entry.

Parameters
clsNULL
pidunused
valuea struct Neighbour
Returns
GNUNET_OK (always)

Definition at line 13256 of file gnunet-service-transport.c.

13259{
13260 struct Neighbour *neighbour = value;
13261
13262 (void) cls;
13263 (void) pid;
13264 GNUNET_break (0); // should this ever happen?
13265 free_neighbour (neighbour, GNUNET_YES);
13266
13267 return GNUNET_OK;
13268}

References free_neighbour(), GNUNET_break, GNUNET_OK, GNUNET_YES, pid, and value.

Referenced by do_shutdown().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_dv_routes_cb()

static int free_dv_routes_cb ( void *  cls,
const struct GNUNET_PeerIdentity pid,
void *  value 
)
static

Free DV route entry.

Parameters
clsNULL
pidunused
valuea struct DistanceVector
Returns
GNUNET_OK (always)

Definition at line 13280 of file gnunet-service-transport.c.

13283{
13284 struct DistanceVector *dv = value;
13285
13286 (void) cls;
13287 (void) pid;
13288 free_dv_route (dv);
13289
13290 return GNUNET_OK;
13291}

References free_dv_route(), GNUNET_OK, pid, and value.

Referenced by do_shutdown().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_validation_state_cb()

static int free_validation_state_cb ( void *  cls,
const struct GNUNET_PeerIdentity pid,
void *  value 
)
static

Free validation state.

Parameters
clsNULL
pidunused
valuea struct ValidationState
Returns
GNUNET_OK (always)

Definition at line 13303 of file gnunet-service-transport.c.

13306{
13307 struct ValidationState *vs = value;
13308
13309 (void) cls;
13310 (void) pid;
13312 return GNUNET_OK;
13313}

References free_validation_state(), GNUNET_OK, pid, and value.

Referenced by do_shutdown().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_pending_ack_cb()

static int free_pending_ack_cb ( void *  cls,
const struct GNUNET_Uuid key,
void *  value 
)
static

Free pending acknowledgement.

Parameters
clsNULL
keyunused
valuea struct PendingAcknowledgement
Returns
GNUNET_OK (always)

Definition at line 13325 of file gnunet-service-transport.c.

13326{
13327 struct PendingAcknowledgement *pa = value;
13328
13329 (void) cls;
13330 (void) key;
13332 return GNUNET_OK;
13333}

References free_pending_acknowledgement(), GNUNET_OK, key, and value.

Referenced by do_shutdown().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_ack_cummulator_cb()

static int free_ack_cummulator_cb ( void *  cls,
const struct GNUNET_PeerIdentity pid,
void *  value 
)
static

Free acknowledgement cummulator.

Parameters
clsNULL
pidunused
valuea struct AcknowledgementCummulator
Returns
GNUNET_OK (always)

Definition at line 13345 of file gnunet-service-transport.c.

13348{
13349 struct AcknowledgementCummulator *ac = value;
13350
13351 (void) cls;
13352 (void) pid;
13354 GNUNET_free (ac);
13355 return GNUNET_OK;
13356}

References GNUNET_free, GNUNET_OK, GNUNET_SCHEDULER_cancel(), pid, AcknowledgementCummulator::task, and value.

Referenced by do_shutdown().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ shutdown_task()

static void shutdown_task ( void *  cls)
static

Definition at line 13476 of file gnunet-service-transport.c.

13477{
13479
13481 "Shutdown task executed\n");
13482 if (NULL != clients_head)
13483 {
13484 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
13485 {
13487 "client still connected: %u\n",
13488 tc->type);
13489 }
13490 }
13491 else
13492 do_shutdown (cls);
13493
13494}

References clients_head, do_shutdown, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_YES, in_shutdown, and tc.

◆ update_hello_from_pid_change_cb()

static void update_hello_from_pid_change_cb ( void *  cls,
int  success 
)
static

Definition at line 13503 of file gnunet-service-transport.c.

13504{
13505 struct UpdateHelloFromPidCtx *pc = cls;
13506
13507 if (GNUNET_OK != success)
13508 {
13510 "Failed to store our new hello with peerstore\n");
13511 }
13512 GNUNET_free (pc);
13514 "Stored our new hello with peerstore\n");
13515}

References GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_OK, and pc.

Referenced by pils_pid_change_cb().

Here is the caller graph for this function:

◆ print_address_list()

void print_address_list ( void *  cls,
const struct GNUNET_PeerIdentity pid,
const char *  uri 
)

Definition at line 13519 of file gnunet-service-transport.c.

13522{
13524 "%s\n", uri);
13525}

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, and uri.

Referenced by pils_pid_change_cb().

Here is the caller graph for this function:

◆ pils_pid_change_cb()

static void pils_pid_change_cb ( void *  cls,
const struct GNUNET_HELLO_Parser parser,
const struct GNUNET_HashCode hash 
)
static

Callback called when pils service updates us with our new peer identity.

Parameters
clsclosure given to GNUNET_PILS_connect
peer_idthe new peer id
hashThe hash of addresses the peer id is based on. This hash is also returned by #GNUNET_PILS_feed_address.

FIXME we may want to have a sanity check here that verifies that our address list in the builder is the same as the one in the parser (and hence derived from the correct set). If it is NOT, then it is very likely that PILS is behind and will send another update shortly. In this case, we may want to hold off and not generate the new HELLO.

Definition at line 13538 of file gnunet-service-transport.c.

13541{
13542 struct GNUNET_MQ_Envelope *env;
13543 const struct GNUNET_MessageHeader *msg;
13544 struct UpdateHelloFromPidCtx *sc;
13545 struct GNUNET_HELLO_Builder *nbuilder;
13546 struct GNUNET_PeerIdentity npid;
13547
13548 if (NULL == GST_my_identity)
13550 if (NULL == GST_my_hello)
13553 "My current identity is `%s'\n",
13565 nbuilder = GNUNET_HELLO_builder_from_parser (parser,
13566 &npid);
13567 if (GNUNET_NO ==
13569 {
13571 "New PID from PILS is derived from address list inconsistend with ours. Ignoring...\n");
13573 "Proposed address list:\n");
13576 "Current address list:\n");
13578 GNUNET_HELLO_builder_free (nbuilder);
13579 return;
13580 }
13581 GST_my_hello = nbuilder;
13582 memcpy (GST_my_identity, &npid, sizeof npid);
13584 "My new identity is `%s'\n",
13590 msg,
13592 sc);
13593 GNUNET_free (env);
13594}

References env, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_HELLO_builder_address_list_cmp(), GNUNET_HELLO_builder_free(), GNUNET_HELLO_builder_from_parser(), GNUNET_HELLO_builder_iterate(), GNUNET_HELLO_builder_new(), GNUNET_HELLO_parser_to_env(), GNUNET_i2s_full(), GNUNET_log, GNUNET_MQ_env_get_msg(), GNUNET_new, GNUNET_NO, GNUNET_PEERSTORE_hello_add(), GST_my_hello, GST_my_identity, msg, peerstore, print_address_list(), sc, and update_hello_from_pid_change_cb().

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ run()

static void run ( void *  cls,
const struct GNUNET_CONFIGURATION_Handle c,
struct GNUNET_SERVICE_Handle service 
)
static

Initiate transport service.

Parameters
clsclosure
cconfiguration to use
servicethe initialized service

Definition at line 13605 of file gnunet-service-transport.c.

13608{
13609 (void) cls;
13610 (void) service;
13611 /* setup globals */
13614 GST_cfg = c;
13622 GNUNET_YES);
13627 // TODO check for all uses of GST_my_hello that it is not used uninitialized
13629 "transport",
13630 "USE_BURST_NAT");
13631 if (GNUNET_SYSERR == use_burst)
13633 "Could not configure burst nat use. Default to no.\n");
13639 "transport",
13640 0,
13641 0,
13642 NULL,
13643 0,
13644 NULL,
13645 NULL,
13646 NULL);
13647 if (NULL == peerstore)
13648 {
13649 GNUNET_break (0);
13651 return;
13652 }
13653 GST_my_identity = NULL;
13656 NULL); // FIXME we need to wait for
13657 // our first peer id before
13658 // we can start the service
13659 // completely - PILS in turn
13660 // waits for the first
13661 // addresses from the
13662 // communicators in order to
13663 // be able to generate a
13664 // peer id
13665 if (NULL == pils)
13666 {
13667 GNUNET_break (0);
13669 return;
13670 }
13671}

References ack_cummulators, backtalkers, dv_routes, dvlearn_map, GNUNET_break, GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CONTAINER_heap_create(), GNUNET_CONTAINER_HEAP_ORDER_MIN, GNUNET_CONTAINER_multihashmap_create(), GNUNET_CONTAINER_multipeermap_create(), GNUNET_CONTAINER_multishortmap_create(), GNUNET_CONTAINER_multiuuidmap_create(), GNUNET_ERROR_TYPE_WARNING, GNUNET_HELLO_builder_new(), GNUNET_log, GNUNET_NAT_register(), GNUNET_NO, GNUNET_PEERSTORE_connect(), GNUNET_PILS_connect(), GNUNET_SCHEDULER_add_shutdown(), GNUNET_SCHEDULER_shutdown(), GNUNET_STATISTICS_create(), GNUNET_SYSERR, GNUNET_TIME_absolute_get_monotonic(), GNUNET_YES, GST_cfg, GST_my_hello, GST_my_identity, GST_stats, hello_mono_time, in_shutdown, links, MAX_DV_LEARN_PENDING, neighbours, nh, peerstore, pending_acks, pils, pils_pid_change_cb(), revalidation_map, service, shutdown_task, use_burst, validation_heap, and validation_map.

Here is the call graph for this function:

◆ GNUNET_SERVICE_MAIN()

GNUNET_SERVICE_MAIN ( GNUNET_OS_project_data_gnunet()  ,
"transport"  ,
GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN  ,
run,
client_connect_cb,
client_disconnect_cb,
NULL  ,
GNUNET_MQ_hd_fixed_size(suggest, GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST, struct ExpressPreferenceMessage, NULL)  ,
GNUNET_MQ_hd_fixed_size(suggest_cancel, GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST_CANCEL, struct ExpressPreferenceMessage, NULL)  ,
GNUNET_MQ_hd_var_size(request_hello_validation, GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION, struct RequestHelloValidationMessage, NULL)  ,
GNUNET_MQ_hd_fixed_size(client_start, GNUNET_MESSAGE_TYPE_TRANSPORT_START, struct StartMessage, NULL)  ,
GNUNET_MQ_hd_var_size(client_send, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, struct OutboundMessage, NULL)  ,
GNUNET_MQ_hd_fixed_size(client_recv_ok, GNUNET_MESSAGE_TYPE_TRANSPORT_RECV_OK, struct RecvOkMessage, NULL)  ,
GNUNET_MQ_hd_var_size(communicator_available, GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR, struct GNUNET_TRANSPORT_CommunicatorAvailableMessage, NULL)  ,
GNUNET_MQ_hd_var_size(communicator_backchannel, GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL, struct GNUNET_TRANSPORT_CommunicatorBackchannel, NULL)  ,
GNUNET_MQ_hd_var_size(add_address, GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS, struct GNUNET_TRANSPORT_AddAddressMessage, NULL)  ,
GNUNET_MQ_hd_fixed_size(del_address, GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS, struct GNUNET_TRANSPORT_DelAddressMessage, NULL)  ,
GNUNET_MQ_hd_var_size(incoming_msg, GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG, struct GNUNET_TRANSPORT_IncomingMessage, NULL)  ,
GNUNET_MQ_hd_fixed_size(queue_create_ok, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK, struct GNUNET_TRANSPORT_CreateQueueResponse, NULL)  ,
GNUNET_MQ_hd_fixed_size(queue_create_fail, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL, struct GNUNET_TRANSPORT_CreateQueueResponse, NULL)  ,
GNUNET_MQ_hd_var_size(add_queue_message, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP, struct GNUNET_TRANSPORT_AddQueueMessage, NULL)  ,
GNUNET_MQ_hd_fixed_size(update_queue_message, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_UPDATE, struct GNUNET_TRANSPORT_UpdateQueueMessage, NULL)  ,
GNUNET_MQ_hd_fixed_size(del_queue_message, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN, struct GNUNET_TRANSPORT_DelQueueMessage, NULL)  ,
GNUNET_MQ_hd_fixed_size(send_message_ack, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK, struct GNUNET_TRANSPORT_SendMessageToAck, NULL)  ,
GNUNET_MQ_hd_fixed_size(burst_finished, GNUNET_MESSAGE_TYPE_TRANSPORT_BURST_FINISHED, struct GNUNET_TRANSPORT_BurstFinished, NULL)  ,
GNUNET_MQ_hd_fixed_size(monitor_start, GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START, struct GNUNET_TRANSPORT_MonitorStart, NULL)  ,
GNUNET_MQ_handler_end()   
)

Define "main" method using service macro.

Variable Documentation

◆ ring_buffer

struct RingBufferEntry* ring_buffer[RING_BUFFER_SIZE]
static

Ring buffer for a CORE message we did not deliver to CORE, because of missing virtual link to sender.

Definition at line 2876 of file gnunet-service-transport.c.

Referenced by handle_raw_message(), and send_msg_from_cache().

◆ ring_buffer_head

unsigned int ring_buffer_head
static

Head of the ring buffer.

Definition at line 2881 of file gnunet-service-transport.c.

Referenced by handle_raw_message(), and send_msg_from_cache().

◆ is_ring_buffer_full

unsigned int is_ring_buffer_full
static

Is the ring buffer filled up to RING_BUFFER_SIZE.

Definition at line 2886 of file gnunet-service-transport.c.

Referenced by handle_raw_message(), and send_msg_from_cache().

◆ ring_buffer_dv

struct PendingMessage* ring_buffer_dv[RING_BUFFER_SIZE]
static

Ring buffer for a forwarded DVBox message we did not deliver to the next hop, because of missing virtual link that hop.

Definition at line 2891 of file gnunet-service-transport.c.

Referenced by forward_dv_box(), and send_msg_from_cache().

◆ ring_buffer_dv_head

unsigned int ring_buffer_dv_head
static

Head of the ring buffer.

Definition at line 2896 of file gnunet-service-transport.c.

Referenced by forward_dv_box(), and send_msg_from_cache().

◆ is_ring_buffer_dv_full

unsigned int is_ring_buffer_dv_full
static

Is the ring buffer filled up to RING_BUFFER_SIZE.

Definition at line 2901 of file gnunet-service-transport.c.

Referenced by forward_dv_box(), and send_msg_from_cache().

◆ clients_head

◆ clients_tail

struct TransportClient* clients_tail
static

Tail of linked list of all clients to this service.

Definition at line 2911 of file gnunet-service-transport.c.

Referenced by client_connect_cb(), and client_disconnect_cb().

◆ GST_stats

◆ GST_cfg

◆ GST_my_identity

◆ GST_my_hello

◆ neighbours

struct GNUNET_CONTAINER_MultiPeerMap* neighbours
static

Map from PIDs to struct Neighbour entries.

A peer is a neighbour if we have an MQ to it from some communicator.

Definition at line 2937 of file gnunet-service-transport.c.

Referenced by do_shutdown(), free_neighbour(), handle_add_queue_message(), handle_dv_learn(), handle_monitor_start(), lookup_neighbour(), run(), sign_dv_init_cb(), and start_dv_learn().

◆ backtalkers

struct GNUNET_CONTAINER_MultiPeerMap* backtalkers
static

Map from PIDs to struct Backtalker entries.

A peer is a backtalker if it recently send us backchannel messages.

Definition at line 2943 of file gnunet-service-transport.c.

Referenced by decaps_dv_box_cb(), do_shutdown(), free_backtalker(), and run().

◆ ack_cummulators

struct GNUNET_CONTAINER_MultiPeerMap* ack_cummulators
static

Map from PIDs to struct AcknowledgementCummulators.

Here we track the cumulative ACKs for transmission.

Definition at line 2949 of file gnunet-service-transport.c.

Referenced by cummulative_ack(), destroy_ack_cummulator(), do_shutdown(), and run().

◆ pending_acks

struct GNUNET_CONTAINER_MultiUuidmap* pending_acks
static

Map of pending acknowledgements, mapping struct AcknowledgementUUID to a struct PendingAcknowledgement.

Definition at line 2955 of file gnunet-service-transport.c.

Referenced by do_shutdown(), free_pending_acknowledgement(), handle_reliability_ack(), prepare_pending_acknowledgement(), and run().

◆ dv_routes

struct GNUNET_CONTAINER_MultiPeerMap* dv_routes
static

Map from PIDs to struct DistanceVector entries describing known paths to the peer.

Definition at line 2961 of file gnunet-service-transport.c.

Referenced by do_shutdown(), free_dv_route(), learn_dv_path(), route_control_message_without_fc(), and run().

◆ validation_map

struct GNUNET_CONTAINER_MultiPeerMap* validation_map
static

Map from PIDs to struct ValidationState entries describing addresses we are aware of and their validity state.

Definition at line 2967 of file gnunet-service-transport.c.

Referenced by do_shutdown(), free_validation_state(), handle_add_queue_message(), handle_validation_response(), run(), and start_address_validation().

◆ revalidation_map

struct GNUNET_CONTAINER_MultiHashMap* revalidation_map
static

Map from addresses to struct ValidationState entries describing addresses we are aware of and their validity state.

Definition at line 2973 of file gnunet-service-transport.c.

Referenced by do_shutdown(), free_validation_state(), handle_validation_response(), run(), and validation_transmit_on_queue().

◆ links

◆ dvlearn_map

struct GNUNET_CONTAINER_MultiShortmap* dvlearn_map
static

Map from challenges to struct LearnLaunchEntry values.

Definition at line 2984 of file gnunet-service-transport.c.

Referenced by do_shutdown(), run(), and start_dv_learn().

◆ lle_head

struct LearnLaunchEntry* lle_head = NULL
static

Head of a DLL sorted by launch time.

Definition at line 2989 of file gnunet-service-transport.c.

Referenced by do_shutdown(), and start_dv_learn().

◆ lle_tail

struct LearnLaunchEntry* lle_tail = NULL
static

Tail of a DLL sorted by launch time.

Definition at line 2994 of file gnunet-service-transport.c.

Referenced by do_shutdown(), and start_dv_learn().

◆ validation_heap

struct GNUNET_CONTAINER_Heap* validation_heap
static

MIN Heap sorted by "next_challenge" to struct ValidationState entries sorting addresses we are aware of by when we should next try to (re)validate (or expire) them.

Definition at line 3001 of file gnunet-service-transport.c.

Referenced by do_shutdown(), run(), update_next_challenge_time(), and validation_start_cb().

◆ nh

struct GNUNET_NAT_Handle* nh

Handle for connect to the NAT service.

Definition at line 3006 of file gnunet-service-transport.c.

Referenced by do_shutdown(), handle_flow_control(), and run().

◆ peerstore

◆ pils

◆ pils_requests_head

◆ pils_requests_tail

◆ dvlearn_task

struct GNUNET_SCHEDULER_Task* dvlearn_task
static

Task run to initiate DV learning.

Definition at line 3052 of file gnunet-service-transport.c.

Referenced by do_shutdown(), handle_add_queue_message(), sign_dv_init_cb(), and start_dv_learn().

◆ validation_task

struct GNUNET_SCHEDULER_Task* validation_task
static

Task to run address validation.

Definition at line 3057 of file gnunet-service-transport.c.

Referenced by do_shutdown(), update_next_challenge_time(), and validation_start_cb().

◆ pils_feed_task

struct GNUNET_SCHEDULER_Task* pils_feed_task
static

Task to feed addresses to PILS.

Definition at line 3062 of file gnunet-service-transport.c.

Referenced by do_shutdown(), feed_addresses_to_pils(), handle_add_address(), and handle_del_address().

◆ ir_head

struct IncomingRequest* ir_head
static

List of incoming connections where we are trying to get a connection back established.

Length kept in ir_total.

Definition at line 3069 of file gnunet-service-transport.c.

Referenced by do_shutdown(), free_incoming_request(), and sign_t_validation_cb().

◆ ir_tail

struct IncomingRequest* ir_tail
static

Tail of DLL starting at ir_head.

Definition at line 3074 of file gnunet-service-transport.c.

Referenced by free_incoming_request(), and sign_t_validation_cb().

◆ ir_total

unsigned int ir_total
static

Length of the DLL starting at ir_head.

Definition at line 3079 of file gnunet-service-transport.c.

Referenced by do_shutdown(), free_incoming_request(), and sign_t_validation_cb().

◆ logging_uuid_gen

unsigned long long logging_uuid_gen
static

Generator of logging_uuid in struct PendingMessage.

Definition at line 3084 of file gnunet-service-transport.c.

Referenced by extract_box_cb(), forward_dv_box(), fragment_message(), handle_client_send(), and reliability_box_message().

◆ burst_running

enum GNUNET_GenericReturnValue burst_running
static

Is there a burst running?

Definition at line 3089 of file gnunet-service-transport.c.

Referenced by burst_timeout(), handle_burst_finished(), queue_burst(), and start_burst().

◆ hello_mono_time

struct GNUNET_TIME_Absolute hello_mono_time
static

Monotonic time we use for HELLOs generated at this time.

TODO: we should increase this value from time to time (i.e. whenever a struct AddressListEntry actually expires), but IF we do this, we must also update all (remaining) addresses in the PEERSTORE at that time! (So for now only increased when the peer is restarted, which hopefully roughly matches whenever our addresses change.)

Definition at line 3099 of file gnunet-service-transport.c.

Referenced by run(), and store_pi().

◆ in_shutdown

int in_shutdown
static

Indication if we have received a shutdown signal and are in the process of cleaning up.

Definition at line 3105 of file gnunet-service-transport.c.

Referenced by client_disconnect_cb(), run(), and shutdown_task().

◆ burst_task

struct GNUNET_SCHEDULER_Task* burst_task
static

The task to start the burst.

Definition at line 3110 of file gnunet-service-transport.c.

Referenced by queue_burst(), and start_burst().

◆ burst_timeout_task

struct GNUNET_SCHEDULER_Task* burst_timeout_task

Definition at line 3112 of file gnunet-service-transport.c.

Referenced by start_burst().

◆ use_burst

enum GNUNET_GenericReturnValue use_burst

Definition at line 3114 of file gnunet-service-transport.c.

Referenced by queue_burst(), and run().