GNUnet 0.26.2-32-gd298f7855
 
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 */
5102 &key->material,
5103 sizeof(key->material),
5104 km,
5105 GNUNET_CRYPTO_kdf_arg_string ("gnunet-transport-dv-key"),
5109 "Deriving backchannel key based on KM %s and IV %s\n",
5110 GNUNET_sh2s (km),
5111 GNUNET_sh2s (iv));
5112 GNUNET_assert (0 == gcry_cipher_open (&key->cipher,
5113 GCRY_CIPHER_AES256 /* low level: go for speed */
5114 ,
5115 GCRY_CIPHER_MODE_CTR,
5116 0 /* flags */));
5117 GNUNET_assert (0 == gcry_cipher_setkey (key->cipher,
5118 &key->material.aes_key,
5119 sizeof(key->material.aes_key)));
5120 gcry_cipher_setctr (key->cipher,
5121 &key->material.aes_ctr,
5122 sizeof(key->material.aes_ctr));
5123}
5124
5125
5135static void
5136dv_hmac (const struct DVKeyState *key,
5137 struct GNUNET_HashCode *hmac,
5138 const void *data,
5139 size_t data_size)
5140{
5141 GNUNET_CRYPTO_hmac (&key->material.hmac_key, data, data_size, hmac);
5142}
5143
5144
5154static void
5155dv_encrypt (struct DVKeyState *key, const void *in, void *dst, size_t in_size)
5156{
5157 GNUNET_assert (0 ==
5158 gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size));
5159}
5160
5161
5172static enum GNUNET_GenericReturnValue
5173dv_decrypt (struct DVKeyState *key,
5174 void *out,
5175 const void *ciph,
5176 size_t out_size)
5177{
5178 return (0 ==
5179 gcry_cipher_decrypt (key->cipher,
5180 out, out_size,
5181 ciph, out_size)) ? GNUNET_OK : GNUNET_SYSERR;
5182}
5183
5184
5190static void
5191dv_key_clean (struct DVKeyState *key)
5192{
5193 gcry_cipher_close (key->cipher);
5194 GNUNET_CRYPTO_zero_keys (&key->material, sizeof(key->material));
5195}
5196
5197
5208typedef void (*DVMessageHandler) (void *cls,
5209 struct Neighbour *next_hop,
5210 const struct GNUNET_MessageHeader *hdr,
5212
5227static struct GNUNET_TIME_Relative
5229 unsigned int num_dvhs,
5230 struct DistanceVectorHop **dvhs,
5231 const struct GNUNET_MessageHeader *hdr,
5232 DVMessageHandler use,
5233 void *use_cls,
5235 enum GNUNET_GenericReturnValue without_fc)
5236{
5237 struct TransportDVBoxMessage box_hdr;
5238 struct TransportDVBoxPayloadP payload_hdr;
5239 uint16_t enc_body_size = ntohs (hdr->size);
5240 char enc[sizeof(struct TransportDVBoxPayloadP) + enc_body_size] GNUNET_ALIGN;
5241 struct DVKeyState *key;
5242 struct GNUNET_TIME_Relative rtt;
5243 struct GNUNET_ShortHashCode km;
5244
5245 key = GNUNET_new (struct DVKeyState);
5246 /* Encrypt payload */
5247 box_hdr.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX);
5248 box_hdr.total_hops = htons (0);
5249 box_hdr.without_fc = htons (without_fc);
5250 // update_ephemeral (dv);
5251 if (0 ==
5252 GNUNET_TIME_absolute_get_remaining (dv->ephemeral_validity).rel_value_us)
5253 {
5254 GNUNET_CRYPTO_eddsa_kem_encaps (&dv->target.public_key,
5255 &dv->ephemeral_key,
5256 &km);
5257 dv->km = GNUNET_new (struct GNUNET_ShortHashCode);
5258 GNUNET_memcpy (dv->km, &km, sizeof(struct GNUNET_ShortHashCode));
5259 sign_ephemeral (dv);
5260 }
5261 box_hdr.ephemeral_key = dv->ephemeral_key;
5262 payload_hdr.sender_sig = dv->sender_sig;
5263
5265 &box_hdr.iv,
5266 sizeof(box_hdr.iv));
5267 // We are creating this key, so this must work.
5268 // FIXME: Possibly also add return values here. We are processing
5269 // Input from other peers...
5270 dv_setup_key_state_from_km (dv->km, &box_hdr.iv, key);
5271 payload_hdr.sender = *GST_my_identity;
5272 payload_hdr.monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
5273 dv_encrypt (key, &payload_hdr, enc, sizeof(payload_hdr));
5274 dv_encrypt (key,
5275 hdr,
5276 &enc[sizeof(struct TransportDVBoxPayloadP)],
5277 enc_body_size);
5278 dv_hmac (key, &box_hdr.hmac, enc, sizeof(enc));
5279 dv_key_clean (key);
5281 /* For each selected path, take the pre-computed header and body
5282 and add the path in the middle of the message; then send it. */
5283 for (unsigned int i = 0; i < num_dvhs; i++)
5284 {
5285 struct DistanceVectorHop *dvh = dvhs[i];
5286 unsigned int num_hops = dvh->distance + 1;
5287 char buf[sizeof(struct TransportDVBoxMessage)
5288 + sizeof(struct GNUNET_PeerIdentity) * num_hops
5289 + sizeof(struct TransportDVBoxPayloadP)
5290 + enc_body_size] GNUNET_ALIGN;
5291 struct GNUNET_PeerIdentity *dhops;
5292
5293 box_hdr.header.size = htons (sizeof(buf));
5294 box_hdr.orig_size = htons (sizeof(buf));
5295 box_hdr.num_hops = htons (num_hops);
5296 memcpy (buf, &box_hdr, sizeof(box_hdr));
5297 dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
5298 memcpy (dhops,
5299 dvh->path,
5300 dvh->distance * sizeof(struct GNUNET_PeerIdentity));
5301 dhops[dvh->distance] = dv->target;
5302 if (GNUNET_EXTRA_LOGGING > 0)
5303 {
5304 char *path;
5305
5307 for (unsigned int j = 0; j < num_hops; j++)
5308 {
5309 char *tmp;
5310
5311 GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
5312 GNUNET_free (path);
5313 path = tmp;
5314 }
5316 "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
5317 ntohs (hdr->type),
5318 GNUNET_i2s (&dv->target),
5319 i + 1,
5320 num_dvhs,
5321 path);
5322 GNUNET_free (path);
5323 }
5324 rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
5325 memcpy (&dhops[num_hops], enc, sizeof(enc));
5326 use (use_cls,
5327 dvh->next_hop,
5328 (const struct GNUNET_MessageHeader *) buf,
5329 options);
5330 GNUNET_free (key);
5331 }
5332 return rtt;
5333}
5334
5335
5345static void
5346send_dv_to_neighbour (void *cls,
5347 struct Neighbour *next_hop,
5348 const struct GNUNET_MessageHeader *hdr,
5350{
5351 (void) cls;
5352 (void) route_via_neighbour (next_hop, hdr, RMO_UNCONFIRMED_ALLOWED);
5353}
5354
5355
5367static struct GNUNET_TIME_Relative
5369// route_control_message_without_fc (const struct GNUNET_PeerIdentity *target,
5370 const struct GNUNET_MessageHeader *hdr,
5372{
5373 // struct VirtualLink *vl;
5374 struct Neighbour *n;
5375 struct DistanceVector *dv;
5376 struct GNUNET_TIME_Relative rtt1;
5377 struct GNUNET_TIME_Relative rtt2;
5378 const struct GNUNET_PeerIdentity *target = &vl->target;
5379
5381 "Trying to route message of type %u to %s without fc\n",
5382 ntohs (hdr->type),
5383 GNUNET_i2s (target));
5384
5385 // TODO Do this elsewhere. vl should be given as parameter to method.
5386 // vl = lookup_virtual_link (target);
5387 GNUNET_assert (NULL != vl && GNUNET_YES == vl->confirmed);
5388 if (NULL == vl)
5390 n = vl->n;
5391 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
5392 if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
5393 {
5394 /* if confirmed is required, and we do not have anything
5395 confirmed, drop respective options */
5396 if (NULL == n)
5397 n = lookup_neighbour (target);
5398 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
5400 }
5401 if ((NULL == n) && (NULL == dv))
5402 {
5404 "Cannot route message of type %u to %s: no route\n",
5405 ntohs (hdr->type),
5406 GNUNET_i2s (target));
5408 "# Messages dropped in routing: no acceptable method",
5409 1,
5410 GNUNET_NO);
5412 }
5414 "Routing message of type %u to %s with options %X\n",
5415 ntohs (hdr->type),
5416 GNUNET_i2s (target),
5417 (unsigned int) options);
5418 /* If both dv and n are possible and we must choose:
5419 flip a coin for the choice between the two; for now 50/50 */
5420 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
5421 {
5423 n = NULL;
5424 else
5425 dv = NULL;
5426 }
5427 if ((NULL != n) && (NULL != dv))
5428 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
5429 enough for redundancy, so clear the flag. */
5432 if (NULL != n)
5433 {
5435 "Try to route message of type %u to %s without fc via neighbour\n",
5436 ntohs (hdr->type),
5437 GNUNET_i2s (target));
5438 rtt1 = route_via_neighbour (n, hdr, options);
5439 }
5440 if (NULL != dv)
5441 {
5442 struct DistanceVectorHop *hops[2];
5443 unsigned int res;
5444
5446 options,
5447 hops,
5448 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
5449 if (0 == res)
5450 {
5452 "Failed to route message, could not determine DV path\n");
5453 return rtt1;
5454 }
5456 "encapsulate_for_dv 1\n");
5457 rtt2 = encapsulate_for_dv (dv,
5458 res,
5459 hops,
5460 hdr,
5462 NULL,
5464 GNUNET_YES);
5465 }
5466 return GNUNET_TIME_relative_min (rtt1, rtt2);
5467}
5468
5469
5470static void
5471consider_sending_fc (void *cls);
5472
5479static void
5480task_consider_sending_fc (void *cls)
5481{
5482 struct VirtualLink *vl = cls;
5483 vl->fc_retransmit_task = NULL;
5484 consider_sending_fc (cls);
5485}
5486
5487
5488static char *
5489get_address_without_port (const char *address);
5490
5491
5493{
5494 size_t off;
5495 char *tgnas;
5496};
5497
5498
5499static enum GNUNET_GenericReturnValue
5500add_global_addresses (void *cls,
5501 const struct GNUNET_PeerIdentity *pid,
5502 void *value)
5503{
5504 struct AddGlobalAddressesContext *ctx = cls;
5505 struct TransportGlobalNattedAddress *tgna = value;
5506 char *addr = (char *) &tgna[1];
5507
5509 "sending address %s length %u\n",
5510 addr,
5511 ntohl (tgna->address_length));
5512 GNUNET_memcpy (&(ctx->tgnas[ctx->off]), tgna, sizeof (struct
5514 + ntohl (tgna->address_length));
5515 ctx->off += sizeof(struct TransportGlobalNattedAddress) + ntohl (tgna->
5517
5518 return GNUNET_OK;
5519}
5520
5521
5522static struct GNUNET_TIME_Relative
5523calculate_rtt (struct DistanceVector *dv);
5524
5525
5532static void
5533consider_sending_fc (void *cls)
5534{
5535 struct VirtualLink *vl = cls;
5536 struct GNUNET_TIME_Absolute monotime;
5537 struct TransportFlowControlMessage *fc;
5539 struct GNUNET_TIME_Relative rtt;
5540 struct GNUNET_TIME_Relative rtt_average;
5541 struct Neighbour *n = vl->n;
5542
5543 if (NULL != n && 0 < n->number_of_addresses)
5544 {
5545 size_t addresses_size =
5546 n->number_of_addresses * sizeof (struct TransportGlobalNattedAddress) + n
5547 ->size_of_global_addresses;
5548 char *tgnas = GNUNET_malloc (addresses_size);
5550 ctx.off = 0;
5551 ctx.tgnas = tgnas;
5552
5554 + addresses_size);
5555 fc->header.size = htons (sizeof(struct TransportFlowControlMessage)
5556 + addresses_size);
5557 fc->size_of_addresses = htonl (n->size_of_global_addresses);
5558 fc->number_of_addresses = htonl (n->number_of_addresses);
5561 &ctx);
5564 }
5565 else
5566 {
5567 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage));
5568 fc->header.size = htons (sizeof(struct TransportFlowControlMessage));
5569 }
5570
5572 /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
5573 it always! */
5574 /* For example, we should probably ONLY do this if a bit more than
5575 an RTT has passed, or if the window changed "significantly" since
5576 then. See vl->last_fc_rtt! NOTE: to do this properly, we also
5577 need an estimate for the bandwidth-delay-product for the entire
5578 VL, as that determines "significantly". We have the delay, but
5579 the bandwidth statistics need to be added for the VL!*/(void) duration;
5580
5581 if (NULL != vl->dv)
5582 rtt_average = calculate_rtt (vl->dv);
5583 else
5584 rtt_average = GNUNET_TIME_UNIT_FOREVER_REL;
5585 fc->rtt = GNUNET_TIME_relative_hton (rtt_average);
5587 "Sending FC seq %u to %s with new window %llu %lu %u\n",
5588 (unsigned int) vl->fc_seq_gen,
5589 GNUNET_i2s (&vl->target),
5590 (unsigned long long) vl->incoming_fc_window_size,
5591 (unsigned long) rtt_average.rel_value_us,
5592 vl->sync_ready);
5594 vl->last_fc_transmission = monotime;
5595 fc->sync_ready = vl->sync_ready;
5597 fc->seq = htonl (vl->fc_seq_gen++);
5598 fc->inbound_window_size = GNUNET_htonll (vl->incoming_fc_window_size
5601 fc->outbound_sent = GNUNET_htonll (vl->outbound_fc_window_size_used);
5602 fc->outbound_window_size = GNUNET_htonll (vl->outbound_fc_window_size);
5603 fc->sender_time = GNUNET_TIME_absolute_hton (monotime);
5605 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
5606 {
5609 "FC retransmission to %s failed, will retry in %s\n",
5610 GNUNET_i2s (&vl->target),
5613 }
5614 else
5615 {
5616 /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
5617 vl->last_fc_rtt = rtt;
5618 }
5619 if (NULL != vl->fc_retransmit_task)
5622 {
5624 vl->fc_retransmit_count = 0;
5625 }
5626 vl->fc_retransmit_task =
5628 vl->fc_retransmit_count++;
5629 GNUNET_free (fc);
5630}
5631
5632
5649static void
5651{
5652 struct Neighbour *n = vl->n;
5653 struct DistanceVector *dv = vl->dv;
5654 struct GNUNET_TIME_Absolute now;
5655 struct VirtualLink *vl_next_hop;
5656 int elig;
5657
5659 "check_vl_transmission to target %s\n",
5660 GNUNET_i2s (&vl->target));
5661 /* Check that we have an eligible pending message!
5662 (cheaper than having #transmit_on_queue() find out!) */
5663 elig = GNUNET_NO;
5664 for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
5665 pm = pm->next_vl)
5666 {
5668 "check_vl_transmission loop\n");
5669 if (NULL != pm->qe)
5670 continue; /* not eligible, is in a queue! */
5671 if (pm->bytes_msg + vl->outbound_fc_window_size_used >
5673 {
5675 "Stalled message %" PRIu64
5676 " transmission on VL %s due to flow control: %llu < %llu\n",
5677 pm->logging_uuid,
5678 GNUNET_i2s (&vl->target),
5679 (unsigned long long) vl->outbound_fc_window_size,
5680 (unsigned long long) (pm->bytes_msg
5683 return; /* We have a message, but flow control says "nope" */
5684 }
5686 "Target window on VL %s not stalled. Scheduling transmission on queue\n",
5687 GNUNET_i2s (&vl->target));
5688 /* Notify queues at direct neighbours that we are interested */
5689 now = GNUNET_TIME_absolute_get ();
5690 if (NULL != n)
5691 {
5692 for (struct Queue *queue = n->queue_head; NULL != queue;
5693 queue = queue->next_neighbour)
5694 {
5695 if ((GNUNET_YES == queue->idle) &&
5696 (queue->validated_until.abs_value_us > now.abs_value_us))
5697 {
5699 "Direct neighbour %s not stalled\n",
5700 GNUNET_i2s (&n->pid));
5702 queue,
5704 elig = GNUNET_YES;
5705 }
5706 else
5708 "Neighbour Queue QID: %u (%u) busy or invalid\n",
5709 queue->qid,
5710 queue->idle);
5711 }
5712 }
5713 /* Notify queues via DV that we are interested */
5714 if (NULL != dv)
5715 {
5716 /* Do DV with lower scheduler priority, which effectively means that
5717 IF a neighbour exists and is available, we prefer it. */
5718 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5719 pos = pos->next_dv)
5720 {
5721 struct Neighbour *nh_iter = pos->next_hop;
5722
5723
5724 if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
5725 continue; /* skip this one: path not validated */
5726 else
5727 {
5728 vl_next_hop = lookup_virtual_link (&nh_iter->pid);
5729 GNUNET_assert (NULL != vl_next_hop);
5730 if (pm->bytes_msg + vl_next_hop->outbound_fc_window_size_used >
5731 vl_next_hop->outbound_fc_window_size)
5732 {
5734 "Stalled message %" PRIu64
5735 " transmission on next hop %s due to flow control: %llu < %llu\n",
5736 pm->logging_uuid,
5737 GNUNET_i2s (&vl_next_hop->target),
5738 (unsigned long
5739 long) vl_next_hop->outbound_fc_window_size,
5740 (unsigned long long) (pm->bytes_msg
5741 + vl_next_hop->
5742 outbound_fc_window_size_used));
5743 consider_sending_fc (vl_next_hop);
5744 continue; /* We have a message, but flow control says "nope" for the first hop of this path */
5745 }
5746 for (struct Queue *queue = nh_iter->queue_head; NULL != queue;
5747 queue = queue->next_neighbour)
5748 if ((GNUNET_YES == queue->idle) &&
5749 (queue->validated_until.abs_value_us > now.abs_value_us))
5750 {
5752 "Next hop neighbour %s not stalled\n",
5753 GNUNET_i2s (&nh_iter->pid));
5755 queue,
5757 elig = GNUNET_YES;
5758 }
5759 else
5761 "DV Queue QID: %u (%u) busy or invalid\n",
5762 queue->qid,
5763 queue->idle);
5764 }
5765 }
5766 }
5767 if (GNUNET_YES == elig)
5769 "Eligible message %" PRIu64 " of size %u to %s: %llu/%llu\n",
5770 pm->logging_uuid,
5771 pm->bytes_msg,
5772 GNUNET_i2s (&vl->target),
5773 (unsigned long long) vl->outbound_fc_window_size,
5774 (unsigned long long) (pm->bytes_msg
5776 break;
5777 }
5778}
5779
5780
5787static void
5788handle_client_send (void *cls, const struct OutboundMessage *obm)
5789{
5790 struct TransportClient *tc = cls;
5791 struct PendingMessage *pm;
5792 const struct GNUNET_MessageHeader *obmm;
5793 uint32_t bytes_msg;
5794 struct VirtualLink *vl;
5796
5797 GNUNET_assert (CT_CORE == tc->type);
5798 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
5799 bytes_msg = ntohs (obmm->size);
5800 pp = ntohl (obm->priority);
5801 vl = lookup_virtual_link (&obm->peer);
5802 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
5803 {
5805 "Don't have %s as a neighbour (anymore).\n",
5806 GNUNET_i2s (&obm->peer));
5807 /* Failure: don't have this peer as a neighbour (anymore).
5808 Might have gone down asynchronously, so this is NOT
5809 a protocol violation by CORE. Still count the event,
5810 as this should be rare. */
5813 "# messages dropped (neighbour unknown)",
5814 1,
5815 GNUNET_NO);
5816 return;
5817 }
5818
5819 pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
5821 "1 created pm %p storing vl %p\n",
5822 pm,
5823 vl);
5824 pm->logging_uuid = logging_uuid_gen++;
5825 pm->prefs = pp;
5826 pm->client = tc;
5827 pm->vl = vl;
5828 pm->bytes_msg = bytes_msg;
5829 memcpy (&pm[1], obmm, bytes_msg);
5831 "Sending message of type %u with %u bytes as <%" PRIu64
5832 "> to %s\n",
5833 ntohs (obmm->type),
5834 bytes_msg,
5835 pm->logging_uuid,
5836 GNUNET_i2s (&obm->peer));
5838 tc->details.core.pending_msg_head,
5839 tc->details.core.pending_msg_tail,
5840 pm);
5842 vl->pending_msg_head,
5843 vl->pending_msg_tail,
5844 pm);
5847}
5848
5849
5859static void
5861 void *cls,
5863{
5864 struct Neighbour *n;
5865 struct VirtualLink *vl;
5866 struct TransportClient *tc = cls;
5867 const struct GNUNET_MessageHeader *inbox =
5868 (const struct GNUNET_MessageHeader *) &cb[1];
5869 uint16_t isize = ntohs (inbox->size);
5870 const char *is = ((const char *) &cb[1]) + isize;
5871 size_t slen = strlen (is) + 1;
5872 char
5873 mbuf[slen + isize
5874 + sizeof(struct
5878
5879 /* 0-termination of 'is' was checked already in
5880 #check_communicator_backchannel() */
5882 "Preparing backchannel transmission to %s:%s of type %u and size %u\n",
5883 GNUNET_i2s (&cb->pid),
5884 is,
5885 ntohs (inbox->type),
5886 ntohs (inbox->size));
5887 /* encapsulate and encrypt message */
5888 be->header.type =
5890 be->header.size = htons (sizeof(mbuf));
5891 memcpy (&be[1], inbox, isize);
5892 memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
5893 + isize],
5894 is,
5895 strlen (is) + 1);
5896 // route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
5897 vl = lookup_virtual_link (&cb->pid);
5898 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
5899 {
5901 }
5902 else
5903 {
5904 /* Use route via neighbour */
5905 n = lookup_neighbour (&cb->pid);
5906 if (NULL != n)
5908 n,
5909 &be->header,
5910 RMO_NONE);
5911 }
5913}
5914
5915
5923static int
5924check_add_address (void *cls,
5925 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5926{
5927 struct TransportClient *tc = cls;
5928
5929 if (CT_COMMUNICATOR != tc->type)
5930 {
5931 GNUNET_break (0);
5932 return GNUNET_SYSERR;
5933 }
5935 return GNUNET_OK;
5936}
5937
5938
5944static void
5945store_pi (void *cls);
5946
5947
5952{
5953
5957 struct AddressListEntry *ale;
5958
5962 struct PilsRequest *req;
5963
5964
5968 struct GNUNET_TIME_Absolute et;
5969};
5970
5971
5972static void
5973shc_cont (void *cls, int success)
5974{
5975 struct PilsAddressSignContext *pc = cls;
5976
5977 GNUNET_assert (NULL == pc->req);
5978 if (GNUNET_OK != success)
5979 {
5981 "Failed to store our address `%s' with peerstore\n",
5982 pc->ale->address);
5983 if (NULL == pc->ale->st)
5984 {
5986 &store_pi,
5987 pc->ale);
5988 }
5989 }
5990 GNUNET_free (pc);
5991}
5992
5993
5997static void
5998pils_sign_hello_cb (void *cls,
5999 const struct GNUNET_PeerIdentity *pid,
6000 const struct GNUNET_CRYPTO_EddsaSignature *sig)
6001{
6002 struct PilsAddressSignContext *pc = cls;
6003 struct GNUNET_MQ_Envelope *env;
6004 const struct GNUNET_MessageHeader *msg;
6005
6006 pc->req->op = NULL;
6009 pc->req);
6010 GNUNET_free (pc->req);
6011 pc->req = NULL;
6014 pid,
6015 sig,
6016 pc->et);
6019 "store_pi 1\n");
6021 msg,
6022 shc_cont,
6023 pc);
6024 GNUNET_free (env);
6025}
6026
6027
6034static void
6035peerstore_store_own_cb (void *cls, int success)
6036{
6037 struct PilsAddressSignContext *pc = cls;
6038
6039 pc->ale->sc = NULL;
6040 if (GNUNET_YES != success)
6042 "Failed to store our own address `%s' in peerstore!\n",
6043 pc->ale->address);
6044 else
6046 "Successfully stored our own address `%s' in peerstore!\n",
6047 pc->ale->address);
6048 /* refresh period is 1/4 of expiration time, that should be plenty
6049 without being excessive. */
6050 if (NULL == pc->ale->st)
6051 {
6052 pc->ale->st =
6054 GNUNET_TIME_relative_divide (pc->ale->expiration,
6055 4ULL),
6056 &store_pi,
6057 pc->ale);
6058 }
6059
6060 /* Now we have to update our HELLO! */
6062 pc->req = GNUNET_new (struct PilsRequest);
6065 pc->req);
6066 pc->req->op = GNUNET_PILS_sign_hello (pils,
6068 pc->et,
6070 pc);
6071}
6072
6073
6074// This function
6075static void
6076pils_sign_addr_cb (void *cls,
6077 const struct GNUNET_PeerIdentity *pid,
6078 const struct GNUNET_CRYPTO_EddsaSignature *sig)
6079{
6080 struct PilsAddressSignContext *pc = cls;
6081 char *sig_str;
6082 void *result;
6083 size_t result_size;
6084
6085 pc->req->op = NULL;
6088 pc->req);
6089 GNUNET_free (pc->req);
6090 sig_str = NULL;
6091 (void) GNUNET_STRINGS_base64_encode (sig, sizeof(*sig), &sig_str);
6092 result_size =
6093 1 + GNUNET_asprintf (
6094 (char **) &result,
6095 "%s;%llu;%u;%s",
6096 sig_str,
6097 (unsigned long long) pc->et.abs_value_us,
6098 (unsigned int) pc->ale->nt,
6099 pc->ale->address);
6100 GNUNET_free (sig_str);
6101
6103 "Build our HELLO URI `%s'\n",
6104 (char*) result);
6105
6106 pc->ale->signed_address = result;
6107 pc->ale->signed_address_len = result_size;
6109
6110 expiration = GNUNET_TIME_relative_to_absolute (pc->ale->expiration);
6112 "transport",
6113 GST_my_identity, // FIXME
6115 result,
6116 result_size,
6117 expiration,
6120 pc);
6121}
6122
6123
6127struct SignedAddress
6128{
6133
6138
6142 struct GNUNET_HashCode addr_hash GNUNET_PACKED;
6143};
6144
6145
6159void
6161 struct AddressListEntry *ale,
6162 struct GNUNET_TIME_Absolute mono_time)
6163{
6164 struct SignedAddress sa;
6165 struct PilsAddressSignContext *pc;
6166
6167 sa.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS);
6168 sa.purpose.size = htonl (sizeof(sa));
6169 sa.mono_time = GNUNET_TIME_absolute_hton (mono_time);
6170 GNUNET_CRYPTO_hash (ale->address, strlen (ale->address), &sa.addr_hash);
6172 pc->ale = ale;
6173 pc->et = mono_time;
6174 pc->req = GNUNET_new (struct PilsRequest);
6176 &sa.purpose,
6178 pc);
6181 pc->req);
6182}
6183
6184
6190static void
6191store_pi (void *cls)
6192{
6193 struct AddressListEntry *ale = cls;
6194 const char *dash;
6195 char *address_uri;
6196 char *prefix;
6197 unsigned int add_success;
6198
6199 if (NULL == GST_my_identity)
6200 {
6202 &store_pi,
6203 ale);
6204 return;
6205 }
6207 dash = strchr (ale->address, '-');
6208 GNUNET_assert (NULL != dash);
6209 dash++;
6210 GNUNET_asprintf (&address_uri,
6211 "%s://%s",
6212 prefix,
6213 dash);
6215 ale->st = NULL;
6217 "Storing our address `%s' in peerstore until %s!\n",
6218 ale->address,
6221 address_uri);
6222 if (GNUNET_OK != add_success)
6223 {
6225 "Storing our address `%s' %s\n",
6226 address_uri,
6227 GNUNET_NO == add_success ? "not done" : "failed");
6228 GNUNET_free (address_uri);
6229 return;
6230 }
6231 else
6232 {
6233
6235 "Storing our address `%s'\n",
6236 address_uri);
6237 }
6238 // FIXME hello_mono_time used here?? What about expiration in ale?
6239 pils_sign_address (ale,
6241 // TODO keep track of op and potentially cancel/clean
6242 GNUNET_free (address_uri);
6243}
6244
6245
6246static struct AddressListEntry *
6250 const char *address,
6251 uint32_t aid,
6252 size_t slen)
6253{
6254 struct AddressListEntry *ale;
6255 char *address_without_port;
6256
6257 ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
6258 ale->tc = tc;
6259 ale->address = (const char *) &ale[1];
6260 ale->expiration = expiration;
6261 ale->aid = aid;
6262 ale->nt = nt;
6263 memcpy (&ale[1], address, slen);
6264 address_without_port = get_address_without_port (ale->address);
6266 "Is this %s a local address (%s)\n",
6267 address_without_port,
6268 ale->address);
6269 if (0 != strcmp ("127.0.0.1", address_without_port))
6270 {
6271 if (NULL != ale->st)
6272 {
6274 }
6275 ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
6276 }
6277 GNUNET_free (address_without_port);
6278
6279 return ale;
6280}
6281
6282
6283static void
6284feed_addresses_to_pils (void *cls)
6285{
6286
6288 "Feeding addresses to PILS\n");
6289 pils_feed_task = NULL;
6290
6292 GST_my_hello);
6293}
6294
6295
6302static void
6303handle_add_address (void *cls,
6304 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
6305{
6306 struct TransportClient *tc = cls;
6307 struct AddressListEntry *ale;
6308 size_t slen;
6309 char *address;
6310
6311 /* 0-termination of &aam[1] was checked in #check_add_address */
6313 "Communicator added address `%s'!\n",
6314 (const char *) &aam[1]);
6315 slen = ntohs (aam->header.size) - sizeof(*aam);
6316 address = GNUNET_malloc (slen);
6317 memcpy (address, &aam[1], slen);
6318 ale = create_address_entry (tc,
6320 ntohl (aam->nt),
6321 address,
6322 aam->aid,
6323 slen);
6324 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
6325 tc->details.communicator.addr_tail,
6326 ale);
6327 {
6328 for (struct AddressListEntry *iter = tc->details.communicator.addr_head;
6329 (NULL != iter && NULL != iter->next);
6330 iter = iter->next)
6331 {
6332 char *address_uri;
6333 char *dash = strchr (ale->address, '-');
6335 GNUNET_assert (NULL != dash);
6336 dash++;
6337 GNUNET_asprintf (&address_uri,
6338 "%s://%s",
6339 prefix,
6340 dash);
6343 GNUNET_free (address_uri);
6344 }
6345 if (NULL != pils_feed_task)
6349 NULL);
6350 }
6353}
6354
6355
6362static void
6363handle_del_address (void *cls,
6364 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
6365{
6366 struct TransportClient *tc = cls;
6367 struct AddressListEntry *alen;
6368
6369 if (CT_COMMUNICATOR != tc->type)
6370 {
6371 GNUNET_break (0);
6373 return;
6374 }
6375 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
6376 NULL != ale;
6377 ale = alen)
6378 {
6379 alen = ale->next;
6380 if (dam->aid != ale->aid)
6381 continue;
6382 GNUNET_assert (ale->tc == tc);
6384 "Communicator deleted address `%s'!\n",
6385 ale->address);
6387 ale->address);
6388 if (NULL != pils_feed_task)
6392 NULL);
6395 return;
6396 }
6398 "Communicator removed address we did not even have.\n");
6400 // GNUNET_SERVICE_client_drop (tc->client);
6401}
6402
6403
6411static void
6413
6414
6422static void
6423core_env_sent_cb (void *cls)
6424{
6425 struct CoreSentContext *ctx = cls;
6426 struct VirtualLink *vl = ctx->vl;
6427
6428 if (NULL == vl)
6429 {
6430 /* lost the link in the meantime, ignore */
6431 GNUNET_free (ctx);
6432 return;
6433 }
6436 vl->incoming_fc_window_size_ram -= ctx->size;
6437 vl->incoming_fc_window_size_used += ctx->isize;
6439 GNUNET_free (ctx);
6440}
6441
6442
6443static void
6445 const struct GNUNET_MessageHeader *mh,
6446 struct CommunicatorMessageContext *cmc,
6447 unsigned int free_cmc)
6448{
6449 uint16_t size = ntohs (mh->size);
6450 int have_core;
6451
6452 if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
6453 {
6455 "# CORE messages dropped (FC arithmetic overflow)",
6456 1,
6457 GNUNET_NO);
6459 "CORE messages of type %u with %u bytes dropped (FC arithmetic overflow)\n",
6460 (unsigned int) ntohs (mh->type),
6461 (unsigned int) ntohs (mh->size));
6462 if (GNUNET_YES == free_cmc)
6464 return;
6465 }
6467 {
6469 "# CORE messages dropped (FC window overflow)",
6470 1,
6471 GNUNET_NO);
6473 "CORE messages of type %u with %u bytes dropped (FC window overflow)\n",
6474 (unsigned int) ntohs (mh->type),
6475 (unsigned int) ntohs (mh->size));
6476 if (GNUNET_YES == free_cmc)
6478 return;
6479 }
6480
6481 /* Forward to all CORE clients */
6482 have_core = GNUNET_NO;
6483 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
6484 {
6485 struct GNUNET_MQ_Envelope *env;
6486 struct InboundMessage *im;
6487 struct CoreSentContext *ctx;
6488
6489 if (CT_CORE != tc->type)
6490 continue;
6493 ctx = GNUNET_new (struct CoreSentContext);
6494 ctx->vl = vl;
6495 ctx->size = size;
6496 ctx->isize = (GNUNET_NO == have_core) ? size : 0;
6497 have_core = GNUNET_YES;
6500 im->peer = cmc->im.sender;
6501 memcpy (&im[1], mh, size);
6502 GNUNET_MQ_send (tc->mq, env);
6504 }
6505 if (GNUNET_NO == have_core)
6506 {
6508 "Dropped message to CORE: no CORE client connected!\n");
6509 /* Nevertheless, count window as used, as it is from the
6510 perspective of the other peer! */
6512 /* TODO-M1 */
6514 "Dropped message of type %u with %u bytes to CORE: no CORE client connected!\n",
6515 (unsigned int) ntohs (mh->type),
6516 (unsigned int) ntohs (mh->size));
6517 if (GNUNET_YES == free_cmc)
6519 return;
6520 }
6522 "Delivered message from %s of type %u to CORE recv window %d\n",
6523 GNUNET_i2s (&cmc->im.sender),
6524 ntohs (mh->type),
6526 if (vl->core_recv_window > 0)
6527 {
6528 if (GNUNET_YES == free_cmc)
6530 return;
6531 }
6532 /* Wait with calling #finish_cmc_handling(cmc) until the message
6533 was processed by CORE MQs (for CORE flow control)! */
6534 if (GNUNET_YES == free_cmc)
6536}
6537
6538
6547static void
6548handle_raw_message (void *cls, const struct GNUNET_MessageHeader *mh)
6549{
6550 struct CommunicatorMessageContext *cmc = cls;
6551 // struct CommunicatorMessageContext *cmc_copy =
6552 // GNUNET_new (struct CommunicatorMessageContext);
6553 struct GNUNET_MessageHeader *mh_copy;
6554 struct RingBufferEntry *rbe;
6555 struct VirtualLink *vl;
6556 uint16_t size = ntohs (mh->size);
6557
6559 "Handling raw message of type %u with %u bytes\n",
6560 (unsigned int) ntohs (mh->type),
6561 (unsigned int) ntohs (mh->size));
6562
6563 if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
6564 (size < sizeof(struct GNUNET_MessageHeader)))
6565 {
6566 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6567
6568 GNUNET_break (0);
6569 finish_cmc_handling (cmc);
6571 return;
6572 }
6573 vl = lookup_virtual_link (&cmc->im.sender);
6574 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6575 {
6576 /* FIXME: sender is giving us messages for CORE but we don't have
6577 the link up yet! I *suspect* this can happen right now (i.e.
6578 sender has verified us, but we didn't verify sender), but if
6579 we pass this on, CORE would be confused (link down, messages
6580 arrive). We should investigate more if this happens often,
6581 or in a persistent manner, and possibly do "something" about
6582 it. Thus logging as error for now. */
6583
6584 mh_copy = GNUNET_malloc (size);
6585 rbe = GNUNET_new (struct RingBufferEntry);
6586 rbe->cmc = cmc;
6587 /*cmc_copy->tc = cmc->tc;
6588 cmc_copy->im = cmc->im;*/
6589 GNUNET_memcpy (mh_copy, mh, size);
6590
6591 rbe->mh = mh_copy;
6592
6594 {
6595 struct RingBufferEntry *rbe_old = ring_buffer[ring_buffer_head];
6596 GNUNET_free (rbe_old->cmc);
6597 GNUNET_free (rbe_old->mh);
6598 GNUNET_free (rbe_old);
6599 }
6600 ring_buffer[ring_buffer_head] = rbe;// cmc_copy;
6601 // cmc_copy->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6602 cmc->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6604 "Storing message for %s and type %u (%u) in ring buffer head %u is full %u\n",
6605 GNUNET_i2s (&cmc->im.sender),
6606 (unsigned int) ntohs (mh->type),
6607 (unsigned int) ntohs (mh_copy->type),
6611 {
6612 ring_buffer_head = 0;
6614 }
6615 else
6617
6619 "%u items stored in ring buffer\n",
6622
6623 /*GNUNET_break_op (0);
6624 GNUNET_STATISTICS_update (GST_stats,
6625 "# CORE messages dropped (virtual link still down)",
6626 1,
6627 GNUNET_NO);
6628
6629 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6630 "CORE messages of type %u with %u bytes dropped (virtual link still down)\n",
6631 (unsigned int) ntohs (mh->type),
6632 (unsigned int) ntohs (mh->size));
6633 finish_cmc_handling (cmc);*/
6636 // GNUNET_free (cmc);
6637 return;
6638 }
6640}
6641
6642
6650static int
6651check_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
6652{
6653 uint16_t size = ntohs (fb->header.size);
6654 uint16_t bsize = size - sizeof(*fb);
6655
6656 (void) cls;
6657 if (0 == bsize)
6658 {
6659 GNUNET_break_op (0);
6660 return GNUNET_SYSERR;
6661 }
6662 if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
6663 {
6664 GNUNET_break_op (0);
6665 return GNUNET_SYSERR;
6666 }
6667 if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
6668 {
6669 GNUNET_break_op (0);
6670 return GNUNET_SYSERR;
6671 }
6672 return GNUNET_YES;
6673}
6674
6675
6681static void
6682destroy_ack_cummulator (void *cls)
6683{
6684 struct AcknowledgementCummulator *ac = cls;
6685
6686 ac->task = NULL;
6687 GNUNET_assert (0 == ac->num_acks);
6689 GNUNET_YES ==
6691 GNUNET_free (ac);
6692}
6693
6694
6700static void
6702{
6703 struct Neighbour *n;
6704 struct VirtualLink *vl;
6705 struct AcknowledgementCummulator *ac = cls;
6706 char buf[sizeof(struct TransportReliabilityAckMessage)
6707 + ac->num_acks
6709 struct TransportReliabilityAckMessage *ack =
6710 (struct TransportReliabilityAckMessage *) buf;
6712
6713 ac->task = NULL;
6715 "Sending ACK with %u components to %s\n",
6716 ac->num_acks,
6717 GNUNET_i2s (&ac->target));
6718 GNUNET_assert (0 < ac->num_acks);
6720 ack->header.size =
6721 htons (sizeof(*ack)
6722 + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP));
6723 ack->ack_counter = htonl (ac->ack_counter += ac->num_acks);
6724 ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
6725 for (unsigned int i = 0; i < ac->num_acks; i++)
6726 {
6727 ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
6730 }
6731 /*route_control_message_without_fc (
6732 &ac->target,
6733 &ack->header,
6734 RMO_DV_ALLOWED);*/
6735 vl = lookup_virtual_link (&ac->target);
6736 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
6737 {
6739 vl,
6740 &ack->header,
6742 }
6743 else
6744 {
6745 /* Use route via neighbour */
6746 n = lookup_neighbour (&ac->target);
6747 if (NULL != n)
6749 n,
6750 &ack->header,
6751 RMO_NONE);
6752 }
6753 ac->num_acks = 0;
6756 ac);
6757}
6758
6759
6768static void
6770 const struct AcknowledgementUUIDP *ack_uuid,
6771 struct GNUNET_TIME_Absolute max_delay)
6772{
6773 struct AcknowledgementCummulator *ac;
6774
6776 "Scheduling ACK %s for transmission to %s\n",
6777 GNUNET_uuid2s (&ack_uuid->value),
6778 GNUNET_i2s (pid));
6780 if (NULL == ac)
6781 {
6783 ac->target = *pid;
6784 ac->min_transmission_time = max_delay;
6788 &ac->target,
6789 ac,
6791 }
6792 else
6793 {
6794 if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
6795 {
6796 /* must run immediately, ack buffer full! */
6798 }
6802 }
6805 ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
6806 ac->num_acks++;
6809 ac);
6810}
6811
6812
6817{
6822
6826 struct ReassemblyContext *rc;
6827};
6828
6829
6839static int
6840find_by_message_uuid (void *cls, uint32_t key, void *value)
6841{
6842 struct FindByMessageUuidContext *fc = cls;
6843 struct ReassemblyContext *rc = value;
6844
6845 (void) key;
6846 if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
6847 {
6848 fc->rc = rc;
6849 return GNUNET_NO;
6850 }
6851 return GNUNET_YES;
6852}
6853
6854
6862static void
6863handle_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
6864{
6865 struct CommunicatorMessageContext *cmc = cls;
6866 struct VirtualLink *vl;
6867 struct ReassemblyContext *rc;
6868 const struct GNUNET_MessageHeader *msg;
6869 uint16_t msize;
6870 uint16_t fsize;
6871 uint16_t frag_off;
6872 char *target;
6873 struct GNUNET_TIME_Relative cdelay;
6874 struct FindByMessageUuidContext fc;
6875
6876 vl = lookup_virtual_link (&cmc->im.sender);
6877 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6878 {
6879 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6880
6882 "No virtual link for %s to handle fragment\n",
6883 GNUNET_i2s (&cmc->im.sender));
6884 GNUNET_break (0);
6885 finish_cmc_handling (cmc);
6887 return;
6888 }
6889 if (NULL == vl->reassembly_map)
6890 {
6892 vl->reassembly_heap =
6897 vl);
6898 }
6899 msize = ntohs (fb->msg_size);
6900 fc.message_uuid = fb->msg_uuid;
6901 fc.rc = NULL;
6903 fb->msg_uuid.uuid,
6905 &fc);
6906 fsize = ntohs (fb->header.size) - sizeof(*fb);
6907 if (NULL == (rc = fc.rc))
6908 {
6909 rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */
6910 + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
6911 rc->msg_uuid = fb->msg_uuid;
6912 rc->virtual_link = vl;
6913 rc->msg_size = msize;
6914 rc->reassembly_timeout =
6918 rc,
6922 vl->reassembly_map,
6923 rc->msg_uuid.uuid,
6924 rc,
6926 target = (char *) &rc[1];
6927 rc->bitfield = (uint8_t *) (target + rc->msg_size);
6928 if (fsize != rc->msg_size)
6929 rc->msg_missing = rc->msg_size;
6930 else
6931 rc->msg_missing = 0;
6933 "Received fragment with size %u at offset %u/%u %u bytes missing from %s for NEW message %"
6934 PRIu64 "\n",
6935 fsize,
6936 ntohs (fb->frag_off),
6937 msize,
6938 rc->msg_missing,
6939 GNUNET_i2s (&cmc->im.sender),
6940 fb->msg_uuid.uuid);
6941 }
6942 else
6943 {
6944 target = (char *) &rc[1];
6946 "Received fragment at offset %u/%u from %s for message %u\n",
6947 ntohs (fb->frag_off),
6948 msize,
6949 GNUNET_i2s (&cmc->im.sender),
6950 (unsigned int) fb->msg_uuid.uuid);
6951 }
6952 if (msize != rc->msg_size)
6953 {
6954 GNUNET_break (0);
6955 finish_cmc_handling (cmc);
6956 return;
6957 }
6958
6959 /* reassemble */
6960 if (0 == fsize)
6961 {
6962 GNUNET_break (0);
6963 finish_cmc_handling (cmc);
6964 return;
6965 }
6966 frag_off = ntohs (fb->frag_off);
6967 if (frag_off + fsize > msize)
6968 {
6969 /* Fragment (plus fragment size) exceeds message size! */
6970 GNUNET_break_op (0);
6971 finish_cmc_handling (cmc);
6972 return;
6973 }
6974 memcpy (&target[frag_off], &fb[1], fsize);
6975 /* update bitfield and msg_missing */
6976 for (unsigned int i = frag_off; i < frag_off + fsize; i++)
6977 {
6978 if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
6979 {
6980 rc->bitfield[i / 8] |= (1 << (i % 8));
6981 rc->msg_missing--;
6982 }
6983 }
6984
6985 /* Compute cumulative ACK */
6987 cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
6988 if (0 == rc->msg_missing)
6989 cdelay = GNUNET_TIME_UNIT_ZERO;
6990 cummulative_ack (&cmc->im.sender,
6991 &fb->ack_uuid,
6994 /* is reassembly complete? */
6995 if (0 != rc->msg_missing)
6996 {
6997 finish_cmc_handling (cmc);
6998 return;
6999 }
7000 /* reassembly is complete, verify result */
7001 msg = (const struct GNUNET_MessageHeader *) &rc[1];
7002 if (ntohs (msg->size) != rc->msg_size)
7003 {
7004 GNUNET_break (0);
7006 finish_cmc_handling (cmc);
7007 return;
7008 }
7009 /* successful reassembly */
7011 "Fragment reassembly complete for message %u\n",
7012 (unsigned int) fb->msg_uuid.uuid);
7013 /* FIXME: check that the resulting msg is NOT a
7014 DV Box or Reliability Box, as that is NOT allowed! */
7015 cmc->mh = msg;
7017 /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
7018 en-route and we forget that we finished this reassembly immediately!
7019 -> keep around until timeout?
7020 -> shorten timeout based on ACK? */
7022}
7023
7024
7032static int
7033check_reliability_box (void *cls,
7034 const struct TransportReliabilityBoxMessage *rb)
7035{
7036 const struct GNUNET_MessageHeader *box = (const struct
7037 GNUNET_MessageHeader *) &rb[1];
7038 (void) cls;
7039
7041 "check_send_msg with size %u: inner msg type %u and size %u (%lu %lu)\n",
7042 ntohs (rb->header.size),
7043 ntohs (box->type),
7044 ntohs (box->size),
7045 sizeof (struct TransportReliabilityBoxMessage),
7046 sizeof (struct GNUNET_MessageHeader));
7048 return GNUNET_YES;
7049}
7050
7051
7059static void
7060handle_reliability_box (void *cls,
7061 const struct TransportReliabilityBoxMessage *rb)
7062{
7063 struct CommunicatorMessageContext *cmc = cls;
7064 const struct GNUNET_MessageHeader *inbox =
7065 (const struct GNUNET_MessageHeader *) &rb[1];
7066 struct GNUNET_TIME_Relative rtt;
7067
7069 "Received reliability box from %s with UUID %s of type %u\n",
7070 GNUNET_i2s (&cmc->im.sender),
7072 (unsigned int) ntohs (inbox->type));
7073 rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
7074 do not really have an RTT for the
7075 * incoming* queue (should we have
7076 the sender add it to the rb message?) */
7078 &cmc->im.sender,
7079 &rb->ack_uuid,
7080 (0 == ntohl (rb->ack_countdown))
7083 GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
7084 /* continue with inner message */
7085 /* FIXME: check that inbox is NOT a DV Box, fragment or another
7086 reliability box (not allowed!) */
7087 cmc->mh = inbox;
7089}
7090
7091
7100static void
7101update_pd_age (struct PerformanceData *pd, unsigned int age)
7102{
7103 unsigned int sage;
7104
7105 if (age == pd->last_age)
7106 return; /* nothing to do */
7107 sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
7108 for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
7109 {
7110 struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
7111
7112 the->bytes_sent = 0;
7113 the->bytes_received = 0;
7114 }
7115 pd->last_age = age;
7116}
7117
7118
7127static void
7129 struct GNUNET_TIME_Relative rtt,
7130 uint16_t bytes_transmitted_ok)
7131{
7132 uint64_t nval = rtt.rel_value_us;
7133 uint64_t oval = pd->aged_rtt.rel_value_us;
7134 unsigned int age = get_age ();
7135 struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
7136
7137 if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
7138 pd->aged_rtt = rtt;
7139 else
7140 pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
7141 update_pd_age (pd, age);
7142 the->bytes_received += bytes_transmitted_ok;
7143}
7144
7145
7153static void
7155 struct GNUNET_TIME_Relative rtt,
7156 uint16_t bytes_transmitted_ok)
7157{
7158 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
7159}
7160
7161
7169static void
7171 struct GNUNET_TIME_Relative rtt,
7172 uint16_t bytes_transmitted_ok)
7173{
7174 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
7175}
7176
7177
7185static void
7187{
7188 struct PendingMessage *pos;
7189
7191 "Complete transmission of message %" PRIu64 " %u\n",
7192 pm->logging_uuid,
7193 pm->pmt);
7194 switch (pm->pmt)
7195 {
7196 case PMT_CORE:
7198 /* Full message sent, we are done */
7200 return;
7201
7202 case PMT_FRAGMENT_BOX:
7203 /* Fragment sent over reliable channel */
7204 pos = pm->frag_parent;
7208 "pos frag_off %lu pos bytes_msg %lu pmt %u parent %u\n",
7209 (unsigned long) pos->frag_off,
7210 (unsigned long) pos->bytes_msg,
7211 pos->pmt,
7212 NULL == pos->frag_parent ? 1 : 0);
7213 /* check if subtree is done */
7214 while ((NULL == pos->head_frag) && (pos->frag_off == (pos->bytes_msg
7215 - sizeof(struct
7217 &&
7218 (NULL != pos->frag_parent))
7219 {
7220 pm = pos;
7221 pos = pm->frag_parent;
7222 if ((NULL == pos) && (PMT_DV_BOX == pm->pmt))
7223 {
7225 return;
7226 }
7227 else if (PMT_DV_BOX == pm->pmt)
7228 {
7230 return;
7231 }
7234 }
7235
7236 /* Was this the last applicable fragment? */
7237 if ((NULL == pos->head_frag) && (NULL == pos->frag_parent || PMT_DV_BOX ==
7238 pos->pmt) &&
7239 (pos->frag_off == pos->bytes_msg))
7241 return;
7242
7243 case PMT_DV_BOX:
7245 "Completed transmission of message %" PRIu64 " (DV Box)\n",
7246 pm->logging_uuid);
7247 if (NULL != pm->frag_parent)
7248 {
7249 pos = pm->frag_parent;
7251 pos->bpm = NULL;
7253 }
7254 else
7256 return;
7257 }
7258}
7259
7260
7268static void
7270 struct GNUNET_TIME_Relative ack_delay)
7271{
7272 struct GNUNET_TIME_Relative delay;
7273
7275 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
7276 if (NULL != pa->queue && 1 == pa->num_send)
7278 if (NULL != pa->dvh && 1 == pa->num_send)
7279 update_dvh_performance (pa->dvh, delay, pa->message_size);
7280 if (NULL != pa->pm)
7283}
7284
7285
7293static int
7294check_reliability_ack (void *cls,
7295 const struct TransportReliabilityAckMessage *ra)
7296{
7297 unsigned int n_acks;
7298
7299 (void) cls;
7300 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7301 / sizeof(struct TransportCummulativeAckPayloadP);
7302 if (0 == n_acks)
7303 {
7304 GNUNET_break_op (0);
7305 return GNUNET_SYSERR;
7306 }
7307 if ((ntohs (ra->header.size) - sizeof(*ra)) !=
7308 n_acks * sizeof(struct TransportCummulativeAckPayloadP))
7309 {
7310 GNUNET_break_op (0);
7311 return GNUNET_SYSERR;
7312 }
7313 return GNUNET_OK;
7314}
7315
7316
7324static void
7325handle_reliability_ack (void *cls,
7326 const struct TransportReliabilityAckMessage *ra)
7327{
7328 struct CommunicatorMessageContext *cmc = cls;
7329 const struct TransportCummulativeAckPayloadP *ack;
7330 unsigned int n_acks;
7331 uint32_t ack_counter;
7332
7333 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7334 / sizeof(struct TransportCummulativeAckPayloadP);
7335 ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
7336 for (unsigned int i = 0; i < n_acks; i++)
7337 {
7338 struct PendingAcknowledgement *pa =
7340 if (NULL == pa)
7341 {
7343 "Received ACK from %s with UUID %s which is unknown to us!\n",
7344 GNUNET_i2s (&cmc->im.sender),
7345 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7347 GST_stats,
7348 "# FRAGMENT_ACKS dropped, no matching pending message",
7349 1,
7350 GNUNET_NO);
7351 continue;
7352 }
7354 "Received ACK from %s with UUID %s\n",
7355 GNUNET_i2s (&cmc->im.sender),
7356 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7357 handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
7358 }
7359
7360 ack_counter = htonl (ra->ack_counter);
7361 (void) ack_counter; /* silence compiler warning for now */
7362 // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
7363 // (DV and/or Neighbour?)
7364 finish_cmc_handling (cmc);
7365}
7366
7367
7375static int
7377 void *cls,
7379{
7380 uint16_t size = ntohs (be->header.size) - sizeof(*be);
7381 const struct GNUNET_MessageHeader *inbox =
7382 (const struct GNUNET_MessageHeader *) &be[1];
7383 const char *is;
7384 uint16_t isize;
7385
7386 (void) cls;
7387 if (ntohs (inbox->size) >= size)
7388 {
7389 GNUNET_break_op (0);
7390 return GNUNET_SYSERR;
7391 }
7392 isize = ntohs (inbox->size);
7393 is = ((const char *) inbox) + isize;
7394 size -= isize;
7395 if ('\0' != is[size - 1])
7396 {
7397 GNUNET_break_op (0);
7398 return GNUNET_SYSERR;
7399 }
7400 return GNUNET_YES;
7401}
7402
7403
7412static void
7414 void *cls,
7416{
7417 struct CommunicatorMessageContext *cmc = cls;
7419 struct GNUNET_MQ_Envelope *env;
7420 struct TransportClient *tc;
7421 const struct GNUNET_MessageHeader *inbox =
7422 (const struct GNUNET_MessageHeader *) &be[1];
7423 uint16_t isize = ntohs (inbox->size);
7424 const char *target_communicator = ((const char *) inbox) + isize;
7425 char *sender;
7426 char *self;
7427
7428 GNUNET_asprintf (&sender,
7429 "%s",
7430 GNUNET_i2s (&cmc->im.sender));
7431 GNUNET_asprintf (&self,
7432 "%s",
7434
7435 /* Find client providing this communicator */
7436 for (tc = clients_head; NULL != tc; tc = tc->next)
7437 if ((CT_COMMUNICATOR == tc->type) &&
7438 (0 ==
7439 strcmp (tc->details.communicator.address_prefix, target_communicator)))
7440 break;
7441 if (NULL == tc)
7442 {
7443 char *stastr;
7444
7446 &stastr,
7447 "# Backchannel message dropped: target communicator `%s' unknown",
7448 target_communicator);
7450 GNUNET_free (stastr);
7451 finish_cmc_handling (cmc);
7452 return;
7453 }
7454 /* Finally, deliver backchannel message to communicator */
7456 "Delivering backchannel message from %s to %s of type %u to %s\n",
7457 sender,
7458 self,
7459 ntohs (inbox->type),
7460 target_communicator);
7462 cbi,
7463 isize,
7465 cbi->pid = cmc->im.sender;
7466 memcpy (&cbi[1], inbox, isize);
7467 GNUNET_MQ_send (tc->mq, env);
7468 finish_cmc_handling (cmc);
7469}
7470
7471
7481static void
7482path_cleanup_cb (void *cls)
7483{
7484 struct DistanceVector *dv = cls;
7485 struct DistanceVectorHop *pos;
7486
7487 dv->timeout_task = NULL;
7488 while (NULL != (pos = dv->dv_head))
7489 {
7490 GNUNET_assert (dv == pos->dv);
7492 break;
7494 }
7495 if (NULL == pos)
7496 {
7497 free_dv_route (dv);
7498 return;
7499 }
7500 dv->timeout_task =
7502}
7503
7504
7505static void
7507{
7508
7509 const struct GNUNET_PeerIdentity target = vl->target;
7510
7511
7513 {
7514 struct RingBufferEntry *ring_buffer_copy[RING_BUFFER_SIZE];
7515 unsigned int tail = GNUNET_YES == is_ring_buffer_full ? ring_buffer_head :
7516 0;
7517 unsigned int head = GNUNET_YES == is_ring_buffer_full ? RING_BUFFER_SIZE :
7520 struct CommunicatorMessageContext *cmc;
7521 struct RingBufferEntry *rbe;
7522 struct GNUNET_MessageHeader *mh;
7523
7525 "Sending from ring buffer, which has %u items\n",
7526 head);
7527
7528 ring_buffer_head = 0;
7529 for (unsigned int i = 0; i < head; i++)
7530 {
7531 rbe = ring_buffer[(i + tail) % RING_BUFFER_SIZE];
7532 cmc = rbe->cmc;
7533 mh = rbe->mh;
7534
7535 im = cmc->im;
7536 // mh = cmc->mh;
7538 "Sending message of type %u to ring buffer target %s using vl target %s index %u\n",
7539 mh->type,
7540 GNUNET_i2s (&im.sender),
7541 GNUNET_i2s2 (&target),
7542 (i + tail) % RING_BUFFER_SIZE);
7543 if (0 == GNUNET_memcmp (&target, &im.sender))
7544 {
7546 "Finish handling message of type %u and size %u\n",
7547 (unsigned int) ntohs (mh->type),
7548 (unsigned int) ntohs (mh->size));
7550 GNUNET_free (mh);
7551 GNUNET_free (rbe->cmc);
7552 GNUNET_free (rbe);
7553 }
7554 else
7555 {
7556 ring_buffer_copy[ring_buffer_head] = rbe;
7558 }
7559 }
7560
7563 {
7565 }
7566
7567 for (unsigned int i = 0; i < ring_buffer_head; i++)
7568 {
7569 ring_buffer[i] = ring_buffer_copy[i];
7571 "ring_buffer_copy[i]->mh->type for i %u %u\n",
7572 i,
7573 ring_buffer_copy[i]->mh->type);
7575 "ring_buffer[i]->mh->type for i %u %u\n",
7576 i,
7577 ring_buffer[i]->mh->type);
7578 }
7579
7581 "%u items still in ring buffer\n",
7583 }
7584
7586 {
7587 struct PendingMessage *ring_buffer_dv_copy[RING_BUFFER_SIZE];
7588 struct PendingMessage *pm;
7589 unsigned int tail = GNUNET_YES == is_ring_buffer_dv_full ?
7591 0;
7592 unsigned int head = GNUNET_YES == is_ring_buffer_dv_full ?
7595
7597 "Sending from ring buffer dv, which has %u items\n",
7598 head);
7599
7601 for (unsigned int i = 0; i < head; i++)
7602 {
7603 pm = ring_buffer_dv[(i + tail) % RING_BUFFER_SIZE];
7604
7606 "Sending to ring buffer target %s using vl target %s\n",
7607 GNUNET_i2s (&pm->target),
7608 GNUNET_i2s2 (&target));
7609 if (0 == GNUNET_memcmp (&target, &pm->target))
7610 {
7612 "Adding PendingMessage to vl, checking transmission.\n");
7613 pm->vl = vl;
7617 pm);
7618
7620 }
7621 else
7622 {
7623 ring_buffer_dv_copy[ring_buffer_dv_head] = pm;
7625 }
7626 }
7627
7629 {
7631 }
7632
7633 for (unsigned int i = 0; i < ring_buffer_dv_head; i++)
7634 ring_buffer_dv[i] = ring_buffer_dv_copy[i];
7635
7637 "%u items still in ring buffer dv.\n",
7639
7640 }
7641}
7642
7643
7651static void
7653{
7654 struct DistanceVector *dv = hop->dv;
7655 struct VirtualLink *vl;
7656
7657 vl = lookup_virtual_link (&dv->target);
7658 if (NULL == vl)
7659 {
7660
7661 vl = GNUNET_new (struct VirtualLink);
7663 "Creating new virtual link %p to %s using DV!\n",
7664 vl,
7665 GNUNET_i2s (&dv->target));
7666 vl->burst_addr = NULL;
7667 vl->confirmed = GNUNET_YES;
7668 vl->message_uuid_ctr =
7670 vl->target = dv->target;
7676 links,
7677 &vl->target,
7678 vl,
7680 vl->dv = dv;
7681 dv->vl = vl;
7682 vl->visibility_task =
7685 /* We lacked a confirmed connection to the target
7686 before, so tell CORE about it (finally!) */
7689 }
7690 else
7691 {
7692 /* Link was already up, remember dv is also now available and we are done */
7693 vl->dv = dv;
7694 dv->vl = vl;
7695 if (GNUNET_NO == vl->confirmed)
7696 {
7697 vl->confirmed = GNUNET_YES;
7698 vl->visibility_task =
7701 /* We lacked a confirmed connection to the target
7702 before, so tell CORE about it (finally!) */
7705 }
7706 else
7708 "Virtual link to %s could now also use DV!\n",
7709 GNUNET_i2s (&dv->target));
7710 }
7711}
7712
7713
7739static int
7740learn_dv_path (const struct GNUNET_PeerIdentity *path,
7741 unsigned int path_len,
7742 struct GNUNET_TIME_Relative network_latency,
7743 struct GNUNET_TIME_Absolute path_valid_until)
7744{
7745 struct DistanceVectorHop *hop;
7746 struct DistanceVector *dv;
7747 struct Neighbour *next_hop;
7748 unsigned int shorter_distance;
7749
7750 if (path_len < 3)
7751 {
7752 /* what a boring path! not allowed! */
7753 GNUNET_break (0);
7754 return GNUNET_SYSERR;
7755 }
7756 GNUNET_assert (0 == GNUNET_memcmp (GST_my_identity, &path[0]));
7757 next_hop = lookup_neighbour (&path[1]);
7758 if (NULL == next_hop)
7759 {
7760 /* next hop must be a neighbour, otherwise this whole thing is useless! */
7761 GNUNET_break (0);
7762 return GNUNET_SYSERR;
7763 }
7764 for (unsigned int i = 2; i < path_len; i++)
7765 {
7766 struct Neighbour *n = lookup_neighbour (&path[i]);
7767 struct GNUNET_TIME_Absolute q_timeout;
7768
7769 if (NULL != n)
7770 {
7771 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
7772 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
7773 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
7775 "remaining %lu to %s\n",
7776 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout)
7777 .rel_value_us,
7778 GNUNET_i2s (&n->pid));
7779 if (0 != GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
7780 {
7781 /* Useless path: we have a direct active connection to some hop
7782 in the middle of the path, so this one is not even
7783 terribly useful for redundancy */
7785 "Path of %u hops useless: directly link to hop %u (%s)\n",
7786 path_len,
7787 i,
7788 GNUNET_i2s (&path[i]));
7790 "# Useless DV path ignored: hop is neighbour",
7791 1,
7792 GNUNET_NO);
7793 return GNUNET_SYSERR;
7794 }
7795 }
7796 }
7797 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
7798 if (NULL == dv)
7799 {
7800 dv = GNUNET_new (struct DistanceVector);
7801 dv->target = path[path_len - 1];
7804 dv);
7807 dv_routes,
7808 &dv->target,
7809 dv,
7811 }
7812 /* Check if we have this path already! */
7813 shorter_distance = 0;
7814 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
7815 pos = pos->next_dv)
7816 {
7817 if (pos->distance < path_len - 3)
7818 shorter_distance++;
7819 /* Note that the distances in 'pos' excludes us (path[0]),
7820 the next_hop (path[1]) and the target so we need to subtract three
7821 and check next_hop explicitly */
7822 if ((pos->distance == path_len - 3) && (pos->next_hop == next_hop))
7823 {
7824 int match = GNUNET_YES;
7825
7826 for (unsigned int i = 0; i < pos->distance; i++)
7827 {
7828 if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
7829 {
7830 match = GNUNET_NO;
7831 break;
7832 }
7833 }
7834 if (GNUNET_YES == match)
7835 {
7836 struct GNUNET_TIME_Relative last_timeout;
7837
7838 /* Re-discovered known path, update timeout */
7840 "# Known DV path refreshed",
7841 1,
7842 GNUNET_NO);
7843 last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
7844 pos->timeout =
7846 pos->path_valid_until =
7847 GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
7848 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
7849 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
7850 if (0 <
7853 if (last_timeout.rel_value_us <
7856 .rel_value_us)
7857 {
7858 /* Some peer send DV learn messages too often, we are learning
7859 the same path faster than it would be useful; do not forward! */
7861 "Rediscovered path too quickly, not forwarding further\n")
7862 ;
7863 return GNUNET_NO;
7864 }
7866 "Refreshed known path to %s valid until %s, forwarding further\n",
7867 GNUNET_i2s (&dv->target),
7869 pos->path_valid_until));
7870 return GNUNET_YES;
7871 }
7872 }
7873 }
7874 /* Count how many shorter paths we have (incl. direct
7875 neighbours) before simply giving up on this one! */
7876 if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
7877 {
7878 /* We have a shorter path already! */
7880 "Have many shorter DV paths %s, not forwarding further\n",
7881 GNUNET_i2s (&dv->target));
7882 return GNUNET_NO;
7883 }
7884 /* create new DV path entry */
7886 "Discovered new DV path to %s valid until %s\n",
7887 GNUNET_i2s (&dv->target),
7888 GNUNET_STRINGS_absolute_time_to_string (path_valid_until));
7889 hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
7890 + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7891 hop->next_hop = next_hop;
7892 hop->dv = dv;
7893 hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
7894 memcpy (&hop[1],
7895 &path[2],
7896 sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7898 hop->path_valid_until = path_valid_until;
7899 hop->distance = path_len - 3;
7900 hop->pd.aged_rtt = network_latency;
7901 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
7903 next_hop->dv_head,
7904 next_hop->dv_tail,
7905 hop);
7906 if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
7908 return GNUNET_YES;
7909}
7910
7911
7919static int
7920check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
7921{
7922 uint16_t size = ntohs (dvl->header.size);
7923 uint16_t num_hops = ntohs (dvl->num_hops);
7924 const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
7925
7926 (void) cls;
7927 if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
7928 {
7929 GNUNET_break_op (0);
7930 return GNUNET_SYSERR;
7931 }
7932 if (num_hops > MAX_DV_HOPS_ALLOWED)
7933 {
7934 GNUNET_break_op (0);
7935 return GNUNET_SYSERR;
7936 }
7937 for (unsigned int i = 0; i < num_hops; i++)
7938 {
7939 if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
7940 {
7941 GNUNET_break_op (0);
7942 return GNUNET_SYSERR;
7943 }
7944 if (0 == GNUNET_memcmp (GST_my_identity, &hops[i].hop))
7945 {
7946 GNUNET_break_op (0);
7947 return GNUNET_SYSERR;
7948 }
7949 }
7950 return GNUNET_YES;
7951}
7952
7953
7954struct SignDhpCls
7955{
7956 struct DVPathEntryP *dhops;
7957 uint16_t nhops;
7958 const struct GNUNET_PeerIdentity *next_hop;
7960 struct PilsRequest *pr;
7961};
7962
7963
7964static void
7965sign_dhp_cp (void *cls,
7966 const struct GNUNET_PeerIdentity *pid,
7967 const struct GNUNET_CRYPTO_EddsaSignature *sig)
7968{
7969 struct SignDhpCls *sign_dhp_cls = cls;
7970 struct VirtualLink *vl;
7971 struct DVPathEntryP *dhops = sign_dhp_cls->dhops;
7972 uint16_t nhops = sign_dhp_cls->nhops;
7973 const struct GNUNET_PeerIdentity *next_hop = sign_dhp_cls->next_hop;
7974 struct TransportDVLearnMessage *fwd = sign_dhp_cls->fwd;
7975 struct Neighbour *n;
7976
7977 sign_dhp_cls->pr->op = NULL;
7980 sign_dhp_cls->pr);
7981 GNUNET_free (sign_dhp_cls->pr);
7982 dhops[nhops].hop_sig = *sig;
7983
7984 /*route_control_message_without_fc (next_hop,
7985 &fwd->header,
7986 RMO_UNCONFIRMED_ALLOWED);*/
7987 vl = lookup_virtual_link (next_hop);
7988 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
7989 {
7991 &fwd->header,
7993 }
7994 else
7995 {
7996 /* Use route via neighbour */
7997 n = lookup_neighbour (next_hop);
7998 if (NULL != n)
8000 n,
8001 &fwd->header,
8003 }
8004 GNUNET_free (sign_dhp_cls);
8005}
8006
8007
8019static void
8020forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop,
8021 const struct TransportDVLearnMessage *msg,
8022 uint16_t bi_history,
8023 uint16_t nhops,
8024 const struct DVPathEntryP *hops,
8025 struct GNUNET_TIME_Absolute in_time)
8026{
8027 struct DVPathEntryP *dhops;
8028 char buf[sizeof(struct TransportDVLearnMessage)
8029 + (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
8030 struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
8031 struct GNUNET_TIME_Relative nnd;
8032
8033 /* compute message for forwarding */
8035 "Forwarding DV learn message originating from %s to %s\n",
8036 GNUNET_i2s (&msg->initiator),
8037 GNUNET_i2s2 (next_hop));
8040 fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
8041 + (nhops + 1) * sizeof(struct DVPathEntryP));
8042 fwd->num_hops = htons (nhops + 1);
8043 fwd->bidirectional = htons (bi_history);
8046 msg->non_network_delay));
8048 fwd->init_sig = msg->init_sig;
8049 fwd->initiator = msg->initiator;
8050 fwd->challenge = msg->challenge;
8051 fwd->monotonic_time = msg->monotonic_time;
8052 dhops = (struct DVPathEntryP *) &fwd[1];
8053 GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
8054 dhops[nhops].hop = *GST_my_identity;
8055 {
8056 struct DvHopPS dhp = {
8058 .purpose.size = htonl (sizeof(dhp)),
8059 .pred = (0 == nhops) ? msg->initiator : dhops[nhops - 1].hop,
8060 .succ = *next_hop,
8062 };
8063 struct SignDhpCls *sign_dhp_cls = GNUNET_new (struct SignDhpCls);
8064 sign_dhp_cls->dhops = dhops;
8065 sign_dhp_cls->nhops = nhops;
8066 sign_dhp_cls->next_hop = next_hop;
8067 sign_dhp_cls->fwd = fwd;
8068 sign_dhp_cls->pr = GNUNET_new (struct PilsRequest);
8071 sign_dhp_cls->pr);
8072 sign_dhp_cls->pr->op =
8074 &dhp.purpose,
8076 sign_dhp_cls);
8077 }
8078}
8079
8080
8090static int
8092 struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
8093 const struct GNUNET_PeerIdentity *init,
8094 const struct GNUNET_CRYPTO_ChallengeNonceP *challenge,
8095 const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
8096{
8097 struct DvInitPS ip = { .purpose.purpose = htonl (
8099 .purpose.size = htonl (sizeof(ip)),
8100 .monotonic_time = sender_monotonic_time,
8101 .challenge = *challenge };
8102
8103 if (
8104 GNUNET_OK !=
8106 &ip,
8107 init_sig,
8108 &init->public_key))
8109 {
8110 GNUNET_break_op (0);
8111 return GNUNET_SYSERR;
8112 }
8113 return GNUNET_OK;
8114}
8115
8116
8121{
8125 const struct TransportDVLearnMessage *dvl;
8126
8130 const struct DVPathEntryP *hops;
8131
8136
8141
8145 unsigned int num_eligible;
8146
8150 unsigned int num_selections;
8151
8155 uint16_t nhops;
8156
8160 uint16_t bi_history;
8161};
8162
8163
8172static int
8173dv_neighbour_selection (void *cls,
8174 const struct GNUNET_PeerIdentity *pid,
8175 void *value)
8176{
8177 struct NeighbourSelectionContext *nsc = cls;
8178
8179 (void) value;
8180 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8181 return GNUNET_YES; /* skip initiator */
8182 for (unsigned int i = 0; i < nsc->nhops; i++)
8183 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8184 return GNUNET_YES;
8185 /* skip peers on path */
8186 nsc->num_eligible++;
8187 return GNUNET_YES;
8188}
8189
8190
8201static int
8202dv_neighbour_transmission (void *cls,
8203 const struct GNUNET_PeerIdentity *pid,
8204 void *value)
8205{
8206 struct NeighbourSelectionContext *nsc = cls;
8207
8209 "transmission %s\n",
8210 GNUNET_i2s (pid));
8211 (void) value;
8212 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8213 return GNUNET_YES; /* skip initiator */
8214 for (unsigned int i = 0; i < nsc->nhops; i++)
8215 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8216 return GNUNET_YES;
8217 /* skip peers on path */
8218 for (unsigned int i = 0; i < nsc->num_selections; i++)
8219 {
8220 if (nsc->selections[i] == nsc->num_eligible)
8221 {
8223 nsc->dvl,
8224 nsc->bi_history,
8225 nsc->nhops,
8226 nsc->hops,
8227 nsc->in_time);
8228 break;
8229 }
8230 }
8231 nsc->num_eligible++;
8232 return GNUNET_YES;
8233}
8234
8235
8279static unsigned int
8280calculate_fork_degree (unsigned int hops_taken,
8281 unsigned int neighbour_count,
8282 unsigned int eligible_count)
8283{
8284 double target_total = 50.0; /* FIXME: use LOG(NSE)? */
8285 double eligible_ratio =
8286 ((double) eligible_count) / ((double) neighbour_count);
8287 double boost_factor = eligible_ratio * eligible_ratio;
8288 unsigned int rnd;
8289 double left;
8290
8291 if (hops_taken >= 64)
8292 {
8293 GNUNET_break (0);
8294 return 0; /* precaution given bitshift below */
8295 }
8296 for (unsigned int i = 1; i < hops_taken; i++)
8297 {
8298 /* For each hop, subtract the expected number of targets
8299 reached at distance d (so what remains divided by 2^d) */
8300 target_total -= (target_total * boost_factor / (1LLU << i));
8301 }
8302 rnd =
8303 (unsigned int) floor (target_total * boost_factor / (1LLU << hops_taken));
8304 /* round up or down probabilistically depending on how close we were
8305 when floor()ing to rnd */
8306 left = target_total - (double) rnd;
8307 if (UINT32_MAX * left >
8309 rnd++; /* round up */
8311 "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
8312 hops_taken,
8313 rnd,
8314 eligible_count,
8315 neighbour_count);
8316 return rnd;
8317}
8318
8319
8326static void
8327neighbour_store_dvmono_cb (void *cls, int success)
8328{
8329 struct Neighbour *n = cls;
8330
8331 n->sc = NULL;
8332 if (GNUNET_YES != success)
8334 "Failed to store other peer's monotonic time in peerstore!\n");
8335}
8336
8337
8338static struct GNUNET_TIME_Relative
8340{
8341 struct GNUNET_TIME_Relative host_latency_sum;
8342 struct GNUNET_TIME_Relative latency;
8343 struct GNUNET_TIME_Relative network_latency;
8344 uint16_t nhops = ntohs (dvl->num_hops);;
8345
8346 /* We initiated this, learn the forward path! */
8347 host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
8348
8349 // Need also something to lookup initiation time
8350 // to compute RTT! -> add RTT argument here?
8352 dvl->monotonic_time));
8353 GNUNET_assert (latency.rel_value_us >= host_latency_sum.rel_value_us);
8354 // latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
8355 // (based on dvl->challenge, we can identify time of origin!)
8356
8357 network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
8358 /* assumption: latency on all links is the same */
8359 network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
8360
8361 return network_latency;
8362}
8363
8364
8372static void
8373handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
8374{
8375 struct CommunicatorMessageContext *cmc = cls;
8377 int bi_hop;
8378 uint16_t nhops;
8379 uint16_t bi_history;
8380 const struct DVPathEntryP *hops;
8381 int do_fwd;
8382 int did_initiator;
8383 struct GNUNET_TIME_Absolute in_time;
8384 struct Neighbour *n;
8385
8386 nhops = ntohs (dvl->num_hops); /* 0 = sender is initiator */
8387 bi_history = ntohs (dvl->bidirectional);
8388 hops = (const struct DVPathEntryP *) &dvl[1];
8389 if (0 == nhops)
8390 {
8391 /* sanity check */
8392 if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
8393 {
8394 GNUNET_break (0);
8395 finish_cmc_handling (cmc);
8396 return;
8397 }
8398 }
8399 else
8400 {
8402 "handle dv learn message last hop %s\n",
8403 GNUNET_i2s (&hops[nhops - 1].hop));
8404 /* sanity check */
8405 if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
8406 {
8407 GNUNET_break (0);
8408 finish_cmc_handling (cmc);
8409 return;
8410 }
8411 }
8412
8414 cc = cmc->tc->details.communicator.cc;
8415 bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
8416 cc); // FIXME: add bi-directional flag to cc?
8417 in_time = GNUNET_TIME_absolute_get ();
8418
8419 /* continue communicator here, everything else can happen asynchronous! */
8420 finish_cmc_handling (cmc);
8421
8422 n = lookup_neighbour (&dvl->initiator);
8423 if (NULL != n)
8424 {
8425 if ((n->dv_monotime_available == GNUNET_YES) &&
8428 {
8430 "DV learn from %s discarded due to time travel",
8431 GNUNET_i2s (&dvl->initiator));
8433 "# DV learn discarded due to time travel",
8434 1,
8435 GNUNET_NO);
8436 return;
8437 }
8439 &dvl->initiator,
8440 &dvl->challenge,
8441 &dvl->init_sig))
8442 {
8444 "DV learn signature from %s invalid\n",
8445 GNUNET_i2s (&dvl->initiator));
8446 GNUNET_break_op (0);
8447 return;
8448 }
8451 {
8452 if (NULL != n->sc)
8453 {
8455 "store cancel\n");
8457 }
8458 n->sc =
8460 "transport",
8461 &dvl->initiator,
8463 &dvl->monotonic_time,
8464 sizeof(dvl->monotonic_time),
8468 n);
8469 }
8470 }
8471 /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
8472 If signature verification load too high, implement random drop strategy */
8473 for (unsigned int i = 0; i < nhops; i++)
8474 {
8475 struct DvHopPS dhp = { .purpose.purpose =
8477 .purpose.size = htonl (sizeof(dhp)),
8478 .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
8479 .succ = (nhops == i + 1) ? *GST_my_identity
8480 : hops[i + 1].hop,
8481 .challenge = dvl->challenge };
8482
8483 if (GNUNET_OK !=
8485 &dhp,
8486 &hops[i].hop_sig,
8487 &hops[i].hop.public_key))
8488 {
8490 "DV learn from %s signature of hop %u invalid\n",
8491 GNUNET_i2s (&dvl->initiator),
8492 i);
8494 "signature of hop %s invalid\n",
8495 GNUNET_i2s (&hops[i].hop));
8497 "pred %s\n",
8498 GNUNET_i2s (&dhp.pred));
8500 "succ %s\n",
8501 GNUNET_i2s (&dhp.succ));
8503 "hash %s\n",
8504 GNUNET_sh2s (&dhp.challenge.value));
8505 GNUNET_break_op (0);
8506 return;
8507 }
8508 }
8509 if (GNUNET_EXTRA_LOGGING > 0)
8510 {
8511 char *path;
8512
8513 path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
8514 for (unsigned int i = 0; i < nhops; i++)
8515 {
8516 char *tmp;
8517
8518 GNUNET_asprintf (&tmp,
8519 "%s%s%s",
8520 path,
8521 (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
8522 GNUNET_i2s (&hops[i].hop));
8523 GNUNET_free (path);
8524 path = tmp;
8525 }
8527 "Received DVInit via %s%s%s\n",
8528 path,
8529 bi_hop ? "<->" : "-->",
8531 GNUNET_free (path);
8532 }
8533 do_fwd = GNUNET_YES;
8534 if (0 == GNUNET_memcmp (GST_my_identity, &dvl->initiator))
8535 {
8536 struct GNUNET_PeerIdentity path[nhops + 1];
8537 struct GNUNET_TIME_Relative network_latency;
8538
8539 /* We initiated this, learn the forward path! */
8540 path[0] = *GST_my_identity;
8541 path[1] = hops[0].hop;
8542
8543 network_latency = get_network_latency (dvl);
8544
8545 for (unsigned int i = 2; i <= nhops; i++)
8546 {
8547 struct GNUNET_TIME_Relative ilat;
8548
8549 /* assumption: linear latency increase per hop */
8550 ilat = GNUNET_TIME_relative_multiply (network_latency, i);
8551 path[i] = hops[i - 1].hop;
8553 "Learned path with %u hops to %s with latency %s\n",
8554 i,
8555 GNUNET_i2s (&path[i]),
8557 learn_dv_path (path,
8558 i + 1,
8559 ilat,
8562 }
8563 /* as we initiated, do not forward again (would be circular!) */
8564 do_fwd = GNUNET_NO;
8565 return;
8566 }
8567 if (bi_hop)
8568 {
8569 /* last hop was bi-directional, we could learn something here! */
8570 struct GNUNET_PeerIdentity path[nhops + 2];
8571 struct GNUNET_TIME_Relative ilat;
8572 struct GNUNET_TIME_Relative network_latency;
8573
8574 path[0] = *GST_my_identity;
8575 path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
8576 for (unsigned int i = 0; i < nhops; i++)
8577 {
8578 int iret;
8579
8580 if (0 == (bi_history & (1 << i)))
8581 break; /* i-th hop not bi-directional, stop learning! */
8582 if (i == nhops - 1)
8583 {
8584 path[i + 2] = dvl->initiator;
8585 }
8586 else
8587 {
8588 path[i + 2] = hops[nhops - i - 2].hop;
8589 }
8590
8592 "Learned inverse path with %u hops to %s\n",
8593 i + 2,
8594 GNUNET_i2s (&path[i + 2]));
8595 network_latency = get_network_latency (dvl);
8596 ilat = GNUNET_TIME_relative_multiply (network_latency, i + 2);
8597 iret = learn_dv_path (path,
8598 i + 3,
8599 ilat,
8602 if (GNUNET_SYSERR == iret)
8603 {
8604 /* path invalid or too long to be interesting for US, thus should also
8605 not be interesting to our neighbours, cut path when forwarding to
8606 'i' hops, except of course for the one that goes back to the
8607 initiator */
8609 "# DV learn not forwarded due invalidity of path",
8610 1,
8611 GNUNET_NO);
8612 do_fwd = GNUNET_NO;
8613 break;
8614 }
8615 if ((GNUNET_NO == iret) && (nhops == i + 1))
8616 {
8617 /* we have better paths, and this is the longest target,
8618 so there cannot be anything interesting later */
8620 "# DV learn not forwarded, got better paths",
8621 1,
8622 GNUNET_NO);
8623 do_fwd = GNUNET_NO;
8624 break;
8625 }
8626 }
8627 }
8628 if (MAX_DV_HOPS_ALLOWED == nhops)
8629 {
8630 /* At limit, we're out of here! */
8631 return;
8632 }
8633
8634 /* Forward to initiator, if path non-trivial and possible */
8635 bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
8636 did_initiator = GNUNET_NO;
8637 if ((1 <= nhops) &&
8638 (GNUNET_YES ==
8640 {
8641 /* send back to origin! */
8643 "Sending DVL back to initiator %s\n",
8644 GNUNET_i2s (&dvl->initiator));
8645 forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
8646 did_initiator = GNUNET_YES;
8647 }
8648 /* We forward under two conditions: either we still learned something
8649 ourselves (do_fwd), or the path was darn short and thus the initiator is
8650 likely to still be very interested in this (and we did NOT already
8651 send it back to the initiator) */
8652 if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
8653 (GNUNET_NO == did_initiator)))
8654 {
8655 /* Pick random neighbours that are not yet on the path */
8656 struct NeighbourSelectionContext nsc;
8657 unsigned int n_cnt;
8658
8660 nsc.nhops = nhops;
8661 nsc.dvl = dvl;
8662 nsc.bi_history = bi_history;
8663 nsc.hops = hops;
8664 nsc.in_time = in_time;
8665 nsc.num_eligible = 0;
8668 &nsc);
8669 if (0 == nsc.num_eligible)
8670 return; /* done here, cannot forward to anyone else */
8672 nsc.num_selections =
8675 "Forwarding DVL to %u other peers\n",
8676 nsc.num_selections);
8677 for (unsigned int i = 0; i < nsc.num_selections; i++)
8678 nsc.selections[i] =
8679 (nsc.num_selections == n_cnt)
8680 ? i /* all were selected, avoid collisions by chance */
8682 nsc.num_eligible = 0;
8685 &nsc);
8686 }
8687}
8688
8689
8697static int
8698check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
8699{
8700 uint16_t size = ntohs (dvb->header.size);
8701 uint16_t num_hops = ntohs (dvb->num_hops);
8702 const struct GNUNET_PeerIdentity *hops =
8703 (const struct GNUNET_PeerIdentity *) &dvb[1];
8704
8705 (void) cls;
8706 if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
8707 + sizeof(struct GNUNET_MessageHeader))
8708 {
8709 GNUNET_break_op (0);
8710 return GNUNET_SYSERR;
8711 }
8712 /* This peer must not be on the path */
8713 for (unsigned int i = 0; i < num_hops; i++)
8714 if (0 == GNUNET_memcmp (&hops[i], GST_my_identity))
8715 {
8716 GNUNET_break_op (0);
8717 return GNUNET_SYSERR;
8718 }
8719 return GNUNET_YES;
8720}
8721
8722
8735static void
8736forward_dv_box (struct Neighbour *next_hop,
8737 struct TransportDVBoxMessage *hdr,
8738 uint16_t total_hops,
8739 uint16_t num_hops,
8740 const struct GNUNET_PeerIdentity *hops,
8741 const void *enc_payload,
8742 uint16_t enc_payload_size)
8743{
8744 struct VirtualLink *vl = next_hop->vl;
8745 struct PendingMessage *pm;
8746 size_t msg_size = sizeof(struct TransportDVBoxMessage)
8747 + num_hops * sizeof(struct GNUNET_PeerIdentity)
8748 + enc_payload_size;
8749 char *buf;
8750 char msg_buf[msg_size] GNUNET_ALIGN;
8751 struct GNUNET_PeerIdentity *dhops;
8752
8753 hdr->num_hops = htons (num_hops);
8754 hdr->total_hops = htons (total_hops);
8755 hdr->header.size = htons (msg_size);
8756 memcpy (msg_buf, hdr, sizeof(*hdr));
8757 dhops = (struct GNUNET_PeerIdentity *) &msg_buf[sizeof(struct
8759 ;
8760 memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
8761 memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
8762
8763 if (GNUNET_YES == ntohs (hdr->without_fc))
8764 {
8766 "Forwarding control message (payload size %u) in DV Box to next hop %s (%u/%u) \n",
8767 enc_payload_size,
8768 GNUNET_i2s (&next_hop->pid),
8769 (unsigned int) num_hops,
8770 (unsigned int) total_hops);
8771 route_via_neighbour (next_hop, (const struct
8772 GNUNET_MessageHeader *) msg_buf,
8774 }
8775 else
8776 {
8777 pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
8779 "2 created pm %p storing vl %p \n",
8780 pm,
8781 vl);
8782 pm->pmt = PMT_DV_BOX;
8783 pm->vl = vl;
8784 pm->target = next_hop->pid;
8786 pm->logging_uuid = logging_uuid_gen++;
8788 pm->bytes_msg = msg_size;
8789 buf = (char *) &pm[1];
8790 memcpy (buf, msg_buf, msg_size);
8791
8793 "Created pending message %" PRIu64
8794 " for DV Box with next hop %s (%u/%u)\n",
8795 pm->logging_uuid,
8796 GNUNET_i2s (&next_hop->pid),
8797 (unsigned int) num_hops,
8798 (unsigned int) total_hops);
8799
8800 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
8801 {
8803 vl->pending_msg_head,
8804 vl->pending_msg_tail,
8805 pm);
8806
8808 }
8809 else
8810 {
8812 "The virtual link is not ready for forwarding a DV Box with payload, storing PendingMessage in ring buffer.\n");
8813
8815 {
8817
8818 GNUNET_free (pm_old);
8819 }
8822 {
8825 }
8826 else
8828
8830 "%u items stored in DV ring buffer\n",
8833 }
8834 }
8835}
8836
8837
8843static void
8844free_backtalker (struct Backtalker *b)
8845{
8846 if (NULL != b->get)
8847 {
8849 b->get = NULL;
8850 GNUNET_assert (NULL != b->cmc);
8852 b->cmc = NULL;
8853 }
8854 if (NULL != b->task)
8855 {
8857 b->task = NULL;
8858 }
8859 if (NULL != b->sc)
8860 {
8862 "store cancel\n");
8864 b->sc = NULL;
8865 }
8867 "Removing backtalker for %s\n",
8868 GNUNET_i2s (&b->pid));
8870 GNUNET_YES ==
8872 GNUNET_free (b);
8873}
8874
8875
8884static int
8885free_backtalker_cb (void *cls,
8886 const struct GNUNET_PeerIdentity *pid,
8887 void *value)
8888{
8889 struct Backtalker *b = value;
8890
8891 (void) cls;
8892 (void) pid;
8893 free_backtalker (b);
8894 return GNUNET_OK;
8895}
8896
8897
8903static void
8904backtalker_timeout_cb (void *cls)
8905{
8906 struct Backtalker *b = cls;
8907
8909 "backtalker timeout.\n");
8910 b->task = NULL;
8912 {
8914 return;
8915 }
8916 GNUNET_assert (NULL == b->sc);
8917 free_backtalker (b);
8918}
8919
8920
8929static void
8930backtalker_monotime_cb (void *cls,
8931 const struct GNUNET_PEERSTORE_Record *record,
8932 const char *emsg)
8933{
8934 struct Backtalker *b = cls;
8935 struct GNUNET_TIME_AbsoluteNBO *mtbe;
8936 struct GNUNET_TIME_Absolute mt;
8937
8938 (void) emsg;
8939 if (NULL == record)
8940 {
8941 /* we're done with #backtalker_monotime_cb() invocations,
8942 continue normal processing */
8943 b->get = NULL;
8944 GNUNET_assert (NULL != b->cmc);
8945 b->cmc->mh = (const struct GNUNET_MessageHeader *) &b[1];
8946 if (0 != b->body_size)
8948 else
8950 b->cmc = NULL;
8951 return;
8952 }
8953 if (sizeof(*mtbe) != record->value_size)
8954 {
8956 GNUNET_break (0);
8957 return;
8958 }
8959 mtbe = record->value;
8960 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
8961 if (mt.abs_value_us > b->monotonic_time.abs_value_us)
8962 {
8964 "Backtalker message from %s dropped, monotime in the past\n",
8965 GNUNET_i2s (&b->pid));
8967 GST_stats,
8968 "# Backchannel messages dropped: monotonic time not increasing",
8969 1,
8970 GNUNET_NO);
8971 b->monotonic_time = mt;
8972 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
8973 */
8974 b->body_size = 0;
8975 }
8977}
8978
8979
8987static void
8988backtalker_monotime_store_cb (void *cls, int success)
8989{
8990 struct Backtalker *b = cls;
8991
8992 if (GNUNET_OK != success)
8993 {
8995 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
8996 }
8997 b->sc = NULL;
8998 if (NULL != b->task)
8999 {
9001 b->task = NULL;
9002 }
9004}
9005
9006
9012static void
9014{
9015 struct GNUNET_TIME_AbsoluteNBO mtbe;
9016
9017 if (NULL != b->sc)
9018 {
9020 "store cancel before store with sc %p\n",
9021 b->sc);
9022 /*GNUNET_PEERSTORE_store_cancel (b->sc);
9023 b->sc = NULL;*/
9025 "store cancel before store with sc %p is null\n",
9026 b->sc);
9027 }
9028 else
9029 {
9031 b->task = NULL;
9032 }
9034 b->sc =
9036 "transport",
9037 &b->pid,
9039 &mtbe,
9040 sizeof(mtbe),
9044 b);
9045}
9046
9047
9048struct DecapsDvBoxCls
9049{
9051 const struct TransportDVBoxMessage *dvb;
9052 struct PilsRequest *pr;
9053};
9054
9055
9056static void
9057decaps_dv_box_cb (void *cls, const struct GNUNET_ShortHashCode *km)
9058{
9059 struct DecapsDvBoxCls *decaps_dv_box_cls = cls;
9060 struct CommunicatorMessageContext *cmc = decaps_dv_box_cls->cmc;
9061 const struct TransportDVBoxMessage *dvb = decaps_dv_box_cls->dvb;
9062 struct DVKeyState key;
9063 const char *hdr;
9064 size_t hdr_len;
9065 struct GNUNET_HashCode hmac;
9066
9067 decaps_dv_box_cls->pr->op = NULL;
9070 decaps_dv_box_cls->pr);
9071 GNUNET_free (decaps_dv_box_cls->pr);
9072 if (NULL == km)
9073 {
9074 GNUNET_break_op (0);
9075 finish_cmc_handling (cmc);
9076 return;
9077 }
9078 dv_setup_key_state_from_km (km, &dvb->iv, &key);
9079 hdr = (const char *) &dvb[1];
9080 hdr_len = ntohs (dvb->orig_size) - sizeof(*dvb) - sizeof(struct
9082 * ntohs (dvb->total_hops);
9083
9084 dv_hmac (&key, &hmac, hdr, hdr_len);
9085 if (0 != GNUNET_memcmp (&hmac, &dvb->hmac))
9086 {
9087 /* HMAC mismatch, discard! */
9088 GNUNET_break_op (0);
9089 finish_cmc_handling (cmc);
9090 return;
9091 }
9092 /* begin actual decryption */
9093 {
9094 struct Backtalker *b;
9095 struct GNUNET_TIME_Absolute monotime;
9096 struct TransportDVBoxPayloadP ppay = { 0 };
9097 char body[hdr_len - sizeof(ppay)] GNUNET_ALIGN;
9098 const struct GNUNET_MessageHeader *mh;
9099
9100 GNUNET_assert (hdr_len >=
9101 sizeof(ppay) + sizeof(struct GNUNET_MessageHeader));
9102 if (GNUNET_OK != dv_decrypt (&key, &ppay, hdr, sizeof(ppay)))
9103 {
9105 "Error decrypting DV payload header\n");
9106 GNUNET_break_op (0);
9107 finish_cmc_handling (cmc);
9108 return;
9109 }
9110 if (GNUNET_OK != dv_decrypt (&key, body,
9111 &hdr[sizeof(ppay)], hdr_len - sizeof(ppay)))
9112 {
9114 "Error decrypting DV payload\n");
9115 GNUNET_break_op (0);
9116 finish_cmc_handling (cmc);
9117 return;
9118 }
9119 mh = (const struct GNUNET_MessageHeader *) body;
9120 dv_key_clean (&key);
9121 if (ntohs (mh->size) != sizeof(body))
9122 {
9123 GNUNET_break_op (0);
9124 finish_cmc_handling (cmc);
9125 return;
9126 }
9127 /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
9128 switch (ntohs (mh->type))
9129 {
9131 GNUNET_break_op (0);
9132 finish_cmc_handling (cmc);
9133 return;
9134
9136 GNUNET_break_op (0);
9137 finish_cmc_handling (cmc);
9138 return;
9139
9140 default:
9141 /* permitted, continue */
9142 break;
9143 }
9144 monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time);
9146 "Decrypted backtalk from %s\n",
9147 GNUNET_i2s (&ppay.sender));
9149 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
9150 {
9152 GST_stats,
9153 "# Backchannel messages dropped: monotonic time not increasing",
9154 1,
9155 GNUNET_NO);
9156 finish_cmc_handling (cmc);
9157 return;
9158 }
9159 if ((NULL == b) ||
9160 (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
9161 {
9162 /* Check signature */
9163 struct EphemeralConfirmationPS ec;
9164
9166 ec.target = *GST_my_identity;
9167 ec.ephemeral_key = dvb->ephemeral_key;
9168 ec.purpose.size = htonl (sizeof(ec));
9169 ec.sender_monotonic_time = ppay.monotonic_time;
9170 if (
9171 GNUNET_OK !=
9174 &ec,
9175 &ppay.sender_sig,
9176 &ppay.sender.public_key))
9177 {
9178 /* Signature invalid, discard! */
9179 GNUNET_break_op (0);
9180 finish_cmc_handling (cmc);
9181 return;
9182 }
9183 }
9184 /* Update sender, we now know the real origin! */
9186 "DVBox received for me from %s via %s\n",
9187 GNUNET_i2s2 (&ppay.sender),
9188 GNUNET_i2s (&cmc->im.sender));
9189 cmc->im.sender = ppay.sender;
9190
9191 if (NULL != b)
9192 {
9193 /* update key cache and mono time */
9194 b->last_ephemeral = dvb->ephemeral_key;
9195 b->monotonic_time = monotime;
9197 b->timeout =
9199 cmc->mh = mh;
9201 return;
9202 }
9203 /* setup data structure to cache signature AND check
9204 monotonic time with PEERSTORE before forwarding backchannel payload */
9205 b = GNUNET_malloc (sizeof(struct Backtalker) + sizeof(body));
9206 b->pid = ppay.sender;
9207 b->body_size = sizeof(body);
9208 memcpy (&b[1], body, sizeof(body));
9212 &b->pid,
9213 b,
9215 b->monotonic_time = monotime; /* NOTE: to be checked still! */
9216 b->cmc = cmc;
9217 b->timeout =
9220 b->get =
9222 "transport",
9223 &b->pid,
9226 b);
9227 } /* end actual decryption */
9228}
9229
9230
9238static void
9239handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
9240{
9241 struct CommunicatorMessageContext *cmc = cls;
9242 uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
9243 uint16_t num_hops = ntohs (dvb->num_hops);
9244 const struct GNUNET_PeerIdentity *hops =
9245 (const struct GNUNET_PeerIdentity *) &dvb[1];
9246 const char *enc_payload = (const char *) &hops[num_hops];
9247 uint16_t enc_payload_size =
9248 size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
9249 struct DecapsDvBoxCls *decaps_dv_box_cls;
9250
9251 if (GNUNET_EXTRA_LOGGING > 0)
9252 {
9253 char *path;
9254
9256 for (unsigned int i = 0; i < num_hops; i++)
9257 {
9258 char *tmp;
9259
9260 GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
9261 GNUNET_free (path);
9262 path = tmp;
9263 }
9265 "Received DVBox with remaining path %s\n",
9266 path);
9267 GNUNET_free (path);
9268 }
9269
9270 if (num_hops > 0)
9271 {
9272 /* We're trying from the end of the hops array, as we may be
9273 able to find a shortcut unknown to the origin that way */
9274 for (int i = num_hops - 1; i >= 0; i--)
9275 {
9276 struct Neighbour *n;
9277
9278 if (0 == GNUNET_memcmp (&hops[i], GST_my_identity))
9279 {
9280 GNUNET_break_op (0);
9281 finish_cmc_handling (cmc);
9282 return;
9283 }
9284 n = lookup_neighbour (&hops[i]);
9285 if (NULL == n)
9286 continue;
9288 "Skipping %u/%u hops ahead while routing DV Box\n",
9289 i,
9290 num_hops);
9291
9292 forward_dv_box (n,
9293 (struct TransportDVBoxMessage *) dvb,
9294 ntohs (dvb->total_hops) + 1,
9295 num_hops - i - 1, /* number of hops left */
9296 &hops[i + 1], /* remaining hops */
9297 enc_payload,
9298 enc_payload_size);
9300 "# DV hops skipped routing boxes",
9301 i,
9302 GNUNET_NO);
9304 "# DV boxes routed (total)",
9305 1,
9306 GNUNET_NO);
9307 finish_cmc_handling (cmc);
9308 return;
9309 }
9310 /* Woopsie, next hop not in neighbours, drop! */
9312 "# DV Boxes dropped: next hop unknown",
9313 1,
9314 GNUNET_NO);
9315 finish_cmc_handling (cmc);
9316 return;
9317 }
9318 /* We are the target. Unbox and handle message. */
9320 "# DV boxes opened (ultimate target)",
9321 1,
9322 GNUNET_NO);
9323 cmc->total_hops = ntohs (dvb->total_hops);
9324
9325 {
9326 // DH key derivation with received DV, could be garbage.
9327 decaps_dv_box_cls = GNUNET_new (struct DecapsDvBoxCls);
9328 decaps_dv_box_cls->cmc = cmc;
9329 decaps_dv_box_cls->dvb = dvb;
9330 decaps_dv_box_cls->pr = GNUNET_new (struct PilsRequest);
9331
9334 decaps_dv_box_cls->pr);
9335 decaps_dv_box_cls->pr->op = GNUNET_PILS_kem_decaps (pils,
9336 &dvb->ephemeral_key,
9338 decaps_dv_box_cls);
9339 }
9340 // TODO keep track of cls and potentially clean
9341}
9342
9343
9351static int
9352check_incoming_msg (void *cls,
9353 const struct GNUNET_TRANSPORT_IncomingMessage *im)
9354{
9355 struct TransportClient *tc = cls;
9356
9357 if (CT_COMMUNICATOR != tc->type)
9358 {
9359 GNUNET_break (0);
9360 return GNUNET_SYSERR;
9361 }
9363 return GNUNET_OK;
9364}
9365
9366
9371{
9375 const char *address;
9376
9380 struct ValidationState *vs;
9381};
9382
9383
9393static int
9394check_known_address (void *cls,
9395 const struct GNUNET_PeerIdentity *pid,
9396 void *value)
9397{
9398 struct CheckKnownAddressContext *ckac = cls;
9399 struct ValidationState *vs = value;
9400
9401 (void) pid;
9402 if (0 != strcmp (vs->address, ckac->address))
9403 return GNUNET_OK;
9404 ckac->vs = vs;
9405 return GNUNET_NO;
9406}
9407
9408
9414static void
9415validation_start_cb (void *cls);
9416
9417
9425static void
9427 struct GNUNET_TIME_Absolute new_time)
9428{
9430
9431 if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
9432 return; /* be lazy */
9433 vs->next_challenge = new_time;
9434 if (NULL == vs->hn)
9435 vs->hn =
9437 else
9440 (NULL != validation_task))
9441 return;
9442 if (NULL != validation_task)
9444 /* randomize a bit */
9447 MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
9448 new_time = GNUNET_TIME_absolute_add (new_time, delta);
9451}
9452
9453
9460static void
9462 const char *address)
9463{
9464 struct GNUNET_TIME_Absolute now;
9465 struct ValidationState *vs;
9466 struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
9467
9469 pid,
9471 &ckac);
9472 if (NULL != (vs = ckac.vs))
9473 {
9474 /* if 'vs' is not currently valid, we need to speed up retrying the
9475 * validation */
9476 if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
9477 {
9478 /* reduce backoff as we got a fresh advertisement */
9479 vs->challenge_backoff =
9482 vs->challenge_backoff,
9483 2));
9486 vs->challenge_backoff));
9487 }
9488 return;
9489 }
9491 vs = GNUNET_new (struct ValidationState);
9492 vs->pid = *pid;
9493 vs->valid_until =
9495 vs->first_challenge_use = now;
9496 vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
9498 &vs->challenge,
9499 sizeof(vs->challenge));
9500 vs->address = GNUNET_strdup (address);
9501 GNUNET_CRYPTO_hash (vs->address, strlen (vs->address), &vs->hc);
9503 "Starting address validation `%s' of peer %s using challenge %s\n",
9504 address,
9505 GNUNET_i2s (pid),
9506 GNUNET_sh2s (&vs->challenge.value));
9510 &vs->pid,
9511 vs,
9514}
9515
9516
9517static struct Queue *
9518find_queue (const struct GNUNET_PeerIdentity *pid, const char *address);
9519
9520
9521static void
9522suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address);
9523
9524
9525static void
9526hello_for_incoming_cb (void *cls,
9527 const struct GNUNET_PeerIdentity *pid,
9528 const char *uri)
9529{
9530 struct Queue *q;
9531 int pfx_len;
9532 const char *eou;
9533 char *address;
9534 (void) cls;
9535
9536 eou = strstr (uri,
9537 "://");
9538 pfx_len = eou - uri;
9539 eou += 3;
9541 "%.*s-%s",
9542 pfx_len,
9543 uri,
9544 eou);
9545
9547 "helo for client %s\n",
9548 address);
9549 q = find_queue (pid, address);
9550 if (NULL == q)
9551 {
9553 }
9554 else
9557}
9558
9559
9567static void
9568handle_hello_for_incoming (void *cls,
9569 const struct GNUNET_PEERSTORE_Record *record,
9570 const char *emsg)
9571{
9572 struct IncomingRequest *ir = cls;
9574 struct GNUNET_MessageHeader *hello;
9575
9576 if (NULL != emsg)
9577 {
9579 "Got failure from PEERSTORE: %s\n",
9580 emsg);
9581 return;
9582 }
9583 hello = record->value;
9584 if (0 == GNUNET_memcmp (&record->peer, GST_my_identity))
9585 {
9587 return;
9588 }
9592 NULL);
9593 GNUNET_HELLO_parser_free (parser);
9594}
9595
9596
9597static void
9599{
9601 "Error in PEERSTORE monitoring\n");
9602}
9603
9604
9605static void
9607{
9609 "Done with initial PEERSTORE iteration during monitoring\n");
9610}
9611
9612
9613struct SignTValidationCls
9614{
9617 struct PilsRequest *pr;
9618};
9619
9620
9621static void
9622sign_t_validation_cb (void *cls,
9623 const struct GNUNET_PeerIdentity *pid,
9624 const struct GNUNET_CRYPTO_EddsaSignature *sig)
9625{
9626 struct SignTValidationCls *sign_t_validation_cls = cls;
9627 struct CommunicatorMessageContext *cmc = sign_t_validation_cls->cmc;
9628 struct TransportValidationResponseMessage tvr = sign_t_validation_cls->tvr;
9629 struct VirtualLink *vl;
9630 struct Neighbour *n;
9631 struct IncomingRequest *ir;
9632 struct GNUNET_PeerIdentity sender;
9633
9634 sign_t_validation_cls->pr->op = NULL;
9637 sign_t_validation_cls->pr);
9638 GNUNET_free (sign_t_validation_cls->pr);
9639 tvr.signature = *sig;
9640 sender = cmc->im.sender;
9641 vl = lookup_virtual_link (&sender);
9642 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9643 {
9644 // route_control_message_without_fc (&cmc->im.sender,
9646 &tvr.header,
9648 }
9649 else
9650 {
9651 /* Use route via neighbour */
9652 n = lookup_neighbour (&sender);
9653 if (NULL != n)
9654 route_via_neighbour (n, &tvr.header,
9657 }
9658
9659 finish_cmc_handling (cmc);
9660 if (NULL != vl)
9661 return;
9662
9663 /* For us, the link is still down, but we need bi-directional
9664 connections (for flow-control and for this to be useful for
9665 CORE), so we must try to bring the link up! */
9666
9667 /* (1) Check existing queues, if any, we may be lucky! */
9668 n = lookup_neighbour (&sender);
9669 if (NULL != n)
9670 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
9671 start_address_validation (&sender, q->address);
9672 /* (2) Also try to see if we have addresses in PEERSTORE for this peer
9673 we could use */
9674 for (ir = ir_head; NULL != ir; ir = ir->next)
9675 if (0 == GNUNET_memcmp (&ir->pid, &sender))
9676 return;
9677 /* we are already trying */
9678 ir = GNUNET_new (struct IncomingRequest);
9679 ir->pid = sender;
9681
9683 GNUNET_YES,
9684 "peerstore",
9685 NULL,
9688 NULL,
9690 NULL,
9692 ir);
9693 ir_total++;
9694 /* Bound attempts we do in parallel here, might otherwise get excessive */
9697};
9698
9699
9708static void
9710 void *cls,
9711 const struct TransportValidationChallengeMessage *tvc)
9712{
9713 struct CommunicatorMessageContext *cmc = cls;
9714 struct TransportValidationResponseMessage tvr = { 0 };
9715 struct GNUNET_TIME_RelativeNBO validity_duration;
9716
9717 /* DV-routed messages are not allowed for validation challenges */
9718 if (cmc->total_hops > 0)
9719 {
9720 GNUNET_break_op (0);
9721 finish_cmc_handling (cmc);
9722 return;
9723 }
9724 validity_duration = cmc->im.expected_address_validity;
9726 "Received address validation challenge %s\n",
9727 GNUNET_sh2s (&tvc->challenge.value));
9728 /* If we have a virtual link, we use this mechanism to signal the
9729 size of the flow control window, and to allow the sender
9730 to ask for increases. If for us the virtual link is still down,
9731 we will always give a window size of zero. */
9732 tvr.header.type =
9734 tvr.header.size = htons (sizeof(tvr));
9735 tvr.reserved = htonl (0);
9736 tvr.challenge = tvc->challenge;
9737 tvr.origin_time = tvc->sender_time;
9738 tvr.validity_duration = validity_duration;
9739 {
9740 /* create signature */
9741 struct TransportValidationPS tvp = {
9743 .purpose.size = htonl (sizeof(tvp)),
9744 .validity_duration = validity_duration,
9745 .challenge = tvc->challenge
9746 };
9747 struct SignTValidationCls *sign_t_validation_cls;
9748
9749 sign_t_validation_cls = GNUNET_new (struct SignTValidationCls);
9750 sign_t_validation_cls->cmc = cmc;
9751 sign_t_validation_cls->tvr = tvr;
9752 sign_t_validation_cls->pr = GNUNET_new (struct PilsRequest);
9755 sign_t_validation_cls->pr);
9756 sign_t_validation_cls->pr->op =
9758 &tvp.purpose,
9760 sign_t_validation_cls);
9761 }
9762}
9763
9764
9769{
9774
9778 struct ValidationState *vs;
9779};
9780
9781
9791static int
9792check_known_challenge (void *cls,
9793 const struct GNUNET_PeerIdentity *pid,
9794 void *value)
9795{
9796 struct CheckKnownChallengeContext *ckac = cls;
9797 struct ValidationState *vs = value;
9798
9799 (void) pid;
9800 if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
9801 return GNUNET_OK;
9802 ckac->vs = vs;
9803 return GNUNET_NO;
9804}
9805
9806
9814static void
9815peerstore_store_validation_cb (void *cls, int success)
9816{
9817 struct ValidationState *vs = cls;
9818
9819 vs->sc = NULL;
9820 if (GNUNET_YES == success)
9821 return;
9823 "# Peerstore failed to store foreign address",
9824 1,
9825 GNUNET_NO);
9826}
9827
9828
9836static struct Queue *
9837find_queue (const struct GNUNET_PeerIdentity *pid, const char *address)
9838{
9839 struct Neighbour *n;
9840
9841 n = lookup_neighbour (pid);
9842 if (NULL == n)
9843 return NULL;
9844 for (struct Queue *pos = n->queue_head; NULL != pos;
9845 pos = pos->next_neighbour)
9846 {
9847 if (0 == strcmp (pos->address, address))
9848 return pos;
9849 }
9850 return NULL;
9851}
9852
9853
9854static void
9856
9857static void
9858revalidation_start_cb (void *cls)
9859{
9860 struct ValidationState *vs = cls;
9861 struct Queue *q;
9862 struct GNUNET_TIME_Absolute now;
9863
9864 vs->revalidation_task = NULL;
9865 q = find_queue (&vs->pid, vs->address);
9866 if (NULL == q)
9867 {
9868 now = GNUNET_TIME_absolute_get ();
9869 vs->awaiting_queue = GNUNET_YES;
9870 suggest_to_connect (&vs->pid, vs->address);
9872 }
9873 else
9875}
9876
9877
9878static enum GNUNET_GenericReturnValue
9880 void *cls,
9881 const struct GNUNET_HashCode *key,
9882 void *value)
9883{
9884 (void) cls;
9886 "Key in revalidate map %s \n",
9887 GNUNET_h2s (key));
9888 return GNUNET_YES;
9889}
9890
9891
9900static void
9902 void *cls,
9903 const struct TransportValidationResponseMessage *tvr)
9904{
9905 struct CommunicatorMessageContext *cmc = cls;
9906 struct ValidationState *vs;
9907 struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
9908 .vs = NULL};
9909 struct GNUNET_TIME_Absolute origin_time;
9910 struct Queue *q;
9911 struct Neighbour *n;
9912 struct VirtualLink *vl;
9914 GST_cfg);
9915
9916 /* check this is one of our challenges */
9918 &cmc->im.sender,
9920 &ckac);
9921 if (NULL == (vs = ckac.vs))
9922 {
9923 /* This can happen simply if we 'forgot' the challenge by now,
9924 i.e. because we received the validation response twice */
9926 "# Validations dropped, challenge unknown",
9927 1,
9928 GNUNET_NO);
9930 "Validation response %s dropped, challenge unknown\n",
9931 GNUNET_sh2s (&tvr->challenge.value));
9932 finish_cmc_handling (cmc);
9933 return;
9934 }
9935
9936 /* sanity check on origin time */
9937 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
9938 if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
9939 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
9940 {
9942 "Diff first use %" PRIu64 " and last use %" PRIu64 "\n",
9943 vs->first_challenge_use.abs_value_us - origin_time.abs_value_us,
9944 origin_time.abs_value_us - vs->last_challenge_use.abs_value_us);
9945 GNUNET_break_op (0);
9946 finish_cmc_handling (cmc);
9947 return;
9948 }
9949
9950 {
9951 /* check signature */
9952 struct TransportValidationPS tvp = {
9954 .purpose.size = htonl (sizeof(tvp)),
9955 .validity_duration = tvr->validity_duration,
9956 .challenge = tvr->challenge
9957 };
9958
9959 if (
9960 GNUNET_OK !=
9962 &tvp,
9963 &tvr->signature,
9964 &cmc->im.sender.public_key))
9965 {
9966 GNUNET_break_op (0);
9967 finish_cmc_handling (cmc);
9968 return;
9969 }
9970 }
9971
9972 /* validity is capped by our willingness to keep track of the
9973 validation entry and the maximum the other peer allows */
9976 tvr->validity_duration),
9978 vs->validated_until =
9982 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
9983 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
9985 &vs->challenge,
9986 sizeof(vs->challenge));
9987 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
9988 vs->validated_until,
9989 GNUNET_TIME_relative_multiply (vs->validation_rtt,
9991 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, <, now))
9992 {
9994 "First challenge use is now %" PRIu64 " %s \n",
9995 vs->first_challenge_use.abs_value_us,
9996 GNUNET_sh2s (&vs->challenge.value));
9997 vs->first_challenge_use = now;
9998 }
9999 else
10001 "First challenge use is later %" PRIu64 " %s \n",
10002 vs->first_challenge_use.abs_value_us,
10003 GNUNET_sh2s (&vs->challenge.value));
10004 vs->last_challenge_use =
10005 GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
10006 update_next_challenge_time (vs, vs->first_challenge_use);
10008 "Validation response %s from %s accepted, address valid until %s\n",
10009 GNUNET_sh2s (&tvr->challenge.value),
10010 GNUNET_i2s (&cmc->im.sender),
10012 /*memcpy (&hkey,
10013 &hc,
10014 sizeof (hkey));*/
10016 "Key %s for address %s map size %u contains %u\n",
10017 GNUNET_h2s (&vs->hc),
10018 vs->address,
10021 &vs->hc));
10025 &vs->hc,
10026 vs,
10030 NULL);
10031 vs->revalidation_task =
10036 "transport",
10037 &cmc->im.sender,
10039 vs->address,
10040 strlen (vs->address) + 1,
10041 vs->valid_until,
10044 vs);
10045 finish_cmc_handling (cmc);
10046
10047 /* Finally, we now possibly have a confirmed (!) working queue,
10048 update queue status (if queue still is around) */
10049 q = find_queue (&vs->pid, vs->address);
10050 if (NULL == q)
10051 {
10053 "# Queues lost at time of successful validation",
10054 1,
10055 GNUNET_NO);
10056 return;
10057 }
10058 q->validated_until = vs->validated_until;
10059 q->pd.aged_rtt = vs->validation_rtt;
10060 n = q->neighbour;
10061 vl = lookup_virtual_link (&vs->pid);
10062 if (NULL == vl)
10063 {
10064 vl = GNUNET_new (struct VirtualLink);
10066 "Creating new virtual link %p to %s using direct neighbour!\n",
10067 vl,
10068 GNUNET_i2s (&vs->pid));
10069 vl->burst_addr = NULL;
10070 vl->confirmed = GNUNET_YES;
10071 vl->message_uuid_ctr =
10073 vl->target = n->pid;
10079 links,
10080 &vl->target,
10081 vl,
10083 vl->n = n;
10084 n->vl = vl;
10085 q->idle = GNUNET_YES;
10086 vl->visibility_task =
10087 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
10089 /* We lacked a confirmed connection to the target
10090 before, so tell CORE about it (finally!) */
10093 }
10094 else
10095 {
10096 /* Link was already up, remember n is also now available and we are done */
10097 if (NULL == vl->n)
10098 {
10099 vl->n = n;
10100 n->vl = vl;
10101 if (GNUNET_YES == vl->confirmed)
10103 "Virtual link to %s could now also use direct neighbour!\n",
10104 GNUNET_i2s (&vs->pid));
10105 }
10106 else
10107 {
10108 GNUNET_assert (n == vl->n);
10109 }
10110 if (GNUNET_NO == vl->confirmed)
10111 {
10112 vl->confirmed = GNUNET_YES;
10113 q->idle = GNUNET_YES;
10114 vl->visibility_task =
10115 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
10117 /* We lacked a confirmed connection to the target
10118 before, so tell CORE about it (finally!) */
10121 }
10122 }
10123}
10124
10125
10131static void
10132handle_incoming_msg (void *cls,
10133 const struct GNUNET_TRANSPORT_IncomingMessage *im)
10134{
10135 struct TransportClient *tc = cls;
10136 struct CommunicatorMessageContext *cmc =
10138
10139 cmc->tc = tc;
10140 cmc->im = *im;
10142 "Received message with size %u and flow control id %" PRIu64
10143 " via communicator from peer %s\n",
10144 ntohs (im->header.size),
10145 im->fc_id,
10146 GNUNET_i2s (&im->sender));
10147 cmc->im.neighbour_sender = cmc->im.sender;
10148 cmc->mh = (const struct GNUNET_MessageHeader *) &im[1];
10150}
10151
10152
10161static int
10162check_flow_control (void *cls, const struct TransportFlowControlMessage *fc)
10163{
10164 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10165 (void) cls;
10166
10168 "Flow control header size %u size of addresses %u number of addresses %u size of message struct %lu second struct %lu\n",
10169 ntohs (fc->header.size),
10170 ntohl (fc->size_of_addresses),
10171 ntohl (fc->number_of_addresses),
10172 sizeof(struct TransportFlowControlMessage),
10173 sizeof (struct TransportGlobalNattedAddress));
10174
10175 if (0 == number_of_addresses || ntohs (fc->header.size) == sizeof(struct
10177 + ntohl (fc->number_of_addresses) * sizeof (struct
10179 + ntohl (fc->size_of_addresses))
10180 return GNUNET_OK;
10181 else
10182 {
10183 GNUNET_break_op (0);
10184 return GNUNET_SYSERR;
10185 }
10186}
10187
10188
10189static struct GNUNET_TIME_Relative
10190calculate_rtt (struct DistanceVector *dv)
10191{
10193 unsigned int n_hops = 0;
10194
10196 "calculate_rtt\n");
10197 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
10198 pos = pos->next_dv)
10199 {
10201 "calculate_rtt %lu\n",
10202 (unsigned long) pos->pd.aged_rtt.rel_value_us);
10203 n_hops++;
10205 aged_rtt, pos
10206 ->distance
10207 + 2), ret);
10208 }
10209
10210 GNUNET_assert (0 != n_hops);
10211
10212 return ret;
10213}
10214
10215
10216static void
10218 const struct GNUNET_PeerIdentity *pid,
10219 const char *uri)
10220{
10221 struct VirtualLink *vl = cls;
10222 const char *slash;
10223 char *address_uri;
10224 char *prefix;
10225 char *uri_without_port;
10226
10227 slash = strrchr (uri, '/');
10228 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
10229 GNUNET_assert (NULL != slash);
10230 slash++;
10231 GNUNET_asprintf (&address_uri,
10232 "%s-%s",
10233 prefix,
10234 slash);
10235
10236 uri_without_port = get_address_without_port (address_uri);
10238 "iterate_address_start_burst %s %s %s %s\n",
10239 uri_without_port,
10240 uri,
10241 address_uri,
10242 slash);
10243 if (0 == strcmp (uri_without_port, slash))
10244 {
10245 vl->burst_addr = GNUNET_strndup (uri_without_port, strlen (uri_without_port)
10246 );
10247 }
10248 else
10249 vl->burst_addr = NULL;
10250
10252 GNUNET_free (uri_without_port);
10253}
10254
10255
10256static void
10257check_for_burst_address (void *cls,
10258 const struct GNUNET_PEERSTORE_Record *record,
10259 const char *emsg)
10260{
10261 struct GNUNET_StartBurstCls *sb_cls = cls;
10262 struct VirtualLink *vl = sb_cls->vl;
10263 struct GNUNET_MessageHeader *hello;
10265
10266 if (NULL != emsg)
10267 {
10269 "Got failure from PEERSTORE: %s\n",
10270 emsg);
10271 return;
10272 }
10273 if (NULL == record)
10274 {
10276 "Hello iteration end for %s\n",
10277 GNUNET_i2s (&vl->target));
10278 vl->ic = NULL;
10279 GNUNET_free (sb_cls);
10280 return;
10281 }
10282
10284 "check_for_burst_address\n");
10285 hello = record->value;
10289 vl);
10290 GNUNET_HELLO_parser_free (parser);
10291
10293 GNUNET_free (sb_cls);
10294}
10295
10296
10297static void
10298burst_timeout (void *cls)
10299{
10301}
10302
10303
10304static void
10305start_burst (void *cls)
10306{
10307 struct GNUNET_StartBurstCls *sb_cls = cls;
10308 struct VirtualLink *vl = sb_cls->vl;
10309 struct GNUNET_TRANSPORT_StartBurst *sb;
10310 struct GNUNET_MQ_Envelope *env;
10311 char *uri_without_port = vl->burst_addr;
10312
10313 burst_task = NULL;
10314 /*char buf[strlen (uri_without_port) + 1];
10315
10316 GNUNET_memcpy (buf, uri_without_port, strlen (uri_without_port));
10317 buf[strlen (uri_without_port)] = '\0';*/
10318 env =
10320 strlen (uri_without_port) + 1,
10322 sb->rtt = GNUNET_TIME_relative_hton (sb_cls->rtt);
10323 sb->pid = vl->target;
10324 memcpy (&sb[1], uri_without_port, strlen (uri_without_port) + 1);
10325 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
10326 {
10328 "iterate_address_start_burst client tc prefix %s\n",
10329 tc->details.communicator.address_prefix);
10330 if (CT_COMMUNICATOR != tc->type)
10331 continue;
10332 if (GNUNET_YES == tc->details.communicator.can_burst)
10333 {
10335 "iterate_address_start_burst %s call %lu %u rtt %lu\n",
10336 uri_without_port,
10337 strlen (uri_without_port),
10338 ntohs (sb->header.size),
10339 (unsigned long) sb_cls->rtt.rel_value_us);
10340 GNUNET_MQ_send (tc->mq, env);
10344 60),
10346 NULL);
10347 // TODO We need some algo to choose from available communicators. Can we run two bursts at once? Atm we only implemented udp burst.
10348 break;
10349 }
10350 }
10351 GNUNET_free (env);
10352 GNUNET_free (sb_cls);
10353}
10354
10355
10356static void
10357queue_burst (void *cls)
10358{
10359 struct GNUNET_StartBurstCls *sb_cls = cls;
10360 struct VirtualLink *vl = sb_cls->vl;
10361
10362 if (GNUNET_YES != use_burst)
10363 return;
10365 "burst_task %p ready %s burst addr %s (%p)\n",
10366 burst_task,
10367 sb_cls->sync_ready ? "yes" : "no",
10368 vl->burst_addr,
10369 vl->burst_addr);
10370 if (NULL != burst_task && GNUNET_NO == sb_cls->sync_ready)
10371 {
10373 burst_task = NULL;
10375 return;
10376 }
10377 if (GNUNET_NO == burst_running && NULL != vl->burst_addr && NULL == burst_task
10378 )
10379 {
10381 &start_burst,
10382 sb_cls);
10383 }
10384 else if (NULL == vl->burst_addr)
10385 {
10387 "peerstore",
10388 &vl->target,
10391 sb_cls);
10392 }
10393}
10394
10395
10404static void
10405handle_flow_control (void *cls, const struct TransportFlowControlMessage *fc)
10406{
10407 struct CommunicatorMessageContext *cmc = cls;
10408 struct VirtualLink *vl;
10410 uint32_t seq;
10411 struct GNUNET_TIME_Absolute st;
10412 uint64_t os;
10413 uint64_t wnd;
10414 uint32_t random;
10415
10417 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
10418 vl = lookup_virtual_link (&cmc->im.sender);
10419 if (NULL == vl)
10420 {
10421 vl = GNUNET_new (struct VirtualLink);
10423 "No virtual link for %p FC creating new unconfirmed virtual link to %s!\n",
10424 vl,
10425 GNUNET_i2s (&cmc->im.sender));
10426 vl->burst_addr = NULL;
10427 vl->confirmed = GNUNET_NO;
10428 vl->message_uuid_ctr =
10430 vl->target = cmc->im.sender;
10436 links,
10437 &vl->target,
10438 vl,
10440 }
10441 if (NULL != vl->n)
10442 {
10443 for (struct Queue *q = vl->n->queue_head; NULL != q; q = q->next_neighbour)
10444 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
10445 }
10446
10448 "remaining %lu timeout for neighbour %p\n",
10449 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout).
10450 rel_value_us,
10451 vl->n);
10452 if (NULL == vl->n ||
10453 0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
10454 {
10455 struct GNUNET_TIME_Relative rtt;
10456 struct GNUNET_BurstSync burst_sync;
10457 struct GNUNET_StartBurstCls *bcls;
10458
10459 bcls = GNUNET_new (struct GNUNET_StartBurstCls);
10460 bcls->vl = vl;
10461 vl->sb_cls = bcls;
10462 if (NULL != vl->dv)
10463 rtt = calculate_rtt (vl->dv);
10464 else
10466 burst_sync.rtt_average = fc->rtt;
10467 bcls->rtt = GNUNET_TIME_relative_ntoh (burst_sync.rtt_average);
10468 burst_sync.sync_ready = fc->sync_ready;
10469
10471 &burst_sync,
10472 &queue_burst,
10473 bcls);
10474 }
10475 if (0 != ntohl (fc->number_of_addresses))
10476 {
10477 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10478 const char *tgnas;
10479 unsigned int off = 0;
10480
10481 tgnas = (const char *) &fc[1];
10482
10483 for (int i = 1; i <= number_of_addresses; i++)
10484 {
10485 struct TransportGlobalNattedAddress *tgna;
10486 char *addr;
10487 unsigned int address_length;
10488
10489 tgna = (struct TransportGlobalNattedAddress*) &tgnas[off];
10490 addr = (char *) &tgna[1];
10491 address_length = ntohl (tgna->address_length);
10492 off += sizeof(struct TransportGlobalNattedAddress) + address_length;
10493
10495 "received address %s length %u\n",
10496 addr,
10497 ntohl (tgna->address_length));
10498
10499 GNUNET_NAT_add_global_address (nh, addr, ntohl (tgna->address_length));
10500 }
10501 }
10503 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
10504 {
10506 "FC dropped: Message out of order\n");
10507 /* out of order, drop */
10509 "# FC dropped: message out of order",
10510 1,
10511 GNUNET_NO);
10512 finish_cmc_handling (cmc);
10513 return;
10514 }
10515 seq = ntohl (fc->seq);
10516 if (seq < vl->last_fc_seq)
10517 {
10518 /* Wrap-around/reset of other peer; start all counters from zero */
10520 }
10521 vl->last_fc_seq = seq;
10522 vl->last_fc_timestamp = st;
10524 os = GNUNET_ntohll (fc->outbound_sent);
10526 (int64_t) (os - vl->incoming_fc_window_size_used);
10528 "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
10529 GNUNET_i2s (&vl->target),
10530 (unsigned int) seq,
10531 (unsigned long long) vl->outbound_fc_window_size,
10532 (long long) vl->incoming_fc_window_size_loss);
10535 UINT32_MAX);
10536 if ((GNUNET_YES == vl->confirmed) && ((wnd < vl->incoming_fc_window_size
10540 != wnd) ||
10541 (0 == random
10543 {
10545 "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",
10546 (unsigned long long) wnd,
10547 (unsigned long long) vl->incoming_fc_window_size,
10548 (unsigned long long) vl->last_outbound_window_size_received,
10551 }
10552 if ((wnd == vl->incoming_fc_window_size
10556 (NULL != vl->fc_retransmit_task))
10557 {
10559 "Stopping FC retransmission to %s: peer is current at window %llu\n",
10560 GNUNET_i2s (&vl->target),
10561 (unsigned long long) wnd);
10563 vl->fc_retransmit_task = NULL;
10564 vl->fc_retransmit_count = 0;
10565 }
10567 /* FC window likely increased, check transmission possibilities! */
10569 finish_cmc_handling (cmc);
10570}
10571
10572
10580static void
10582{
10584 { GNUNET_MQ_hd_var_size (fragment_box,
10587 cmc),
10588 GNUNET_MQ_hd_var_size (reliability_box,
10591 cmc),
10592 GNUNET_MQ_hd_var_size (reliability_ack,
10595 cmc),
10596 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
10599 cmc),
10600 GNUNET_MQ_hd_var_size (dv_learn,
10603 cmc),
10604 GNUNET_MQ_hd_var_size (dv_box,
10606 struct TransportDVBoxMessage,
10607 cmc),
10608 GNUNET_MQ_hd_var_size (flow_control,
10611 cmc),
10613 validation_challenge,
10616 cmc),
10618 validation_response,
10621 cmc),
10623 int ret;
10624 const struct GNUNET_MessageHeader *msg = cmc->mh;
10625
10627 "Handling message of type %u with %u bytes\n",
10628 (unsigned int) ntohs (msg->type),
10629 (unsigned int) ntohs (msg->size));
10631 if (GNUNET_SYSERR == ret)
10632 {
10633 GNUNET_break (0);
10635 GNUNET_free (cmc);
10636 return;
10637 }
10638 if (GNUNET_NO == ret)
10639 {
10640 /* unencapsulated 'raw' message */
10641 handle_raw_message (cmc, msg);
10642 }
10643}
10644
10645
10652static int
10653check_add_queue_message (void *cls,
10654 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
10655{
10656 struct TransportClient *tc = cls;
10657
10658 if (CT_COMMUNICATOR != tc->type)
10659 {
10660 GNUNET_break (0);
10661 return GNUNET_SYSERR;
10662 }
10664 return GNUNET_OK;
10665}
10666
10667
10673static void
10675{
10676 if (pm->msg_uuid_set)
10677 return;
10678 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
10679 pm->msg_uuid_set = GNUNET_YES;
10680}
10681
10682
10691static struct PendingAcknowledgement *
10693 struct DistanceVectorHop *dvh,
10694 struct PendingMessage *pm)
10695{
10696 struct PendingAcknowledgement *pa;
10697
10698 pa = GNUNET_new (struct PendingAcknowledgement);
10699 pa->queue = queue;
10700 pa->dvh = dvh;
10701 pa->pm = pm;
10702 do
10703 {
10705 &pa->ack_uuid,
10706 sizeof(pa->ack_uuid));
10707 }
10710 &pa->ack_uuid.value,
10711 pa,
10713 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
10714 GNUNET_CONTAINER_MDLL_insert (pm, pm->pa_head, pm->pa_tail, pa);
10715 if (NULL != dvh)
10718 pa->message_size = pm->bytes_msg;
10720 "Waiting for ACKnowledgment `%s' for <%" PRIu64 ">\n",
10722 pm->logging_uuid);
10723 return pa;
10724}
10725
10726
10738static struct PendingMessage *
10740 struct DistanceVectorHop *dvh,
10741 struct PendingMessage *pm)
10742{
10743 struct PendingAcknowledgement *pa;
10744 struct PendingMessage *ff;
10745 uint16_t mtu;
10746 uint16_t msize;
10747
10748 mtu = (UINT16_MAX == queue->mtu)
10749 ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
10750 : queue->mtu;
10752 "Fragmenting message <%" PRIu64
10753 "> with size %u to %s for MTU %u\n",
10754 pm->logging_uuid,
10755 pm->bytes_msg,
10756 GNUNET_i2s (&pm->vl->target),
10757 (unsigned int) mtu);
10760 "Fragmenting message %" PRIu64 " <%" PRIu64
10761 "> with size %u to %s for MTU %u\n",
10762 pm->msg_uuid.uuid,
10763 pm->logging_uuid,
10764 pm->bytes_msg,
10765 GNUNET_i2s (&pm->vl->target),
10766 (unsigned int) mtu);
10767
10768 /* This invariant is established in #handle_add_queue_message() */
10769 GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
10770
10771 /* select fragment for transmission, descending the tree if it has
10772 been expanded until we are at a leaf or at a fragment that is small
10773 enough
10774 */
10775 ff = pm;
10776 msize = ff->bytes_msg;
10777
10778 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
10779 (ff->frag_off == msize) && (NULL != ff->head_frag))
10780 {
10781 ff = ff->head_frag; /* descent into fragmented fragments */
10782 msize = ff->bytes_msg - sizeof(struct TransportFragmentBoxMessage);
10783 }
10784
10785 if (((ff->bytes_msg > mtu) || (pm == ff)) && (ff->frag_off < msize))
10786 {
10787 /* Did not yet calculate all fragments, calculate next fragment */
10788 struct PendingMessage *frag;
10789 struct TransportFragmentBoxMessage tfb;
10790 const char *orig;
10791 char *msg;
10792 uint16_t fragmax;
10793 uint16_t fragsize;
10794 uint16_t msize_ff;
10795 uint16_t xoff = 0;
10796 pm->frag_count++;
10797
10798 orig = (const char *) &ff[1];
10799 msize_ff = ff->bytes_msg;
10800 if (pm != ff)
10801 {
10802 const struct TransportFragmentBoxMessage *tfbo;
10803
10804 tfbo = (const struct TransportFragmentBoxMessage *) orig;
10805 orig += sizeof(struct TransportFragmentBoxMessage);
10806 msize_ff -= sizeof(struct TransportFragmentBoxMessage);
10807 xoff = ntohs (tfbo->frag_off);
10808 }
10809 fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
10810 fragsize = GNUNET_MIN (msize_ff - ff->frag_off, fragmax);
10811 frag =
10812 GNUNET_malloc (sizeof(struct PendingMessage)
10813 + sizeof(struct TransportFragmentBoxMessage) + fragsize);
10815 "3 created pm %p from pm %p storing vl %p from pm %p\n",
10816 frag,
10817 ff,
10818 pm->vl,
10819 pm);
10821 frag->vl = pm->vl;
10822 frag->frag_parent = ff;
10823 frag->timeout = pm->timeout;
10824 frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
10825 frag->pmt = PMT_FRAGMENT_BOX;
10826 msg = (char *) &frag[1];
10827 tfb.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT);
10828 tfb.header.size =
10829 htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
10830 pa = prepare_pending_acknowledgement (queue, dvh, frag);
10831 tfb.ack_uuid = pa->ack_uuid;
10832 tfb.msg_uuid = pm->msg_uuid;
10833 tfb.frag_off = htons (ff->frag_off + xoff);
10834 tfb.msg_size = htons (pm->bytes_msg);
10835 memcpy (msg, &tfb, sizeof(tfb));
10836 memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
10838 ff->tail_frag, frag);
10839 ff->frag_off += fragsize;
10840 ff = frag;
10841 }
10842
10843 /* Move head to the tail and return it */
10847 ff);
10851 ff);
10852
10853 return ff;
10854}
10855
10856
10869static struct PendingMessage *
10871 struct DistanceVectorHop *dvh,
10872 struct PendingMessage *pm)
10873{
10875 struct PendingAcknowledgement *pa;
10876 struct PendingMessage *bpm;
10877 char *msg;
10878
10879 if ((PMT_CORE != pm->pmt) && (PMT_DV_BOX != pm->pmt))
10880 return pm; /* already fragmented or reliability boxed, or control message:
10881 do nothing */
10882 if (NULL != pm->bpm)
10883 return pm->bpm; /* already computed earlier: do nothing */
10884 // TODO I guess we do not need this assertion. We might have a DLL with
10885 // fragments, because the MTU changed, and we do not need to fragment anymore.
10886 // But we should keep the fragments until message was completed, because
10887 // the MTU might change again.
10888 // GNUNET_assert (NULL == pm->head_frag);
10889 if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
10890 {
10891 /* failed hard */
10892 GNUNET_break (0);
10894 return NULL;
10895 }
10896
10898
10899 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
10900 + pm->bytes_msg);
10902 "4 created pm %p storing vl %p from pm %p\n",
10903 bpm,
10904 pm->vl,
10905 pm);
10907 bpm->vl = pm->vl;
10908 bpm->frag_parent = pm;
10909 // Why was this needed?
10910 // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
10911 bpm->timeout = pm->timeout;
10913 bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
10915 rbox.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX);
10916 rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
10917 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
10918
10919 rbox.ack_uuid = pa->ack_uuid;
10920 msg = (char *) &bpm[1];
10921 memcpy (msg, &rbox, sizeof(rbox));
10922 memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
10923 pm->bpm = bpm;
10925 "Preparing reliability box for message <%" PRIu64
10926 "> of size %d (%d) to %s on queue %s\n",
10927 pm->logging_uuid,
10928 pm->bytes_msg,
10929 ntohs (((const struct GNUNET_MessageHeader *) &pm[1])->size),
10930 GNUNET_i2s (&pm->vl->target),
10931 queue->address);
10932 return bpm;
10933}
10934
10935
10936static void
10939{
10940 struct VirtualLink *vl = pm->vl;
10941 struct PendingMessage *pos;
10942
10943 /* re-insert sort in neighbour list */
10947 pm);
10948 pos = vl->pending_msg_tail;
10949 while ((NULL != pos) &&
10951 pos = pos->prev_vl;
10955 pos,
10956 pm);
10957}
10958
10959
10960static unsigned int
10962{
10963 struct PendingMessage *pos;
10965
10966 pos = pm->head_frag;
10967 while (NULL != pos)
10968 {
10969 if (pos->frags_in_flight_round == pm->frags_in_flight_round ||
10970 GNUNET_NO == check_next_attempt_tree (pos, root))
10972 else
10973 {
10975 break;
10976 }
10977 pos = pos->next_frag;
10978 }
10979
10980 return frags_in_flight;
10981}
10982
10983
10984static void
10986{
10987 struct PendingMessage *pos;
10988
10989 pos = pm->head_frag;
10990 while (NULL != pos)
10991 {
10992 pos->frags_in_flight_round = pm->frags_in_flight_round;
10994 pos = pos->next_frag;
10995 }
10996}
10997
10998
11007static void
11010{
11011 if (NULL == pm->frag_parent)
11012 {
11015 "Next attempt for message <%" PRIu64 "> set to %" PRIu64 "\n",
11016 pm->logging_uuid,
11019 }
11020 else if ((PMT_RELIABILITY_BOX == pm->pmt) || (PMT_DV_BOX == pm->pmt))// || (PMT_FRAGMENT_BOX == pm->pmt))
11021 {
11022 struct PendingMessage *root = pm->frag_parent;
11023
11024 while (NULL != root->frag_parent)
11025 root = root->frag_parent;
11027 "Next attempt for root message <%" PRIu64 "> set to %s\n",
11028 root->logging_uuid,
11030 root->next_attempt = next_attempt;
11032 }
11033 else
11034 {
11035 struct PendingMessage *root = pm->frag_parent;
11036
11037 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11038 root = root->frag_parent;
11039
11041 "frag_count next attempt %u\n",
11042 root->frag_count);
11043
11044 if (GNUNET_NO == root->frags_in_flight)
11045 {
11046 root->next_attempt = next_attempt;
11048 root->frags_in_flight_round++;
11050 "Next attempt for fragmented message <%" PRIu64 "> (<%" PRIu64
11051 ">)set to %" PRIu64 "\n",
11052 pm->logging_uuid,
11053 root->logging_uuid,
11055 }
11056
11057 pm->next_attempt = root->next_attempt;
11058 pm->frags_in_flight_round = root->frags_in_flight_round;
11060
11061 if (root->bytes_msg == root->frag_off)
11062 root->frags_in_flight = check_next_attempt_tree (root, root);
11063 else
11065
11066 if (GNUNET_NO == root->frags_in_flight)
11067 {
11069 "We have no fragments in flight for message %" PRIu64
11070 ", reorder root! Next attempt is %" PRIu64 "\n",
11071 root->logging_uuid,
11073 if (PMT_DV_BOX == root->pmt)
11074 root = root->frag_parent;
11075 reorder_root_pm (root, root->next_attempt);
11076 // root->next_attempt = GNUNET_TIME_UNIT_ZERO_ABS;
11077 }
11078 else
11079 {
11080 double factor = ((double) root->frag_count - 1)
11081 / (double) root->frag_count;
11082 struct GNUNET_TIME_Relative s1;
11083 struct GNUNET_TIME_Relative s2;
11084 struct GNUNET_TIME_Relative plus_mean =
11087 next_attempt);
11088
11090 "frag_count %u after factor\n",
11091 root->frag_count);
11093 factor);
11094 s2 = GNUNET_TIME_relative_divide (plus,
11095 root->frag_count);
11096 plus_mean = GNUNET_TIME_relative_add (s1, s2);
11099 "We have fragments in flight for message %" PRIu64
11100 ", do not reorder root! Actual next attempt %" PRIu64 "\n",
11101 root->logging_uuid,
11103 }
11104 }
11105}
11106
11107
11112{
11116 struct PendingMessage *best;
11117
11121 struct DistanceVectorHop *dvh;
11122
11126 size_t real_overhead;
11127
11131 unsigned int consideration_counter;
11132
11136 int frag;
11137
11141 int relb;
11142
11146 int to_early;
11147
11151 unsigned int frags_in_flight;
11152
11157};
11158
11159
11171static void
11173 struct Queue *queue,
11174 struct VirtualLink *vl,
11175 struct DistanceVectorHop *dvh,
11176 size_t overhead)
11177{
11178 struct GNUNET_TIME_Absolute now;
11179
11180 now = GNUNET_TIME_absolute_get ();
11181 sc->to_early = GNUNET_NO;
11182 sc->frags_in_flight = GNUNET_NO;
11183 for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
11184 pos = pos->next_vl)
11185 {
11186 size_t real_overhead = overhead;
11187 int frag;
11188 int relb;
11189
11190 if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
11191 {
11193 "DV messages must not be DV-routed to next hop!\n");
11194 continue; /* DV messages must not be DV-routed to next hop! */
11195 }
11196 if (pos->next_attempt.abs_value_us > now.abs_value_us)
11197 {
11198 if (GNUNET_YES == pos->frags_in_flight)
11199 {
11200 sc->frags_in_flight = GNUNET_YES;
11202 "Fragments in flight for message %" PRIu64 "\n",
11203 pos->logging_uuid);
11204 }
11205 else
11206 {
11208 "Maybe too early, because message are sorted by next_attempt, if there are no fragments in flight.Checked message %"
11209 PRIu64 "\n",
11210 pos->logging_uuid);
11211 sc->to_early = GNUNET_YES;
11212 sc->to_early_retry_delay = GNUNET_TIME_absolute_get_remaining (
11213 pos->next_attempt);
11214 continue;
11215 }
11216 // break; /* too early for all messages, they are sorted by next_attempt */
11217 }
11218 if (NULL != pos->qe)
11219 {
11221 "not eligible\n");
11222 continue; /* not eligible */
11223 }
11224 sc->consideration_counter++;
11225 /* determine if we have to fragment, if so add fragmentation
11226 overhead! */
11228 "check %" PRIu64 " for sc->best\n",
11229 pos->logging_uuid);
11230 frag = GNUNET_NO;
11231 if (((0 != queue->mtu) &&
11232 (pos->bytes_msg + real_overhead > queue->mtu)) ||
11233 (pos->bytes_msg > UINT16_MAX - sizeof(struct
11235 ||
11236 (NULL != pos->head_frag /* fragments already exist, should
11237 respect that even if MTU is UINT16_MAX for
11238 this queue */))
11239 {
11241 "fragment msg with size %u, realoverhead is %lu\n",
11242 pos->bytes_msg,
11243 real_overhead);
11244 frag = GNUNET_YES;
11245 if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
11246 {
11247 /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
11248 header without the ACK UUID when using a *reliable* channel! */
11249 }
11250 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11251 }
11252 /* determine if we have to reliability-box, if so add reliability box
11253 overhead */
11254 relb = GNUNET_NO;
11255 if ((GNUNET_NO == frag) &&
11256 (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
11257 (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
11258 {
11259 real_overhead += sizeof(struct TransportReliabilityBoxMessage);
11260
11261 if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu))
11262 {
11263 frag = GNUNET_YES;
11264 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11265 }
11266 else
11267 {
11268 relb = GNUNET_YES;
11269 }
11271 "Create reliability box of msg with size %u, realoverhead is %lu %u %u %u\n",
11272 pos->bytes_msg,
11273 real_overhead,
11274 queue->mtu,
11275 frag,
11276 relb);
11277 }
11278
11279 /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
11280 message would beat it! */
11281 if (GNUNET_NO == sc->frags_in_flight && NULL != sc->best)
11282 {
11283 /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
11284 OPTIMIZE-ME: This is a heuristic, which so far has NOT been
11285 experimentally validated. There may be some huge potential for
11286 improvement here. Also, we right now only compare how well the
11287 given message fits _this_ queue, and do not consider how well other
11288 queues might suit the message. Taking other queues into consideration
11289 may further improve the result, but could also be expensive
11290 in terms of CPU time. */
11291 long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
11292 long long pm_score = frag * 40 + relb * 20 + real_overhead;
11293 long long time_delta =
11294 (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
11295 / 1000LL;
11296
11297 /* "time_delta" considers which message has been 'ready' for transmission
11298 for longer, if a message has a preference for low latency, increase
11299 the weight of the time_delta by 10x if it is favorable for that message */
11300 if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11301 (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
11302 time_delta *= 10; /* increase weight (always, both are low latency) */
11303 else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11304 (time_delta > 0))
11305 time_delta *= 10; /* increase weight, favors 'pos', which is low latency */
11306 else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11307 (time_delta < 0))
11308 time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */
11309 if (0 != queue->mtu)
11310 {
11311 /* Grant bonus if we are below MTU, larger bonus the closer we will
11312 be to the MTU */
11313 if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
11314 sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
11315 if (queue->mtu > real_overhead + pos->bytes_msg)
11316 pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
11317 }
11318 if (sc_score + time_delta > pm_score)
11319 {
11321 "sc_score of %" PRIu64 " larger, keep sc->best %" PRIu64
11322 "\n",
11323 pos->logging_uuid,
11324 sc->best->logging_uuid);
11325 continue; /* sc_score larger, keep sc->best */
11326 }
11327 }
11328 sc->best = pos;
11329 sc->dvh = dvh;
11330 sc->frag = frag;
11331 sc->relb = relb;
11332 sc->real_overhead = real_overhead;
11333 }
11334}
11335
11336
11347static void
11348extract_box_cb (void *cls,
11349 struct Neighbour *next_hop,
11350 const struct GNUNET_MessageHeader *hdr,
11352{
11353 struct PendingMessageScoreContext *sc = cls;
11354 struct PendingMessage *pm = sc->best;
11355 struct PendingMessage *bpm;
11356 uint16_t bsize = ntohs (hdr->size);
11357
11358 GNUNET_assert (NULL == pm->bpm);
11359 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
11361 "5 created pm %p storing vl %p from pm %p\n",
11362 bpm,
11363 pm->vl,
11364 pm);
11366 bpm->pmt = PMT_DV_BOX;
11367 bpm->vl = pm->vl;
11368 bpm->timeout = pm->timeout;
11369 bpm->bytes_msg = bsize;
11370 bpm->frag_parent = pm;
11373 "Creating DV Box %" PRIu64 " for original message %" PRIu64
11374 " (next hop is %s)\n",
11376 pm->logging_uuid,
11377 GNUNET_i2s (&next_hop->pid));
11378 memcpy (&bpm[1], hdr, bsize);
11379 pm->bpm = bpm;
11380}
11381
11382
11398static void
11399transmit_on_queue (void *cls)
11400{
11401 struct Queue *queue = cls;
11402 struct Neighbour *n = queue->neighbour;
11404 struct PendingMessage *pm;
11405
11406 queue->transmit_task = NULL;
11407 if (NULL == n->vl)
11408 {
11410 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
11411 GNUNET_i2s (&n->pid),
11412 queue->address);
11413 queue->idle = GNUNET_YES;
11414 return;
11415 }
11416 memset (&sc, 0, sizeof(sc));
11417 select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
11418 if (NULL == sc.best)
11419 {
11420 /* Also look at DVH that have the n as first hop! */
11421 for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
11422 dvh = dvh->next_neighbour)
11423 {
11425 queue,
11426 dvh->dv->vl,
11427 dvh,
11428 sizeof(struct GNUNET_PeerIdentity)
11429 * (1 + dvh->distance)
11430 + sizeof(struct TransportDVBoxMessage)
11431 + sizeof(struct TransportDVBoxPayloadP));
11432 }
11433 }
11434 if (NULL == sc.best)
11435 {
11436 /* no message pending, nothing to do here! */
11438 "No pending messages, queue `%s' to %s now idle\n",
11439 queue->address,
11440 GNUNET_i2s (&n->pid));
11441 if (GNUNET_YES == sc.to_early)
11442 schedule_transmit_on_queue (sc.to_early_retry_delay,
11443 queue,
11445 queue->idle = GNUNET_YES;
11446 return;
11447 }
11448 /* There is a message pending, we are certainly not idle */
11449 queue->idle = GNUNET_NO;
11450
11451 /* Given selection in `sc`, do transmission */
11452 pm = sc.best;
11454 "Selected message <%" PRIu64 ">\n",
11455 pm->logging_uuid);
11456 if (NULL != sc.dvh)
11457 {
11459 "Is this %u a DV box?\n",
11460 pm->pmt);
11461 GNUNET_assert (PMT_DV_BOX != pm->pmt);
11462 if ((NULL != sc.best->bpm) && (sc.best->bpm->used_dvh != sc.dvh))
11463 {
11465 "Discard old box, because we have a new DV path.\n");
11466 free_pending_message (sc.best->bpm);
11467 sc.best->bpm = NULL;
11468 }
11469
11470 if (NULL == sc.best->bpm)
11471 {
11473 "encapsulate_for_dv 2\n");
11474 encapsulate_for_dv (sc.dvh->dv,
11475 1,
11476 &sc.dvh,
11477 (const struct GNUNET_MessageHeader *) &sc.best[1],
11479 &sc,
11480 RMO_NONE,
11481 GNUNET_NO);
11482 GNUNET_assert (NULL != sc.best->bpm);
11484 "%lu %lu %lu %lu %u\n",
11485 sizeof(struct GNUNET_PeerIdentity),
11486 sizeof(struct TransportDVBoxMessage),
11487 sizeof(struct TransportDVBoxPayloadP),
11488 sizeof(struct TransportFragmentBoxMessage),
11489 ((const struct GNUNET_MessageHeader *) &sc.best[1])->size);
11490 sc.best->bpm->used_dvh = sc.dvh;
11491 }
11492 pm = sc.best->bpm;
11493 }
11494 if (GNUNET_YES == sc.frag)
11495 {
11496 pm = fragment_message (queue, sc.dvh, pm);
11497 if (NULL == pm)
11498 {
11500 "Fragmentation failed queue %s to %s for <%" PRIu64
11501 ">, trying again\n",
11502 queue->address,
11503 GNUNET_i2s (&n->pid),
11504 sc.best->logging_uuid);
11506 queue,
11508 return;
11509 }
11510 }
11511 else if (GNUNET_YES == sc.relb)
11512 {
11514 if (NULL == pm)
11515 {
11516 /* Reliability boxing failed, try next message... */
11517 GNUNET_log (
11519 "Reliability boxing failed queue %s to %s for <%" PRIu64
11520 ">, trying again\n",
11521 queue->address,
11522 GNUNET_i2s (&n->pid),
11523 sc.best->logging_uuid);
11525 queue,
11527 return;
11528 }
11529 }
11530
11531 /* Pass 'pm' for transission to the communicator */
11532 GNUNET_log (
11534 "Passing message <%" PRIu64
11535 "> to queue %s for peer %s (considered %u others)\n",
11536 pm->logging_uuid,
11537 queue->address,
11538 GNUNET_i2s (&n->pid),
11539 sc.consideration_counter);
11540
11541 /* Flow control: increment amount of traffic sent; if we are routing
11542 via DV (and thus the ultimate target of the pending message is for
11543 a different virtual link than the one of the queue), then we need
11544 to use up not only the window of the direct link but also the
11545 flow control window for the DV link! */
11546 pm->vl->outbound_fc_window_size_used += pm->bytes_msg;
11547
11548 if (pm->vl != queue->neighbour->vl)
11549 {
11550 /* If the virtual link of the queue differs, this better be distance
11551 vector routing! */
11552 GNUNET_assert (NULL != sc.dvh);
11553 /* If we do distance vector routing, we better not do this for a
11554 message that was itself DV-routed */
11555 GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
11556 /* We use the size of the unboxed message here, to avoid counting
11557 the DV-Box header which is eaten up on the way by intermediaries */
11558 queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
11559 }
11560 else
11561 {
11562 GNUNET_assert (NULL == sc.dvh);
11563 }
11564
11565 queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
11566
11567 /* Check if this transmission somehow conclusively finished handing 'pm'
11568 even without any explicit ACKs */
11569 if ((PMT_CORE == pm->pmt) ||
11570 (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
11571 {
11573 }
11574 else
11575 {
11576 struct GNUNET_TIME_Relative wait_duration;
11577 unsigned int wait_multiplier;
11578
11579 if (PMT_FRAGMENT_BOX == pm->pmt)
11580 {
11581 struct PendingMessage *root;
11582
11583 root = pm->frag_parent;
11584 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11585 root = root->frag_parent;
11586
11587 wait_multiplier = (unsigned int) ceil ((double) root->bytes_msg
11588 / ((double) root->frag_off
11589 / (double) root->frag_count))
11590 * 4;
11591 }
11592 else
11593 {
11594 // No fragments, we use 4 RTT before retransmitting.
11595 wait_multiplier = 4;
11596 }
11597
11598 // Depending on how much pending message the VirtualLink is queueing, we wait longer.
11599 // wait_multiplier = wait_multiplier * pm->vl->pending_msg_num;
11600
11602 "Wait multiplier %u\n",
11603 wait_multiplier);
11604
11605 /* Message not finished, waiting for acknowledgement.
11606 Update time by which we might retransmit 's' based on queue
11607 characteristics (i.e. RTT); it takes one RTT for the message to
11608 arrive and the ACK to come back in the best case; but the other
11609 side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
11610 retransmitting.
11611
11612 OPTIMIZE: Note that in the future this heuristic should likely
11613 be improved further (measure RTT stability, consider message
11614 urgency and size when delaying ACKs, etc.) */
11615
11616 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
11617 queue->pd.aged_rtt.rel_value_us)
11618 wait_duration = queue->pd.aged_rtt;
11619 else
11620 {
11621 wait_duration = DEFAULT_ACK_WAIT_DURATION;
11622 wait_multiplier = 4;
11623 }
11624 {
11627 wait_duration, wait_multiplier));
11629 wait_duration, wait_multiplier);
11631 "Waiting %s for ACK until %s\n",
11636 GNUNET_TIME_relative_multiply (wait_duration,
11637 wait_multiplier))
11638 );
11639 }
11640 }
11641 /* finally, re-schedule queue transmission task itself */
11643 queue,
11645}
11646
11647
11654static void
11655handle_del_queue_message (void *cls,
11656 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
11657{
11658 struct TransportClient *tc = cls;
11659
11660 if (CT_COMMUNICATOR != tc->type)
11661 {
11662 GNUNET_break (0);
11664 return;
11665 }
11666 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11667 queue = queue->next_client)
11668 {
11669 struct Neighbour *neighbour = queue->neighbour;
11670
11671 if ((ntohl (dqm->qid) != queue->qid) ||
11672 (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
11673 continue;
11675 "Dropped queue %s to peer %s\n",
11676 queue->address,
11677 GNUNET_i2s (&neighbour->pid));
11678 free_queue (queue);
11680 return;
11681 }
11682 GNUNET_break (0);
11684}
11685
11686
11687static void
11689 struct TransportClient *tc)
11690{
11691 struct PendingMessage *pm;
11692
11693 GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
11694 qe->queue->queue_tail,
11695 qe);
11696 qe->queue->queue_length--;
11697 tc->details.communicator.total_queue_length--;
11699 "Received ACK on queue %s (QID %u) to peer %s (new length: %u/%u)\n",
11700 qe->queue->address,
11701 qe->queue->qid,
11702 GNUNET_i2s (&qe->queue->neighbour->pid),
11703 qe->queue->queue_length,
11704 tc->details.communicator.total_queue_length);
11705
11706 /* if applicable, resume transmissions that waited on ACK */
11708 tc->details.communicator.total_queue_length)
11709 {
11710 /* Communicator dropped below threshold, resume all queues
11711 incident with this client! */
11713 GST_stats,
11714 "# Transmission throttled due to communicator queue limit",
11715 -1,
11716 GNUNET_NO);
11717 for (struct Queue *queue = tc->details.communicator.queue_head;
11718 NULL != queue;
11719 queue = queue->next_client)
11720 {
11722 queue,
11724 }
11725 }
11726 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
11727 {
11728 /* queue dropped below threshold; only resume this one queue */
11730 "# Transmission throttled due to queue queue limit",
11731 -1,
11732 GNUNET_NO);
11734 qe->queue,
11736 }
11737 else if (1 == qe->queue->q_capacity)
11738 {
11739 // TODO I guess this will never happen, because the communicator triggers this by updating its queue length itself.
11741 "Transmission rescheduled due to communicator message queue with qid %u has capacity %"
11742 PRIu64 ".\n",
11743 qe->queue->qid,
11744 qe->queue->q_capacity);
11745 /* message queue has capacity; only resume this one queue */
11746 /* queue dropped below threshold; only resume this one queue */
11748 "# Transmission throttled due to message queue capacity",
11749 -1,
11750 GNUNET_NO);
11752 qe->queue,
11754 }
11755
11756 if (NULL != (pm = qe->pm))
11757 {
11758 struct VirtualLink *vl;
11759
11760 // GNUNET_assert (qe == pm->qe);
11761 pm->qe = NULL;
11762 /* If waiting for this communicator may have blocked transmission
11763 of pm on other queues for this neighbour, force schedule
11764 transmit on queue for queues of the neighbour */
11765 if (NULL == pm->frag_parent)
11766 {
11767 vl = pm->vl;
11768 if ((NULL != vl) &&
11769 (NULL != vl->pending_msg_head) &&
11770 (vl->pending_msg_head == pm))
11772 }
11773 }
11774 GNUNET_free (qe);
11775}
11776
11777
11784static void
11785handle_send_message_ack (void *cls,
11786 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
11787{
11788 struct TransportClient *tc = cls;
11789 struct QueueEntry *qe;
11790
11791 if (CT_COMMUNICATOR != tc->type)
11792 {
11793 GNUNET_break (0);
11795 return;
11796 }
11797
11798 /* find our queue entry matching the ACK */
11799 qe = NULL;
11801 "Looking for queue for PID %s\n",
11802 GNUNET_i2s (&sma->receiver));
11803 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11804 queue = queue->next_client)
11805 {
11806 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
11807 continue;
11809 "Found PID %s\n",
11810 GNUNET_i2s (&queue->neighbour->pid));
11811
11812
11813 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
11814 qep = qep->next)
11815 {
11816 if (qep->mid != GNUNET_ntohll (sma->mid) || queue->qid != ntohl (
11817 sma->qid))
11818 continue;
11820 "QueueEntry MID: %" PRIu64 " on queue QID: %u, Ack MID: %"
11821 PRIu64 " Ack QID %u\n",
11822 qep->mid,
11823 queue->qid,
11824 GNUNET_ntohll (sma->mid),
11825 ntohl (sma->qid));
11826 qe = qep;
11827 if ((NULL != qe->pm) && (qe->pm->qe != qe))
11829 "For pending message %" PRIu64 " we had retransmissions.\n",
11830 qe->pm->logging_uuid);
11831 break;
11832 }
11833 }
11834 if (NULL == qe)
11835 {
11837 "No QueueEntry found for Ack MID %" PRIu64 " QID: %u\n",
11838 GNUNET_ntohll (sma->mid),
11839 ntohl (sma->qid));
11840 // TODO I guess this can happen, if the Ack from the peer comes before the Ack from the queue.
11841 // Update: Maybe QueueEntry was accidentally freed during freeing PendingMessage.
11842 /* this should never happen */
11843 // GNUNET_break (0);
11844 // GNUNET_SERVICE_client_drop (tc->client);
11846 return;
11847 }
11850}
11851
11852
11858static void
11859handle_burst_finished (void *cls,
11860 const struct GNUNET_TRANSPORT_BurstFinished *bf)
11861{
11863}
11864
11865
11875static int
11876notify_client_queues (void *cls,
11877 const struct GNUNET_PeerIdentity *pid,
11878 void *value)
11879{
11880 struct TransportClient *tc = cls;
11881 struct Neighbour *neighbour = value;
11882
11883 GNUNET_assert (CT_MONITOR == tc->type);
11884 for (struct Queue *q = neighbour->queue_head; NULL != q;
11885 q = q->next_neighbour)
11886 {
11887 struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
11888 .cs = q->cs,
11889 .num_msg_pending = q->num_msg_pending,
11890 .num_bytes_pending = q->num_bytes_pending };
11891
11892 notify_monitor (tc, pid, q->address, q->nt, &me);
11893 }
11894 return GNUNET_OK;
11895}
11896
11897
11904static void
11905handle_monitor_start (void *cls,
11907{
11908 struct TransportClient *tc = cls;
11909
11910 if (CT_NONE != tc->type)
11911 {
11912 GNUNET_break (0);
11914 return;
11915 }
11916 tc->type = CT_MONITOR;
11917 tc->details.monitor.peer = start->peer;
11918 tc->details.monitor.one_shot = ntohl (start->one_shot);
11922}
11923
11924
11932static struct TransportClient *
11933lookup_communicator (const char *prefix)
11934{
11935 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
11936 {
11937 if (CT_COMMUNICATOR != tc->type)
11938 continue;
11939 if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
11940 return tc;
11941 }
11942 GNUNET_log (
11944 "Someone suggested use of communicator for `%s', but we do not have such a communicator!\n",
11945 prefix);
11946 return NULL;
11947}
11948
11949
11957static void
11958suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address)
11959{
11960 static uint32_t idgen = 0;
11961 struct TransportClient *tc;
11962 char *prefix;
11963 struct GNUNET_TRANSPORT_CreateQueue *cqm;
11964 struct GNUNET_MQ_Envelope *env;
11965 size_t alen;
11966
11968 if (NULL == prefix)
11969 {
11970 GNUNET_break (0); /* We got an invalid address!? */
11971 return;
11972 }
11974 if (NULL == tc)
11975 {
11977 "# Suggestions ignored due to missing communicator",
11978 1,
11979 GNUNET_NO);
11981 "Cannot connect to %s at `%s', no matching communicator present\n",
11982 GNUNET_i2s (pid),
11983 address);
11985 return;
11986 }
11987 /* forward suggestion for queue creation to communicator */
11989 "Request #%u for `%s' communicator to create queue to `%s' at `%s'\n",
11990 (unsigned int) idgen,
11991 prefix,
11992 GNUNET_i2s (pid),
11993 address);
11995 alen = strlen (address) + 1;
11996 env =
11998 cqm->request_id = htonl (idgen++);
11999 cqm->receiver = *pid;
12000 memcpy (&cqm[1], address, alen);
12001 GNUNET_MQ_send (tc->mq, env);
12002}
12003
12004
12012static void
12014{
12016 struct GNUNET_TIME_Absolute monotonic_time;
12017
12018 if (NULL != vs->revalidation_task)
12019 {
12020 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
12021 vs->revalidation_task = NULL;
12022 }
12023 /*memcpy (&hkey,
12024 &hc,
12025 sizeof (hkey));*/
12027 "Remove key %s for address %s map size %u contains %u\n",
12028 GNUNET_h2s (&vs->hc),
12029 vs->address,
12032 &vs->hc));
12034
12036 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
12037 vs->last_challenge_use.abs_value_us)
12038 {
12039 vs->first_challenge_use = monotonic_time;
12040 }
12041 vs->last_challenge_use = monotonic_time;
12042 tvc.header.type =
12044 tvc.header.size = htons (sizeof(tvc));
12045 tvc.reserved = htonl (0);
12046 tvc.challenge = vs->challenge;
12047 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
12049 "Sending address validation challenge %s to %s\n",
12051 GNUNET_i2s (&q->neighbour->pid));
12052 queue_send_msg (q, NULL, &tvc, sizeof(tvc));
12053}
12054
12055
12061static void
12062validation_start_cb (void *cls)
12063{
12064 struct ValidationState *vs;
12065 struct Queue *q;
12067 GST_cfg);
12068
12069 (void) cls;
12070 validation_task = NULL;
12072 /* drop validations past their expiration */
12073 while (
12074 (NULL != vs) &&
12076 {
12078 "Validation response %s cleaned up\n",
12079 GNUNET_sh2s (&vs->challenge.value));
12082 }
12083 if (NULL == vs)
12084 {
12086 "Address validation task not scheduled anymore, nothing to do\n");
12087 return; /* woopsie, no more addresses known, should only
12088 happen if we're really a lonely peer */
12089 }
12090 q = find_queue (&vs->pid, vs->address);
12091 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
12092 {
12094 "To early to start next address validation for challenge %s\n",
12095 GNUNET_sh2s (&vs->challenge.value));
12096 return;
12097 }
12098 if (NULL == q)
12099 {
12100 vs->awaiting_queue = GNUNET_YES;
12101 suggest_to_connect (&vs->pid, vs->address);
12102 }
12103 else
12105 /* Finally, reschedule next attempt */
12106 vs->challenge_backoff =
12107 GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
12110 "Address validation task will run again in %s\n",
12111 GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
12112 GNUNET_YES));
12115 vs->challenge_backoff));
12116}
12117
12118
12123{
12127 struct Queue *q;
12128
12132 unsigned int quality_count;
12133
12137 unsigned int num_queues;
12138
12143 unsigned int k;
12144};
12145
12146
12158static int
12159check_connection_quality (void *cls,
12160 const struct GNUNET_PeerIdentity *pid,
12161 void *value)
12162{
12163 struct QueueQualityContext *ctx = cls;
12164 struct Neighbour *n = value;
12165 int do_inc;
12166
12167 (void) pid;
12168 do_inc = GNUNET_NO;
12169 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
12170 {
12171 ctx->num_queues++;
12172 if (0 == ctx->k--)
12173 ctx->q = q;
12174 /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
12175 statistics and consider those as well here? */
12176 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
12177 do_inc = GNUNET_YES;
12178 }
12179 if (GNUNET_YES == do_inc)
12180 ctx->quality_count++;
12181 return GNUNET_OK;
12182}
12183
12184
12196static void
12197start_dv_learn (void *cls);
12198
12199
12200struct SignDvInitCls
12201{
12203 struct LearnLaunchEntry *lle;
12204 struct QueueQualityContext qqc;
12205 struct PilsRequest *pr;
12206};
12207
12208
12209static void
12210sign_dv_init_cb (void *cls,
12211 const struct GNUNET_PeerIdentity *pid,
12212 const struct GNUNET_CRYPTO_EddsaSignature *sig)
12213{
12214 struct SignDvInitCls *sign_dv_init_cls = cls;
12215 struct TransportDVLearnMessage dvl = sign_dv_init_cls->dvl;
12216 struct LearnLaunchEntry *lle = sign_dv_init_cls->lle;
12217 struct QueueQualityContext qqc = sign_dv_init_cls->qqc;
12218
12219 sign_dv_init_cls->pr->op = NULL;
12222 sign_dv_init_cls->pr);
12223 GNUNET_free (sign_dv_init_cls->pr);
12224
12225 dvl.init_sig = *sig;
12227 dvl.challenge = lle->challenge;
12228
12229 qqc.quality_count = 0;
12231 qqc.num_queues = 0;
12232 qqc.q = NULL;
12235 &qqc);
12236 GNUNET_assert (NULL != qqc.q);
12237
12238 /* Do this as close to transmission time as possible! */
12240
12241 queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
12242 /* reschedule this job, randomizing the time it runs (but no
12243 actual backoff!) */
12247 NULL);
12248}
12249
12250
12262static void
12263start_dv_learn (void *cls)
12264{
12265 struct LearnLaunchEntry *lle;
12266 struct QueueQualityContext qqc;
12267 struct TransportDVLearnMessage dvl;
12268
12269 (void) cls;
12270 dvlearn_task = NULL;
12272 return; /* lost all connectivity, cannot do learning */
12273 qqc.quality_count = 0;
12274 qqc.num_queues = 0;
12278 &qqc);
12280 {
12281 struct GNUNET_TIME_Relative delay;
12282 unsigned int factor;
12283
12284 /* scale our retries by how far we are above the threshold */
12288 "At connection quality %u, will launch DV learn in %s\n",
12289 qqc.quality_count,
12292 return;
12293 }
12294 /* remove old entries in #dvlearn_map if it has grown too big */
12295 while (MAX_DV_LEARN_PENDING <=
12297 {
12298 lle = lle_tail;
12301 &lle->challenge.value,
12302 lle));
12304 GNUNET_free (lle);
12305 }
12306 /* setup data structure for learning */
12307 lle = GNUNET_new (struct LearnLaunchEntry);
12309 &lle->challenge,
12310 sizeof(lle->challenge));
12312 "Starting launch DV learn with challenge %s\n",
12313 GNUNET_sh2s (&lle->challenge.value));
12318 &lle->challenge.value,
12319 lle,
12322 dvl.header.size = htons (sizeof(dvl));
12323 dvl.num_hops = htons (0);
12324 dvl.bidirectional = htons (0);
12326 dvl.monotonic_time =
12328 // We will set the below again later
12329 memset (&dvl.init_sig, 0, sizeof dvl.init_sig);
12330 dvl.challenge = lle->challenge;
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 inconsistent with ours. Ignoring...\n");
13572 "Proposed address list:\n");
13575 "Current address list:\n");
13577 GNUNET_HELLO_builder_free (nbuilder);
13578 return;
13579 }
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}
13595
13596
13604static void
13605run (void *cls,
13606 const struct GNUNET_CONFIGURATION_Handle *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}
13672
13673
13679 "transport",
13681 &run,
13684 NULL,
13685 /* communication with applications */
13686 GNUNET_MQ_hd_fixed_size (suggest,
13689 NULL),
13690 GNUNET_MQ_hd_fixed_size (suggest_cancel,
13693 NULL),
13694 GNUNET_MQ_hd_var_size (request_hello_validation,
13697 NULL),
13698 /* communication with core */
13699 GNUNET_MQ_hd_fixed_size (client_start,
13701 struct StartMessage,
13702 NULL),
13703 GNUNET_MQ_hd_var_size (client_send,
13705 struct OutboundMessage,
13706 NULL),
13707 GNUNET_MQ_hd_fixed_size (client_recv_ok,
13709 struct RecvOkMessage,
13710 NULL),
13711 /* communication with communicators */
13712 GNUNET_MQ_hd_var_size (communicator_available,
13715 NULL),
13716 GNUNET_MQ_hd_var_size (communicator_backchannel,
13719 NULL),
13720 GNUNET_MQ_hd_var_size (add_address,
13723 NULL),
13724 GNUNET_MQ_hd_fixed_size (del_address,
13727 NULL),
13728 GNUNET_MQ_hd_var_size (incoming_msg,
13731 NULL),
13732 GNUNET_MQ_hd_fixed_size (queue_create_ok,
13735 NULL),
13736 GNUNET_MQ_hd_fixed_size (queue_create_fail,
13739 NULL),
13740 GNUNET_MQ_hd_var_size (add_queue_message,
13743 NULL),
13744 GNUNET_MQ_hd_fixed_size (update_queue_message,
13747 NULL),
13748 GNUNET_MQ_hd_fixed_size (del_queue_message,
13751 NULL),
13752 GNUNET_MQ_hd_fixed_size (send_message_ack,
13755 NULL),
13756 GNUNET_MQ_hd_fixed_size (burst_finished,
13759 NULL),
13760 /* communication with monitors */
13761 GNUNET_MQ_hd_fixed_size (monitor_start,
13764 NULL),
13766
13767
13768/* 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 void queue(const char *label, uint32_t rd_count, struct GNUNET_GNSRECORD_Data *rd, const struct Zone *zone)
Add hostname to the list of requests to be made.
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_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
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:575
void GNUNET_PILS_cancel(struct GNUNET_PILS_Operation *op)
Cancel request.
Definition pils_api.c:495
struct GNUNET_PILS_Operation * GNUNET_PILS_sign_by_peer_identity(struct GNUNET_PILS_Handle *handle, const struct GNUNET_CRYPTO_SignaturePurpose *purpose, GNUNET_PILS_SignResultCallback cb, void *cb_cls)
Sign data with the peer id.
Definition pils_api.c:428
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
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:541
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)
#define GNUNET_CRYPTO_hkdf_expand(result, out_len, 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)
#define GNUNET_CRYPTO_kdf_arg_string(d)
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_CRYPTO_kdf_arg_auto(d)
#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:572
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:1260
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:1345
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
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:1310
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:1283
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:1213
#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:1623
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:626
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:604
#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:830
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:601
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:737
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:583
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:851
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:616
#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:860
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:548
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:636
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition strings.c:665
#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:436
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.
char aes_key[256/8]
Symmetric key to use for encryption.
char aes_ctr[128/8]
Counter value to use during setup.
struct DVKeyState::@73 material
Actual key material.
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_SignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
struct GNUNET_PeerIdentity succ
Identity of the next peer on the path.
Content signed by the initiator during DV learning.
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Time at the initiator when generating the signature.
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_SignaturePurpose 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.
an ECC signature using EdDSA.
HPKE DHKEM encapsulation (X25519) See RFC 9180.
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...
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:141
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_HashCode addr_hash GNUNET_PACKED
Hash of the address.
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose must be GNUNET_SIGNATURE_PURPOSE_TRANSPORT_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.
union TransportClient::@68 details
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::@68::@72 application
Information for type CT_APPLICATION.
struct TransportClient::@68::@70 monitor
Information for type CT_MONITOR.
struct Queue * queue_head
Head of DLL of queues offered by this communicator.
struct AddressListEntry * addr_head
Head of list of the addresses of this peer offered by this communicator.
struct TransportClient::@68::@69 core
Information for type CT_CORE.
struct GNUNET_CONTAINER_MultiPeerMap * requests
Map of requests for peers the given client application would like to see connections for.
struct GNUNET_SERVICE_Client * client
Handle to the client.
struct TransportClient * prev
Kept in a DLL.
struct TransportClient::@68::@71 communicator
Information for type CT_COMMUNICATOR.
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.
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_TIME_RelativeNBO validity_duration
How long does the sender believe the address on which the challenge was received to remain valid?
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE.
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 5209 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 11400 of file gnunet-service-transport.c.

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

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_SignaturePurpose::purpose, EphemeralConfirmationPS::purpose, SignDvCls::req, EphemeralConfirmationPS::sender_monotonic_time, sign_dv_cb(), GNUNET_CRYPTO_SignaturePurpose::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 11689 of file gnunet-service-transport.c.

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

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 */
5103 &key->material,
5104 sizeof(key->material),
5105 km,
5106 GNUNET_CRYPTO_kdf_arg_string ("gnunet-transport-dv-key"),
5110 "Deriving backchannel key based on KM %s and IV %s\n",
5111 GNUNET_sh2s (km),
5112 GNUNET_sh2s (iv));
5113 GNUNET_assert (0 == gcry_cipher_open (&key->cipher,
5114 GCRY_CIPHER_AES256 /* low level: go for speed */
5115 ,
5116 GCRY_CIPHER_MODE_CTR,
5117 0 /* flags */));
5118 GNUNET_assert (0 == gcry_cipher_setkey (key->cipher,
5119 &key->material.aes_key,
5120 sizeof(key->material.aes_key)));
5121 gcry_cipher_setctr (key->cipher,
5122 &key->material.aes_ctr,
5123 sizeof(key->material.aes_ctr));
5124}

References GNUNET_assert, GNUNET_CRYPTO_hkdf_expand, GNUNET_CRYPTO_kdf_arg_auto, GNUNET_CRYPTO_kdf_arg_string, 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 5137 of file gnunet-service-transport.c.

5141{
5142 GNUNET_CRYPTO_hmac (&key->material.hmac_key, data, data_size, hmac);
5143}

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 5156 of file gnunet-service-transport.c.

5157{
5158 GNUNET_assert (0 ==
5159 gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size));
5160}

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 5174 of file gnunet-service-transport.c.

5178{
5179 return (0 ==
5180 gcry_cipher_decrypt (key->cipher,
5181 out, out_size,
5182 ciph, out_size)) ? GNUNET_OK : GNUNET_SYSERR;
5183}

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 5192 of file gnunet-service-transport.c.

5193{
5194 gcry_cipher_close (key->cipher);
5195 GNUNET_CRYPTO_zero_keys (&key->material, sizeof(key->material));
5196}

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 5229 of file gnunet-service-transport.c.

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

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 5347 of file gnunet-service-transport.c.

5351{
5352 (void) cls;
5353 (void) route_via_neighbour (next_hop, hdr, RMO_UNCONFIRMED_ALLOWED);
5354}

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 5369 of file gnunet-service-transport.c.

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

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 5534 of file gnunet-service-transport.c.

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

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 5481 of file gnunet-service-transport.c.

5482{
5483 struct VirtualLink *vl = cls;
5484 vl->fc_retransmit_task = NULL;
5485 consider_sending_fc (cls);
5486}

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 5501 of file gnunet-service-transport.c.

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

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 10191 of file gnunet-service-transport.c.

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

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 5651 of file gnunet-service-transport.c.

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

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 5789 of file gnunet-service-transport.c.

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

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 5861 of file gnunet-service-transport.c.

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

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 5925 of file gnunet-service-transport.c.

5927{
5928 struct TransportClient *tc = cls;
5929
5930 if (CT_COMMUNICATOR != tc->type)
5931 {
5932 GNUNET_break (0);
5933 return GNUNET_SYSERR;
5934 }
5936 return GNUNET_OK;
5937}

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 6192 of file gnunet-service-transport.c.

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

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 5974 of file gnunet-service-transport.c.

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

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 5999 of file gnunet-service-transport.c.

6002{
6003 struct PilsAddressSignContext *pc = cls;
6004 struct GNUNET_MQ_Envelope *env;
6005 const struct GNUNET_MessageHeader *msg;
6006
6007 pc->req->op = NULL;
6010 pc->req);
6011 GNUNET_free (pc->req);
6012 pc->req = NULL;
6015 pid,
6016 sig,
6017 pc->et);
6020 "store_pi 1\n");
6022 msg,
6023 shc_cont,
6024 pc);
6025 GNUNET_free (env);
6026}

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 6036 of file gnunet-service-transport.c.

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

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 6077 of file gnunet-service-transport.c.

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

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 6161 of file gnunet-service-transport.c.

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

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_SignaturePurpose::purpose, SignedAddress::purpose, and GNUNET_CRYPTO_SignaturePurpose::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 6248 of file gnunet-service-transport.c.

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

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 6285 of file gnunet-service-transport.c.

6286{
6287
6289 "Feeding addresses to PILS\n");
6290 pils_feed_task = NULL;
6291
6293 GST_my_hello);
6294}

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 6304 of file gnunet-service-transport.c.

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

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 6364 of file gnunet-service-transport.c.

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

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 10582 of file gnunet-service-transport.c.

10583{
10585 { GNUNET_MQ_hd_var_size (fragment_box,
10588 cmc),
10589 GNUNET_MQ_hd_var_size (reliability_box,
10592 cmc),
10593 GNUNET_MQ_hd_var_size (reliability_ack,
10596 cmc),
10597 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
10600 cmc),
10601 GNUNET_MQ_hd_var_size (dv_learn,
10604 cmc),
10605 GNUNET_MQ_hd_var_size (dv_box,
10607 struct TransportDVBoxMessage,
10608 cmc),
10609 GNUNET_MQ_hd_var_size (flow_control,
10612 cmc),
10614 validation_challenge,
10617 cmc),
10619 validation_response,
10622 cmc),
10624 int ret;
10625 const struct GNUNET_MessageHeader *msg = cmc->mh;
10626
10628 "Handling message of type %u with %u bytes\n",
10629 (unsigned int) ntohs (msg->type),
10630 (unsigned int) ntohs (msg->size));
10632 if (GNUNET_SYSERR == ret)
10633 {
10634 GNUNET_break (0);
10636 GNUNET_free (cmc);
10637 return;
10638 }
10639 if (GNUNET_NO == ret)
10640 {
10641 /* unencapsulated 'raw' message */
10642 handle_raw_message (cmc, msg);
10643 }
10644}

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 6424 of file gnunet-service-transport.c.

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

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 6445 of file gnunet-service-transport.c.

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

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 6549 of file gnunet-service-transport.c.

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

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 6652 of file gnunet-service-transport.c.

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

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 6683 of file gnunet-service-transport.c.

6684{
6685 struct AcknowledgementCummulator *ac = cls;
6686
6687 ac->task = NULL;
6688 GNUNET_assert (0 == ac->num_acks);
6690 GNUNET_YES ==
6692 GNUNET_free (ac);
6693}

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 6702 of file gnunet-service-transport.c.

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

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 6770 of file gnunet-service-transport.c.

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

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 6841 of file gnunet-service-transport.c.

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

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 6864 of file gnunet-service-transport.c.

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

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 7034 of file gnunet-service-transport.c.

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

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 7061 of file gnunet-service-transport.c.

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

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 7102 of file gnunet-service-transport.c.

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

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 7129 of file gnunet-service-transport.c.

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

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 7155 of file gnunet-service-transport.c.

7158{
7159 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
7160}

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 7171 of file gnunet-service-transport.c.

7174{
7175 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
7176}

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 7187 of file gnunet-service-transport.c.

7188{
7189 struct PendingMessage *pos;
7190
7192 "Complete transmission of message %" PRIu64 " %u\n",
7193 pm->logging_uuid,
7194 pm->pmt);
7195 switch (pm->pmt)
7196 {
7197 case PMT_CORE:
7199 /* Full message sent, we are done */
7201 return;
7202
7203 case PMT_FRAGMENT_BOX:
7204 /* Fragment sent over reliable channel */
7205 pos = pm->frag_parent;
7209 "pos frag_off %lu pos bytes_msg %lu pmt %u parent %u\n",
7210 (unsigned long) pos->frag_off,
7211 (unsigned long) pos->bytes_msg,
7212 pos->pmt,
7213 NULL == pos->frag_parent ? 1 : 0);
7214 /* check if subtree is done */
7215 while ((NULL == pos->head_frag) && (pos->frag_off == (pos->bytes_msg
7216 - sizeof(struct
7218 &&
7219 (NULL != pos->frag_parent))
7220 {
7221 pm = pos;
7222 pos = pm->frag_parent;
7223 if ((NULL == pos) && (PMT_DV_BOX == pm->pmt))
7224 {
7226 return;
7227 }
7228 else if (PMT_DV_BOX == pm->pmt)
7229 {
7231 return;
7232 }
7235 }
7236
7237 /* Was this the last applicable fragment? */
7238 if ((NULL == pos->head_frag) && (NULL == pos->frag_parent || PMT_DV_BOX ==
7239 pos->pmt) &&
7240 (pos->frag_off == pos->bytes_msg))
7242 return;
7243
7244 case PMT_DV_BOX:
7246 "Completed transmission of message %" PRIu64 " (DV Box)\n",
7247 pm->logging_uuid);
7248 if (NULL != pm->frag_parent)
7249 {
7250 pos = pm->frag_parent;
7252 pos->bpm = NULL;
7254 }
7255 else
7257 return;
7258 }
7259}

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 7270 of file gnunet-service-transport.c.

7272{
7273 struct GNUNET_TIME_Relative delay;
7274
7276 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
7277 if (NULL != pa->queue && 1 == pa->num_send)
7279 if (NULL != pa->dvh && 1 == pa->num_send)
7280 update_dvh_performance (pa->dvh, delay, pa->message_size);
7281 if (NULL != pa->pm)
7284}

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 7295 of file gnunet-service-transport.c.

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

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 7326 of file gnunet-service-transport.c.

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

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 7377 of file gnunet-service-transport.c.

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

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 7414 of file gnunet-service-transport.c.

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

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 7483 of file gnunet-service-transport.c.

7484{
7485 struct DistanceVector *dv = cls;
7486 struct DistanceVectorHop *pos;
7487
7488 dv->timeout_task = NULL;
7489 while (NULL != (pos = dv->dv_head))
7490 {
7491 GNUNET_assert (dv == pos->dv);
7493 break;
7495 }
7496 if (NULL == pos)
7497 {
7498 free_dv_route (dv);
7499 return;
7500 }
7501 dv->timeout_task =
7503}

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 7507 of file gnunet-service-transport.c.

7508{
7509
7510 const struct GNUNET_PeerIdentity target = vl->target;
7511
7512
7514 {
7515 struct RingBufferEntry *ring_buffer_copy[RING_BUFFER_SIZE];
7516 unsigned int tail = GNUNET_YES == is_ring_buffer_full ? ring_buffer_head :
7517 0;
7518 unsigned int head = GNUNET_YES == is_ring_buffer_full ? RING_BUFFER_SIZE :
7521 struct CommunicatorMessageContext *cmc;
7522 struct RingBufferEntry *rbe;
7523 struct GNUNET_MessageHeader *mh;
7524
7526 "Sending from ring buffer, which has %u items\n",
7527 head);
7528
7529 ring_buffer_head = 0;
7530 for (unsigned int i = 0; i < head; i++)
7531 {
7532 rbe = ring_buffer[(i + tail) % RING_BUFFER_SIZE];
7533 cmc = rbe->cmc;
7534 mh = rbe->mh;
7535
7536 im = cmc->im;
7537 // mh = cmc->mh;
7539 "Sending message of type %u to ring buffer target %s using vl target %s index %u\n",
7540 mh->type,
7541 GNUNET_i2s (&im.sender),
7542 GNUNET_i2s2 (&target),
7543 (i + tail) % RING_BUFFER_SIZE);
7544 if (0 == GNUNET_memcmp (&target, &im.sender))
7545 {
7547 "Finish handling message of type %u and size %u\n",
7548 (unsigned int) ntohs (mh->type),
7549 (unsigned int) ntohs (mh->size));
7551 GNUNET_free (mh);
7552 GNUNET_free (rbe->cmc);
7553 GNUNET_free (rbe);
7554 }
7555 else
7556 {
7557 ring_buffer_copy[ring_buffer_head] = rbe;
7559 }
7560 }
7561
7564 {
7566 }
7567
7568 for (unsigned int i = 0; i < ring_buffer_head; i++)
7569 {
7570 ring_buffer[i] = ring_buffer_copy[i];
7572 "ring_buffer_copy[i]->mh->type for i %u %u\n",
7573 i,
7574 ring_buffer_copy[i]->mh->type);
7576 "ring_buffer[i]->mh->type for i %u %u\n",
7577 i,
7578 ring_buffer[i]->mh->type);
7579 }
7580
7582 "%u items still in ring buffer\n",
7584 }
7585
7587 {
7588 struct PendingMessage *ring_buffer_dv_copy[RING_BUFFER_SIZE];
7589 struct PendingMessage *pm;
7590 unsigned int tail = GNUNET_YES == is_ring_buffer_dv_full ?
7592 0;
7593 unsigned int head = GNUNET_YES == is_ring_buffer_dv_full ?
7596
7598 "Sending from ring buffer dv, which has %u items\n",
7599 head);
7600
7602 for (unsigned int i = 0; i < head; i++)
7603 {
7604 pm = ring_buffer_dv[(i + tail) % RING_BUFFER_SIZE];
7605
7607 "Sending to ring buffer target %s using vl target %s\n",
7608 GNUNET_i2s (&pm->target),
7609 GNUNET_i2s2 (&target));
7610 if (0 == GNUNET_memcmp (&target, &pm->target))
7611 {
7613 "Adding PendingMessage to vl, checking transmission.\n");
7614 pm->vl = vl;
7618 pm);
7619
7621 }
7622 else
7623 {
7624 ring_buffer_dv_copy[ring_buffer_dv_head] = pm;
7626 }
7627 }
7628
7630 {
7632 }
7633
7634 for (unsigned int i = 0; i < ring_buffer_dv_head; i++)
7635 ring_buffer_dv[i] = ring_buffer_dv_copy[i];
7636
7638 "%u items still in ring buffer dv.\n",
7640
7641 }
7642}

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 7653 of file gnunet-service-transport.c.

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

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 7741 of file gnunet-service-transport.c.

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

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 7921 of file gnunet-service-transport.c.

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

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 7966 of file gnunet-service-transport.c.

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

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 8021 of file gnunet-service-transport.c.

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

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_SignaturePurpose::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 8092 of file gnunet-service-transport.c.

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

References DvInitPS::challenge, GNUNET_break_op, GNUNET_CRYPTO_eddsa_verify, GNUNET_OK, GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR, GNUNET_SYSERR, init, GNUNET_CRYPTO_SignaturePurpose::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 8174 of file gnunet-service-transport.c.

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

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 8203 of file gnunet-service-transport.c.

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

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 8281 of file gnunet-service-transport.c.

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

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 8328 of file gnunet-service-transport.c.

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

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 8340 of file gnunet-service-transport.c.

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

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 8374 of file gnunet-service-transport.c.

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

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_SignaturePurpose::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 8699 of file gnunet-service-transport.c.

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

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 8737 of file gnunet-service-transport.c.

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

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 8845 of file gnunet-service-transport.c.

8846{
8847 if (NULL != b->get)
8848 {
8850 b->get = NULL;
8851 GNUNET_assert (NULL != b->cmc);
8853 b->cmc = NULL;
8854 }
8855 if (NULL != b->task)
8856 {
8858 b->task = NULL;
8859 }
8860 if (NULL != b->sc)
8861 {
8863 "store cancel\n");
8865 b->sc = NULL;
8866 }
8868 "Removing backtalker for %s\n",
8869 GNUNET_i2s (&b->pid));
8871 GNUNET_YES ==
8873 GNUNET_free (b);
8874}

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 8886 of file gnunet-service-transport.c.

8889{
8890 struct Backtalker *b = value;
8891
8892 (void) cls;
8893 (void) pid;
8894 free_backtalker (b);
8895 return GNUNET_OK;
8896}

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 8905 of file gnunet-service-transport.c.

8906{
8907 struct Backtalker *b = cls;
8908
8910 "backtalker timeout.\n");
8911 b->task = NULL;
8913 {
8915 return;
8916 }
8917 GNUNET_assert (NULL == b->sc);
8918 free_backtalker (b);
8919}

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 8931 of file gnunet-service-transport.c.

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

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 8989 of file gnunet-service-transport.c.

8990{
8991 struct Backtalker *b = cls;
8992
8993 if (GNUNET_OK != success)
8994 {
8996 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
8997 }
8998 b->sc = NULL;
8999 if (NULL != b->task)
9000 {
9002 b->task = NULL;
9003 }
9005}

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 9014 of file gnunet-service-transport.c.

9015{
9016 struct GNUNET_TIME_AbsoluteNBO mtbe;
9017
9018 if (NULL != b->sc)
9019 {
9021 "store cancel before store with sc %p\n",
9022 b->sc);
9023 /*GNUNET_PEERSTORE_store_cancel (b->sc);
9024 b->sc = NULL;*/
9026 "store cancel before store with sc %p is null\n",
9027 b->sc);
9028 }
9029 else
9030 {
9032 b->task = NULL;
9033 }
9035 b->sc =
9037 "transport",
9038 &b->pid,
9040 &mtbe,
9041 sizeof(mtbe),
9045 b);
9046}

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 9058 of file gnunet-service-transport.c.

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

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(), DecapsDvBoxCls::dvb, 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_SignaturePurpose::purpose, EphemeralConfirmationPS::purpose, TransportDVBoxPayloadP::sender, GNUNET_TRANSPORT_IncomingMessage::sender, EphemeralConfirmationPS::sender_monotonic_time, TransportDVBoxPayloadP::sender_sig, GNUNET_CRYPTO_SignaturePurpose::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 9240 of file gnunet-service-transport.c.

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

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 9353 of file gnunet-service-transport.c.

9355{
9356 struct TransportClient *tc = cls;
9357
9358 if (CT_COMMUNICATOR != tc->type)
9359 {
9360 GNUNET_break (0);
9361 return GNUNET_SYSERR;
9362 }
9364 return GNUNET_OK;
9365}

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 9395 of file gnunet-service-transport.c.

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

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 12063 of file gnunet-service-transport.c.

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

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 9427 of file gnunet-service-transport.c.

9429{
9431
9432 if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
9433 return; /* be lazy */
9434 vs->next_challenge = new_time;
9435 if (NULL == vs->hn)
9436 vs->hn =
9438 else
9441 (NULL != validation_task))
9442 return;
9443 if (NULL != validation_task)
9445 /* randomize a bit */
9448 MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
9449 new_time = GNUNET_TIME_absolute_add (new_time, delta);
9452}

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 9462 of file gnunet-service-transport.c.

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

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 9838 of file gnunet-service-transport.c.

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

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 11959 of file gnunet-service-transport.c.

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

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 9527 of file gnunet-service-transport.c.

9530{
9531 struct Queue *q;
9532 int pfx_len;
9533 const char *eou;
9534 char *address;
9535 (void) cls;
9536
9537 eou = strstr (uri,
9538 "://");
9539 pfx_len = eou - uri;
9540 eou += 3;
9542 "%.*s-%s",
9543 pfx_len,
9544 uri,
9545 eou);
9546
9548 "helo for client %s\n",
9549 address);
9550 q = find_queue (pid, address);
9551 if (NULL == q)
9552 {
9554 }
9555 else
9558}

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 9569 of file gnunet-service-transport.c.

9572{
9573 struct IncomingRequest *ir = cls;
9575 struct GNUNET_MessageHeader *hello;
9576
9577 if (NULL != emsg)
9578 {
9580 "Got failure from PEERSTORE: %s\n",
9581 emsg);
9582 return;
9583 }
9584 hello = record->value;
9585 if (0 == GNUNET_memcmp (&record->peer, GST_my_identity))
9586 {
9588 return;
9589 }
9593 NULL);
9594 GNUNET_HELLO_parser_free (parser);
9595}

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 9599 of file gnunet-service-transport.c.

9600{
9602 "Error in PEERSTORE monitoring\n");
9603}

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 9607 of file gnunet-service-transport.c.

9608{
9610 "Done with initial PEERSTORE iteration during monitoring\n");
9611}

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 9623 of file gnunet-service-transport.c.

9626{
9627 struct SignTValidationCls *sign_t_validation_cls = cls;
9628 struct CommunicatorMessageContext *cmc = sign_t_validation_cls->cmc;
9629 struct TransportValidationResponseMessage tvr = sign_t_validation_cls->tvr;
9630 struct VirtualLink *vl;
9631 struct Neighbour *n;
9632 struct IncomingRequest *ir;
9633 struct GNUNET_PeerIdentity sender;
9634
9635 sign_t_validation_cls->pr->op = NULL;
9638 sign_t_validation_cls->pr);
9639 GNUNET_free (sign_t_validation_cls->pr);
9640 tvr.signature = *sig;
9641 sender = cmc->im.sender;
9642 vl = lookup_virtual_link (&sender);
9643 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9644 {
9645 // route_control_message_without_fc (&cmc->im.sender,
9647 &tvr.header,
9649 }
9650 else
9651 {
9652 /* Use route via neighbour */
9653 n = lookup_neighbour (&sender);
9654 if (NULL != n)
9655 route_via_neighbour (n, &tvr.header,
9658 }
9659
9660 finish_cmc_handling (cmc);
9661 if (NULL != vl)
9662 return;
9663
9664 /* For us, the link is still down, but we need bi-directional
9665 connections (for flow-control and for this to be useful for
9666 CORE), so we must try to bring the link up! */
9667
9668 /* (1) Check existing queues, if any, we may be lucky! */
9669 n = lookup_neighbour (&sender);
9670 if (NULL != n)
9671 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
9672 start_address_validation (&sender, q->address);
9673 /* (2) Also try to see if we have addresses in PEERSTORE for this peer
9674 we could use */
9675 for (ir = ir_head; NULL != ir; ir = ir->next)
9676 if (0 == GNUNET_memcmp (&ir->pid, &sender))
9677 return;
9678 /* we are already trying */
9679 ir = GNUNET_new (struct IncomingRequest);
9680 ir->pid = sender;
9682
9684 GNUNET_YES,
9685 "peerstore",
9686 NULL,
9689 NULL,
9691 NULL,
9693 ir);
9694 ir_total++;
9695 /* Bound attempts we do in parallel here, might otherwise get excessive */
9698};

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 9710 of file gnunet-service-transport.c.

9713{
9714 struct CommunicatorMessageContext *cmc = cls;
9715 struct TransportValidationResponseMessage tvr = { 0 };
9716 struct GNUNET_TIME_RelativeNBO validity_duration;
9717
9718 /* DV-routed messages are not allowed for validation challenges */
9719 if (cmc->total_hops > 0)
9720 {
9721 GNUNET_break_op (0);
9722 finish_cmc_handling (cmc);
9723 return;
9724 }
9725 validity_duration = cmc->im.expected_address_validity;
9727 "Received address validation challenge %s\n",
9728 GNUNET_sh2s (&tvc->challenge.value));
9729 /* If we have a virtual link, we use this mechanism to signal the
9730 size of the flow control window, and to allow the sender
9731 to ask for increases. If for us the virtual link is still down,
9732 we will always give a window size of zero. */
9733 tvr.header.type =
9735 tvr.header.size = htons (sizeof(tvr));
9736 tvr.reserved = htonl (0);
9737 tvr.challenge = tvc->challenge;
9738 tvr.origin_time = tvc->sender_time;
9739 tvr.validity_duration = validity_duration;
9740 {
9741 /* create signature */
9742 struct TransportValidationPS tvp = {
9744 .purpose.size = htonl (sizeof(tvp)),
9745 .validity_duration = validity_duration,
9746 .challenge = tvc->challenge
9747 };
9748 struct SignTValidationCls *sign_t_validation_cls;
9749
9750 sign_t_validation_cls = GNUNET_new (struct SignTValidationCls);
9751 sign_t_validation_cls->cmc = cmc;
9752 sign_t_validation_cls->tvr = tvr;
9753 sign_t_validation_cls->pr = GNUNET_new (struct PilsRequest);
9756 sign_t_validation_cls->pr);
9757 sign_t_validation_cls->pr->op =
9759 &tvp.purpose,
9761 sign_t_validation_cls);
9762 }
9763}

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_SignaturePurpose::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 9793 of file gnunet-service-transport.c.

9796{
9797 struct CheckKnownChallengeContext *ckac = cls;
9798 struct ValidationState *vs = value;
9799
9800 (void) pid;
9801 if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
9802 return GNUNET_OK;
9803 ckac->vs = vs;
9804 return GNUNET_NO;
9805}

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 9816 of file gnunet-service-transport.c.

9817{
9818 struct ValidationState *vs = cls;
9819
9820 vs->sc = NULL;
9821 if (GNUNET_YES == success)
9822 return;
9824 "# Peerstore failed to store foreign address",
9825 1,
9826 GNUNET_NO);
9827}

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 12014 of file gnunet-service-transport.c.

12015{
12017 struct GNUNET_TIME_Absolute monotonic_time;
12018
12019 if (NULL != vs->revalidation_task)
12020 {
12021 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
12022 vs->revalidation_task = NULL;
12023 }
12024 /*memcpy (&hkey,
12025 &hc,
12026 sizeof (hkey));*/
12028 "Remove key %s for address %s map size %u contains %u\n",
12029 GNUNET_h2s (&vs->hc),
12030 vs->address,
12033 &vs->hc));
12035
12037 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
12038 vs->last_challenge_use.abs_value_us)
12039 {
12040 vs->first_challenge_use = monotonic_time;
12041 }
12042 vs->last_challenge_use = monotonic_time;
12043 tvc.header.type =
12045 tvc.header.size = htons (sizeof(tvc));
12046 tvc.reserved = htonl (0);
12047 tvc.challenge = vs->challenge;
12048 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
12050 "Sending address validation challenge %s to %s\n",
12051 GNUNET_sh2s (&tvc.challenge.value),
12052 GNUNET_i2s (&q->neighbour->pid));
12053 queue_send_msg (q, NULL, &tvc, sizeof(tvc));
12054}

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 9859 of file gnunet-service-transport.c.

9860{
9861 struct ValidationState *vs = cls;
9862 struct Queue *q;
9863 struct GNUNET_TIME_Absolute now;
9864
9865 vs->revalidation_task = NULL;
9866 q = find_queue (&vs->pid, vs->address);
9867 if (NULL == q)
9868 {
9869 now = GNUNET_TIME_absolute_get ();
9870 vs->awaiting_queue = GNUNET_YES;
9871 suggest_to_connect (&vs->pid, vs->address);
9873 }
9874 else
9876}

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 9880 of file gnunet-service-transport.c.

9884{
9885 (void) cls;
9887 "Key in revalidate map %s \n",
9888 GNUNET_h2s (key));
9889 return GNUNET_YES;
9890}

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 9902 of file gnunet-service-transport.c.

9905{
9906 struct CommunicatorMessageContext *cmc = cls;
9907 struct ValidationState *vs;
9908 struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
9909 .vs = NULL};
9910 struct GNUNET_TIME_Absolute origin_time;
9911 struct Queue *q;
9912 struct Neighbour *n;
9913 struct VirtualLink *vl;
9915 GST_cfg);
9916
9917 /* check this is one of our challenges */
9919 &cmc->im.sender,
9921 &ckac);
9922 if (NULL == (vs = ckac.vs))
9923 {
9924 /* This can happen simply if we 'forgot' the challenge by now,
9925 i.e. because we received the validation response twice */
9927 "# Validations dropped, challenge unknown",
9928 1,
9929 GNUNET_NO);
9931 "Validation response %s dropped, challenge unknown\n",
9932 GNUNET_sh2s (&tvr->challenge.value));
9933 finish_cmc_handling (cmc);
9934 return;
9935 }
9936
9937 /* sanity check on origin time */
9938 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
9939 if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
9940 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
9941 {
9943 "Diff first use %" PRIu64 " and last use %" PRIu64 "\n",
9944 vs->first_challenge_use.abs_value_us - origin_time.abs_value_us,
9945 origin_time.abs_value_us - vs->last_challenge_use.abs_value_us);
9946 GNUNET_break_op (0);
9947 finish_cmc_handling (cmc);
9948 return;
9949 }
9950
9951 {
9952 /* check signature */
9953 struct TransportValidationPS tvp = {
9955 .purpose.size = htonl (sizeof(tvp)),
9956 .validity_duration = tvr->validity_duration,
9957 .challenge = tvr->challenge
9958 };
9959
9960 if (
9961 GNUNET_OK !=
9963 &tvp,
9964 &tvr->signature,
9965 &cmc->im.sender.public_key))
9966 {
9967 GNUNET_break_op (0);
9968 finish_cmc_handling (cmc);
9969 return;
9970 }
9971 }
9972
9973 /* validity is capped by our willingness to keep track of the
9974 validation entry and the maximum the other peer allows */
9977 tvr->validity_duration),
9979 vs->validated_until =
9983 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
9984 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
9986 &vs->challenge,
9987 sizeof(vs->challenge));
9988 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
9989 vs->validated_until,
9990 GNUNET_TIME_relative_multiply (vs->validation_rtt,
9992 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, <, now))
9993 {
9995 "First challenge use is now %" PRIu64 " %s \n",
9996 vs->first_challenge_use.abs_value_us,
9997 GNUNET_sh2s (&vs->challenge.value));
9998 vs->first_challenge_use = now;
9999 }
10000 else
10002 "First challenge use is later %" PRIu64 " %s \n",
10003 vs->first_challenge_use.abs_value_us,
10004 GNUNET_sh2s (&vs->challenge.value));
10005 vs->last_challenge_use =
10006 GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
10007 update_next_challenge_time (vs, vs->first_challenge_use);
10009 "Validation response %s from %s accepted, address valid until %s\n",
10010 GNUNET_sh2s (&tvr->challenge.value),
10011 GNUNET_i2s (&cmc->im.sender),
10013 /*memcpy (&hkey,
10014 &hc,
10015 sizeof (hkey));*/
10017 "Key %s for address %s map size %u contains %u\n",
10018 GNUNET_h2s (&vs->hc),
10019 vs->address,
10022 &vs->hc));
10026 &vs->hc,
10027 vs,
10031 NULL);
10032 vs->revalidation_task =
10037 "transport",
10038 &cmc->im.sender,
10040 vs->address,
10041 strlen (vs->address) + 1,
10042 vs->valid_until,
10045 vs);
10046 finish_cmc_handling (cmc);
10047
10048 /* Finally, we now possibly have a confirmed (!) working queue,
10049 update queue status (if queue still is around) */
10050 q = find_queue (&vs->pid, vs->address);
10051 if (NULL == q)
10052 {
10054 "# Queues lost at time of successful validation",
10055 1,
10056 GNUNET_NO);
10057 return;
10058 }
10059 q->validated_until = vs->validated_until;
10060 q->pd.aged_rtt = vs->validation_rtt;
10061 n = q->neighbour;
10062 vl = lookup_virtual_link (&vs->pid);
10063 if (NULL == vl)
10064 {
10065 vl = GNUNET_new (struct VirtualLink);
10067 "Creating new virtual link %p to %s using direct neighbour!\n",
10068 vl,
10069 GNUNET_i2s (&vs->pid));
10070 vl->burst_addr = NULL;
10071 vl->confirmed = GNUNET_YES;
10072 vl->message_uuid_ctr =
10074 vl->target = n->pid;
10080 links,
10081 &vl->target,
10082 vl,
10084 vl->n = n;
10085 n->vl = vl;
10086 q->idle = GNUNET_YES;
10087 vl->visibility_task =
10088 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
10090 /* We lacked a confirmed connection to the target
10091 before, so tell CORE about it (finally!) */
10094 }
10095 else
10096 {
10097 /* Link was already up, remember n is also now available and we are done */
10098 if (NULL == vl->n)
10099 {
10100 vl->n = n;
10101 n->vl = vl;
10102 if (GNUNET_YES == vl->confirmed)
10104 "Virtual link to %s could now also use direct neighbour!\n",
10105 GNUNET_i2s (&vs->pid));
10106 }
10107 else
10108 {
10109 GNUNET_assert (n == vl->n);
10110 }
10111 if (GNUNET_NO == vl->confirmed)
10112 {
10113 vl->confirmed = GNUNET_YES;
10114 q->idle = GNUNET_YES;
10115 vl->visibility_task =
10116 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
10118 /* We lacked a confirmed connection to the target
10119 before, so tell CORE about it (finally!) */
10122 }
10123 }
10124}

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_SignaturePurpose::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 10133 of file gnunet-service-transport.c.

10135{
10136 struct TransportClient *tc = cls;
10137 struct CommunicatorMessageContext *cmc =
10139
10140 cmc->tc = tc;
10141 cmc->im = *im;
10143 "Received message with size %u and flow control id %" PRIu64
10144 " via communicator from peer %s\n",
10145 ntohs (im->header.size),
10146 im->fc_id,
10147 GNUNET_i2s (&im->sender));
10148 cmc->im.neighbour_sender = cmc->im.sender;
10149 cmc->mh = (const struct GNUNET_MessageHeader *) &im[1];
10151}

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 10163 of file gnunet-service-transport.c.

10164{
10165 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10166 (void) cls;
10167
10169 "Flow control header size %u size of addresses %u number of addresses %u size of message struct %lu second struct %lu\n",
10170 ntohs (fc->header.size),
10171 ntohl (fc->size_of_addresses),
10172 ntohl (fc->number_of_addresses),
10173 sizeof(struct TransportFlowControlMessage),
10174 sizeof (struct TransportGlobalNattedAddress));
10175
10176 if (0 == number_of_addresses || ntohs (fc->header.size) == sizeof(struct
10178 + ntohl (fc->number_of_addresses) * sizeof (struct
10180 + ntohl (fc->size_of_addresses))
10181 return GNUNET_OK;
10182 else
10183 {
10184 GNUNET_break_op (0);
10185 return GNUNET_SYSERR;
10186 }
10187}

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 10218 of file gnunet-service-transport.c.

10221{
10222 struct VirtualLink *vl = cls;
10223 const char *slash;
10224 char *address_uri;
10225 char *prefix;
10226 char *uri_without_port;
10227
10228 slash = strrchr (uri, '/');
10229 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
10230 GNUNET_assert (NULL != slash);
10231 slash++;
10232 GNUNET_asprintf (&address_uri,
10233 "%s-%s",
10234 prefix,
10235 slash);
10236
10237 uri_without_port = get_address_without_port (address_uri);
10239 "iterate_address_start_burst %s %s %s %s\n",
10240 uri_without_port,
10241 uri,
10242 address_uri,
10243 slash);
10244 if (0 == strcmp (uri_without_port, slash))
10245 {
10246 vl->burst_addr = GNUNET_strndup (uri_without_port, strlen (uri_without_port)
10247 );
10248 }
10249 else
10250 vl->burst_addr = NULL;
10251
10253 GNUNET_free (uri_without_port);
10254}

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 10258 of file gnunet-service-transport.c.

10261{
10262 struct GNUNET_StartBurstCls *sb_cls = cls;
10263 struct VirtualLink *vl = sb_cls->vl;
10264 struct GNUNET_MessageHeader *hello;
10266
10267 if (NULL != emsg)
10268 {
10270 "Got failure from PEERSTORE: %s\n",
10271 emsg);
10272 return;
10273 }
10274 if (NULL == record)
10275 {
10277 "Hello iteration end for %s\n",
10278 GNUNET_i2s (&vl->target));
10279 vl->ic = NULL;
10280 GNUNET_free (sb_cls);
10281 return;
10282 }
10283
10285 "check_for_burst_address\n");
10286 hello = record->value;
10290 vl);
10291 GNUNET_HELLO_parser_free (parser);
10292
10294 GNUNET_free (sb_cls);
10295}

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 10299 of file gnunet-service-transport.c.

10300{
10302}

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 10306 of file gnunet-service-transport.c.

10307{
10308 struct GNUNET_StartBurstCls *sb_cls = cls;
10309 struct VirtualLink *vl = sb_cls->vl;
10310 struct GNUNET_TRANSPORT_StartBurst *sb;
10311 struct GNUNET_MQ_Envelope *env;
10312 char *uri_without_port = vl->burst_addr;
10313
10314 burst_task = NULL;
10315 /*char buf[strlen (uri_without_port) + 1];
10316
10317 GNUNET_memcpy (buf, uri_without_port, strlen (uri_without_port));
10318 buf[strlen (uri_without_port)] = '\0';*/
10319 env =
10321 strlen (uri_without_port) + 1,
10323 sb->rtt = GNUNET_TIME_relative_hton (sb_cls->rtt);
10324 sb->pid = vl->target;
10325 memcpy (&sb[1], uri_without_port, strlen (uri_without_port) + 1);
10326 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
10327 {
10329 "iterate_address_start_burst client tc prefix %s\n",
10330 tc->details.communicator.address_prefix);
10331 if (CT_COMMUNICATOR != tc->type)
10332 continue;
10333 if (GNUNET_YES == tc->details.communicator.can_burst)
10334 {
10336 "iterate_address_start_burst %s call %lu %u rtt %lu\n",
10337 uri_without_port,
10338 strlen (uri_without_port),
10339 ntohs (sb->header.size),
10340 (unsigned long) sb_cls->rtt.rel_value_us);
10341 GNUNET_MQ_send (tc->mq, env);
10345 60),
10347 NULL);
10348 // TODO We need some algo to choose from available communicators. Can we run two bursts at once? Atm we only implemented udp burst.
10349 break;
10350 }
10351 }
10352 GNUNET_free (env);
10353 GNUNET_free (sb_cls);
10354}

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 10358 of file gnunet-service-transport.c.

10359{
10360 struct GNUNET_StartBurstCls *sb_cls = cls;
10361 struct VirtualLink *vl = sb_cls->vl;
10362
10363 if (GNUNET_YES != use_burst)
10364 return;
10366 "burst_task %p ready %s burst addr %s (%p)\n",
10367 burst_task,
10368 sb_cls->sync_ready ? "yes" : "no",
10369 vl->burst_addr,
10370 vl->burst_addr);
10371 if (NULL != burst_task && GNUNET_NO == sb_cls->sync_ready)
10372 {
10374 burst_task = NULL;
10376 return;
10377 }
10378 if (GNUNET_NO == burst_running && NULL != vl->burst_addr && NULL == burst_task
10379 )
10380 {
10382 &start_burst,
10383 sb_cls);
10384 }
10385 else if (NULL == vl->burst_addr)
10386 {
10388 "peerstore",
10389 &vl->target,
10392 sb_cls);
10393 }
10394}

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 10406 of file gnunet-service-transport.c.

10407{
10408 struct CommunicatorMessageContext *cmc = cls;
10409 struct VirtualLink *vl;
10411 uint32_t seq;
10412 struct GNUNET_TIME_Absolute st;
10413 uint64_t os;
10414 uint64_t wnd;
10415 uint32_t random;
10416
10418 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
10419 vl = lookup_virtual_link (&cmc->im.sender);
10420 if (NULL == vl)
10421 {
10422 vl = GNUNET_new (struct VirtualLink);
10424 "No virtual link for %p FC creating new unconfirmed virtual link to %s!\n",
10425 vl,
10426 GNUNET_i2s (&cmc->im.sender));
10427 vl->burst_addr = NULL;
10428 vl->confirmed = GNUNET_NO;
10429 vl->message_uuid_ctr =
10431 vl->target = cmc->im.sender;
10437 links,
10438 &vl->target,
10439 vl,
10441 }
10442 if (NULL != vl->n)
10443 {
10444 for (struct Queue *q = vl->n->queue_head; NULL != q; q = q->next_neighbour)
10445 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
10446 }
10447
10449 "remaining %lu timeout for neighbour %p\n",
10450 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout).
10451 rel_value_us,
10452 vl->n);
10453 if (NULL == vl->n ||
10454 0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
10455 {
10456 struct GNUNET_TIME_Relative rtt;
10457 struct GNUNET_BurstSync burst_sync;
10458 struct GNUNET_StartBurstCls *bcls;
10459
10460 bcls = GNUNET_new (struct GNUNET_StartBurstCls);
10461 bcls->vl = vl;
10462 vl->sb_cls = bcls;
10463 if (NULL != vl->dv)
10464 rtt = calculate_rtt (vl->dv);
10465 else
10467 burst_sync.rtt_average = fc->rtt;
10468 bcls->rtt = GNUNET_TIME_relative_ntoh (burst_sync.rtt_average);
10469 burst_sync.sync_ready = fc->sync_ready;
10470
10472 &burst_sync,
10473 &queue_burst,
10474 bcls);
10475 }
10476 if (0 != ntohl (fc->number_of_addresses))
10477 {
10478 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10479 const char *tgnas;
10480 unsigned int off = 0;
10481
10482 tgnas = (const char *) &fc[1];
10483
10484 for (int i = 1; i <= number_of_addresses; i++)
10485 {
10486 struct TransportGlobalNattedAddress *tgna;
10487 char *addr;
10488 unsigned int address_length;
10489
10490 tgna = (struct TransportGlobalNattedAddress*) &tgnas[off];
10491 addr = (char *) &tgna[1];
10492 address_length = ntohl (tgna->address_length);
10493 off += sizeof(struct TransportGlobalNattedAddress) + address_length;
10494
10496 "received address %s length %u\n",
10497 addr,
10498 ntohl (tgna->address_length));
10499
10500 GNUNET_NAT_add_global_address (nh, addr, ntohl (tgna->address_length));
10501 }
10502 }
10504 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
10505 {
10507 "FC dropped: Message out of order\n");
10508 /* out of order, drop */
10510 "# FC dropped: message out of order",
10511 1,
10512 GNUNET_NO);
10513 finish_cmc_handling (cmc);
10514 return;
10515 }
10516 seq = ntohl (fc->seq);
10517 if (seq < vl->last_fc_seq)
10518 {
10519 /* Wrap-around/reset of other peer; start all counters from zero */
10521 }
10522 vl->last_fc_seq = seq;
10523 vl->last_fc_timestamp = st;
10525 os = GNUNET_ntohll (fc->outbound_sent);
10527 (int64_t) (os - vl->incoming_fc_window_size_used);
10529 "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
10530 GNUNET_i2s (&vl->target),
10531 (unsigned int) seq,
10532 (unsigned long long) vl->outbound_fc_window_size,
10533 (long long) vl->incoming_fc_window_size_loss);
10536 UINT32_MAX);
10537 if ((GNUNET_YES == vl->confirmed) && ((wnd < vl->incoming_fc_window_size
10541 != wnd) ||
10542 (0 == random
10544 {
10546 "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",
10547 (unsigned long long) wnd,
10548 (unsigned long long) vl->incoming_fc_window_size,
10549 (unsigned long long) vl->last_outbound_window_size_received,
10552 }
10553 if ((wnd == vl->incoming_fc_window_size
10557 (NULL != vl->fc_retransmit_task))
10558 {
10560 "Stopping FC retransmission to %s: peer is current at window %llu\n",
10561 GNUNET_i2s (&vl->target),
10562 (unsigned long long) wnd);
10564 vl->fc_retransmit_task = NULL;
10565 vl->fc_retransmit_count = 0;
10566 }
10568 /* FC window likely increased, check transmission possibilities! */
10570 finish_cmc_handling (cmc);
10571}

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 10654 of file gnunet-service-transport.c.

10656{
10657 struct TransportClient *tc = cls;
10658
10659 if (CT_COMMUNICATOR != tc->type)
10660 {
10661 GNUNET_break (0);
10662 return GNUNET_SYSERR;
10663 }
10665 return GNUNET_OK;
10666}

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 10675 of file gnunet-service-transport.c.

10676{
10677 if (pm->msg_uuid_set)
10678 return;
10679 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
10680 pm->msg_uuid_set = GNUNET_YES;
10681}

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 10693 of file gnunet-service-transport.c.

10696{
10697 struct PendingAcknowledgement *pa;
10698
10699 pa = GNUNET_new (struct PendingAcknowledgement);
10700 pa->queue = queue;
10701 pa->dvh = dvh;
10702 pa->pm = pm;
10703 do
10704 {
10706 &pa->ack_uuid,
10707 sizeof(pa->ack_uuid));
10708 }
10711 &pa->ack_uuid.value,
10712 pa,
10714 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
10715 GNUNET_CONTAINER_MDLL_insert (pm, pm->pa_head, pm->pa_tail, pa);
10716 if (NULL != dvh)
10719 pa->message_size = pm->bytes_msg;
10721 "Waiting for ACKnowledgment `%s' for <%" PRIu64 ">\n",
10723 pm->logging_uuid);
10724 return pa;
10725}

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 10740 of file gnunet-service-transport.c.

10743{
10744 struct PendingAcknowledgement *pa;
10745 struct PendingMessage *ff;
10746 uint16_t mtu;
10747 uint16_t msize;
10748
10749 mtu = (UINT16_MAX == queue->mtu)
10750 ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
10751 : queue->mtu;
10753 "Fragmenting message <%" PRIu64
10754 "> with size %u to %s for MTU %u\n",
10755 pm->logging_uuid,
10756 pm->bytes_msg,
10757 GNUNET_i2s (&pm->vl->target),
10758 (unsigned int) mtu);
10761 "Fragmenting message %" PRIu64 " <%" PRIu64
10762 "> with size %u to %s for MTU %u\n",
10763 pm->msg_uuid.uuid,
10764 pm->logging_uuid,
10765 pm->bytes_msg,
10766 GNUNET_i2s (&pm->vl->target),
10767 (unsigned int) mtu);
10768
10769 /* This invariant is established in #handle_add_queue_message() */
10770 GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
10771
10772 /* select fragment for transmission, descending the tree if it has
10773 been expanded until we are at a leaf or at a fragment that is small
10774 enough
10775 */
10776 ff = pm;
10777 msize = ff->bytes_msg;
10778
10779 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
10780 (ff->frag_off == msize) && (NULL != ff->head_frag))
10781 {
10782 ff = ff->head_frag; /* descent into fragmented fragments */
10783 msize = ff->bytes_msg - sizeof(struct TransportFragmentBoxMessage);
10784 }
10785
10786 if (((ff->bytes_msg > mtu) || (pm == ff)) && (ff->frag_off < msize))
10787 {
10788 /* Did not yet calculate all fragments, calculate next fragment */
10789 struct PendingMessage *frag;
10790 struct TransportFragmentBoxMessage tfb;
10791 const char *orig;
10792 char *msg;
10793 uint16_t fragmax;
10794 uint16_t fragsize;
10795 uint16_t msize_ff;
10796 uint16_t xoff = 0;
10797 pm->frag_count++;
10798
10799 orig = (const char *) &ff[1];
10800 msize_ff = ff->bytes_msg;
10801 if (pm != ff)
10802 {
10803 const struct TransportFragmentBoxMessage *tfbo;
10804
10805 tfbo = (const struct TransportFragmentBoxMessage *) orig;
10806 orig += sizeof(struct TransportFragmentBoxMessage);
10807 msize_ff -= sizeof(struct TransportFragmentBoxMessage);
10808 xoff = ntohs (tfbo->frag_off);
10809 }
10810 fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
10811 fragsize = GNUNET_MIN (msize_ff - ff->frag_off, fragmax);
10812 frag =
10813 GNUNET_malloc (sizeof(struct PendingMessage)
10814 + sizeof(struct TransportFragmentBoxMessage) + fragsize);
10816 "3 created pm %p from pm %p storing vl %p from pm %p\n",
10817 frag,
10818 ff,
10819 pm->vl,
10820 pm);
10822 frag->vl = pm->vl;
10823 frag->frag_parent = ff;
10824 frag->timeout = pm->timeout;
10825 frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
10826 frag->pmt = PMT_FRAGMENT_BOX;
10827 msg = (char *) &frag[1];
10828 tfb.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT);
10829 tfb.header.size =
10830 htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
10831 pa = prepare_pending_acknowledgement (queue, dvh, frag);
10832 tfb.ack_uuid = pa->ack_uuid;
10833 tfb.msg_uuid = pm->msg_uuid;
10834 tfb.frag_off = htons (ff->frag_off + xoff);
10835 tfb.msg_size = htons (pm->bytes_msg);
10836 memcpy (msg, &tfb, sizeof(tfb));
10837 memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
10839 ff->tail_frag, frag);
10840 ff->frag_off += fragsize;
10841 ff = frag;
10842 }
10843
10844 /* Move head to the tail and return it */
10848 ff);
10852 ff);
10853
10854 return ff;
10855}

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 10871 of file gnunet-service-transport.c.

10874{
10876 struct PendingAcknowledgement *pa;
10877 struct PendingMessage *bpm;
10878 char *msg;
10879
10880 if ((PMT_CORE != pm->pmt) && (PMT_DV_BOX != pm->pmt))
10881 return pm; /* already fragmented or reliability boxed, or control message:
10882 do nothing */
10883 if (NULL != pm->bpm)
10884 return pm->bpm; /* already computed earlier: do nothing */
10885 // TODO I guess we do not need this assertion. We might have a DLL with
10886 // fragments, because the MTU changed, and we do not need to fragment anymore.
10887 // But we should keep the fragments until message was completed, because
10888 // the MTU might change again.
10889 // GNUNET_assert (NULL == pm->head_frag);
10890 if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
10891 {
10892 /* failed hard */
10893 GNUNET_break (0);
10895 return NULL;
10896 }
10897
10899
10900 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
10901 + pm->bytes_msg);
10903 "4 created pm %p storing vl %p from pm %p\n",
10904 bpm,
10905 pm->vl,
10906 pm);
10908 bpm->vl = pm->vl;
10909 bpm->frag_parent = pm;
10910 // Why was this needed?
10911 // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
10912 bpm->timeout = pm->timeout;
10914 bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
10916 rbox.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX);
10917 rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
10918 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
10919
10920 rbox.ack_uuid = pa->ack_uuid;
10921 msg = (char *) &bpm[1];
10922 memcpy (msg, &rbox, sizeof(rbox));
10923 memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
10924 pm->bpm = bpm;
10926 "Preparing reliability box for message <%" PRIu64
10927 "> of size %d (%d) to %s on queue %s\n",
10928 pm->logging_uuid,
10929 pm->bytes_msg,
10930 ntohs (((const struct GNUNET_MessageHeader *) &pm[1])->size),
10931 GNUNET_i2s (&pm->vl->target),
10932 queue->address);
10933 return bpm;
10934}

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 10938 of file gnunet-service-transport.c.

10940{
10941 struct VirtualLink *vl = pm->vl;
10942 struct PendingMessage *pos;
10943
10944 /* re-insert sort in neighbour list */
10948 pm);
10949 pos = vl->pending_msg_tail;
10950 while ((NULL != pos) &&
10952 pos = pos->prev_vl;
10956 pos,
10957 pm);
10958}

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 10962 of file gnunet-service-transport.c.

10963{
10964 struct PendingMessage *pos;
10966
10967 pos = pm->head_frag;
10968 while (NULL != pos)
10969 {
10970 if (pos->frags_in_flight_round == pm->frags_in_flight_round ||
10971 GNUNET_NO == check_next_attempt_tree (pos, root))
10973 else
10974 {
10976 break;
10977 }
10978 pos = pos->next_frag;
10979 }
10980
10981 return frags_in_flight;
10982}

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 10986 of file gnunet-service-transport.c.

10987{
10988 struct PendingMessage *pos;
10989
10990 pos = pm->head_frag;
10991 while (NULL != pos)
10992 {
10993 pos->frags_in_flight_round = pm->frags_in_flight_round;
10995 pos = pos->next_frag;
10996 }
10997}

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 11009 of file gnunet-service-transport.c.

11011{
11012 if (NULL == pm->frag_parent)
11013 {
11014 pm->next_attempt = next_attempt;
11016 "Next attempt for message <%" PRIu64 "> set to %" PRIu64 "\n",
11017 pm->logging_uuid,
11018 next_attempt.abs_value_us);
11019 reorder_root_pm (pm, next_attempt);
11020 }
11021 else if ((PMT_RELIABILITY_BOX == pm->pmt) || (PMT_DV_BOX == pm->pmt))// || (PMT_FRAGMENT_BOX == pm->pmt))
11022 {
11023 struct PendingMessage *root = pm->frag_parent;
11024
11025 while (NULL != root->frag_parent)
11026 root = root->frag_parent;
11028 "Next attempt for root message <%" PRIu64 "> set to %s\n",
11029 root->logging_uuid,
11031 root->next_attempt = next_attempt;
11033 }
11034 else
11035 {
11036 struct PendingMessage *root = pm->frag_parent;
11037
11038 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11039 root = root->frag_parent;
11040
11042 "frag_count next attempt %u\n",
11043 root->frag_count);
11044
11045 if (GNUNET_NO == root->frags_in_flight)
11046 {
11047 root->next_attempt = next_attempt;
11049 root->frags_in_flight_round++;
11051 "Next attempt for fragmented message <%" PRIu64 "> (<%" PRIu64
11052 ">)set to %" PRIu64 "\n",
11053 pm->logging_uuid,
11054 root->logging_uuid,
11056 }
11057
11058 pm->next_attempt = root->next_attempt;
11059 pm->frags_in_flight_round = root->frags_in_flight_round;
11061
11062 if (root->bytes_msg == root->frag_off)
11063 root->frags_in_flight = check_next_attempt_tree (root, root);
11064 else
11066
11067 if (GNUNET_NO == root->frags_in_flight)
11068 {
11070 "We have no fragments in flight for message %" PRIu64
11071 ", reorder root! Next attempt is %" PRIu64 "\n",
11072 root->logging_uuid,
11074 if (PMT_DV_BOX == root->pmt)
11075 root = root->frag_parent;
11076 reorder_root_pm (root, root->next_attempt);
11077 // root->next_attempt = GNUNET_TIME_UNIT_ZERO_ABS;
11078 }
11079 else
11080 {
11081 double factor = ((double) root->frag_count - 1)
11082 / (double) root->frag_count;
11083 struct GNUNET_TIME_Relative s1;
11084 struct GNUNET_TIME_Relative s2;
11085 struct GNUNET_TIME_Relative plus_mean =
11088 next_attempt);
11089
11091 "frag_count %u after factor\n",
11092 root->frag_count);
11094 factor);
11095 s2 = GNUNET_TIME_relative_divide (plus,
11096 root->frag_count);
11097 plus_mean = GNUNET_TIME_relative_add (s1, s2);
11100 "We have fragments in flight for message %" PRIu64
11101 ", do not reorder root! Actual next attempt %" PRIu64 "\n",
11102 root->logging_uuid,
11104 }
11105 }
11106}

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 11173 of file gnunet-service-transport.c.

11178{
11179 struct GNUNET_TIME_Absolute now;
11180
11181 now = GNUNET_TIME_absolute_get ();
11182 sc->to_early = GNUNET_NO;
11183 sc->frags_in_flight = GNUNET_NO;
11184 for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
11185 pos = pos->next_vl)
11186 {
11187 size_t real_overhead = overhead;
11188 int frag;
11189 int relb;
11190
11191 if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
11192 {
11194 "DV messages must not be DV-routed to next hop!\n");
11195 continue; /* DV messages must not be DV-routed to next hop! */
11196 }
11197 if (pos->next_attempt.abs_value_us > now.abs_value_us)
11198 {
11199 if (GNUNET_YES == pos->frags_in_flight)
11200 {
11201 sc->frags_in_flight = GNUNET_YES;
11203 "Fragments in flight for message %" PRIu64 "\n",
11204 pos->logging_uuid);
11205 }
11206 else
11207 {
11209 "Maybe too early, because message are sorted by next_attempt, if there are no fragments in flight.Checked message %"
11210 PRIu64 "\n",
11211 pos->logging_uuid);
11212 sc->to_early = GNUNET_YES;
11213 sc->to_early_retry_delay = GNUNET_TIME_absolute_get_remaining (
11214 pos->next_attempt);
11215 continue;
11216 }
11217 // break; /* too early for all messages, they are sorted by next_attempt */
11218 }
11219 if (NULL != pos->qe)
11220 {
11222 "not eligible\n");
11223 continue; /* not eligible */
11224 }
11225 sc->consideration_counter++;
11226 /* determine if we have to fragment, if so add fragmentation
11227 overhead! */
11229 "check %" PRIu64 " for sc->best\n",
11230 pos->logging_uuid);
11231 frag = GNUNET_NO;
11232 if (((0 != queue->mtu) &&
11233 (pos->bytes_msg + real_overhead > queue->mtu)) ||
11234 (pos->bytes_msg > UINT16_MAX - sizeof(struct
11236 ||
11237 (NULL != pos->head_frag /* fragments already exist, should
11238 respect that even if MTU is UINT16_MAX for
11239 this queue */))
11240 {
11242 "fragment msg with size %u, realoverhead is %lu\n",
11243 pos->bytes_msg,
11244 real_overhead);
11245 frag = GNUNET_YES;
11246 if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
11247 {
11248 /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
11249 header without the ACK UUID when using a *reliable* channel! */
11250 }
11251 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11252 }
11253 /* determine if we have to reliability-box, if so add reliability box
11254 overhead */
11255 relb = GNUNET_NO;
11256 if ((GNUNET_NO == frag) &&
11257 (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
11258 (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
11259 {
11260 real_overhead += sizeof(struct TransportReliabilityBoxMessage);
11261
11262 if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu))
11263 {
11264 frag = GNUNET_YES;
11265 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11266 }
11267 else
11268 {
11269 relb = GNUNET_YES;
11270 }
11272 "Create reliability box of msg with size %u, realoverhead is %lu %u %u %u\n",
11273 pos->bytes_msg,
11274 real_overhead,
11275 queue->mtu,
11276 frag,
11277 relb);
11278 }
11279
11280 /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
11281 message would beat it! */
11282 if (GNUNET_NO == sc->frags_in_flight && NULL != sc->best)
11283 {
11284 /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
11285 OPTIMIZE-ME: This is a heuristic, which so far has NOT been
11286 experimentally validated. There may be some huge potential for
11287 improvement here. Also, we right now only compare how well the
11288 given message fits _this_ queue, and do not consider how well other
11289 queues might suit the message. Taking other queues into consideration
11290 may further improve the result, but could also be expensive
11291 in terms of CPU time. */
11292 long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
11293 long long pm_score = frag * 40 + relb * 20 + real_overhead;
11294 long long time_delta =
11295 (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
11296 / 1000LL;
11297
11298 /* "time_delta" considers which message has been 'ready' for transmission
11299 for longer, if a message has a preference for low latency, increase
11300 the weight of the time_delta by 10x if it is favorable for that message */
11301 if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11302 (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
11303 time_delta *= 10; /* increase weight (always, both are low latency) */
11304 else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11305 (time_delta > 0))
11306 time_delta *= 10; /* increase weight, favors 'pos', which is low latency */
11307 else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11308 (time_delta < 0))
11309 time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */
11310 if (0 != queue->mtu)
11311 {
11312 /* Grant bonus if we are below MTU, larger bonus the closer we will
11313 be to the MTU */
11314 if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
11315 sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
11316 if (queue->mtu > real_overhead + pos->bytes_msg)
11317 pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
11318 }
11319 if (sc_score + time_delta > pm_score)
11320 {
11322 "sc_score of %" PRIu64 " larger, keep sc->best %" PRIu64
11323 "\n",
11324 pos->logging_uuid,
11325 sc->best->logging_uuid);
11326 continue; /* sc_score larger, keep sc->best */
11327 }
11328 }
11329 sc->best = pos;
11330 sc->dvh = dvh;
11331 sc->frag = frag;
11332 sc->relb = relb;
11333 sc->real_overhead = real_overhead;
11334 }
11335}

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 11349 of file gnunet-service-transport.c.

11353{
11354 struct PendingMessageScoreContext *sc = cls;
11355 struct PendingMessage *pm = sc->best;
11356 struct PendingMessage *bpm;
11357 uint16_t bsize = ntohs (hdr->size);
11358
11359 GNUNET_assert (NULL == pm->bpm);
11360 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
11362 "5 created pm %p storing vl %p from pm %p\n",
11363 bpm,
11364 pm->vl,
11365 pm);
11367 bpm->pmt = PMT_DV_BOX;
11368 bpm->vl = pm->vl;
11369 bpm->timeout = pm->timeout;
11370 bpm->bytes_msg = bsize;
11371 bpm->frag_parent = pm;
11374 "Creating DV Box %" PRIu64 " for original message %" PRIu64
11375 " (next hop is %s)\n",
11377 pm->logging_uuid,
11378 GNUNET_i2s (&next_hop->pid));
11379 memcpy (&bpm[1], hdr, bsize);
11380 pm->bpm = bpm;
11381}

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 11656 of file gnunet-service-transport.c.

11658{
11659 struct TransportClient *tc = cls;
11660
11661 if (CT_COMMUNICATOR != tc->type)
11662 {
11663 GNUNET_break (0);
11665 return;
11666 }
11667 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11668 queue = queue->next_client)
11669 {
11670 struct Neighbour *neighbour = queue->neighbour;
11671
11672 if ((ntohl (dqm->qid) != queue->qid) ||
11673 (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
11674 continue;
11676 "Dropped queue %s to peer %s\n",
11677 queue->address,
11678 GNUNET_i2s (&neighbour->pid));
11679 free_queue (queue);
11681 return;
11682 }
11683 GNUNET_break (0);
11685}

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 11786 of file gnunet-service-transport.c.

11788{
11789 struct TransportClient *tc = cls;
11790 struct QueueEntry *qe;
11791
11792 if (CT_COMMUNICATOR != tc->type)
11793 {
11794 GNUNET_break (0);
11796 return;
11797 }
11798
11799 /* find our queue entry matching the ACK */
11800 qe = NULL;
11802 "Looking for queue for PID %s\n",
11803 GNUNET_i2s (&sma->receiver));
11804 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11805 queue = queue->next_client)
11806 {
11807 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
11808 continue;
11810 "Found PID %s\n",
11811 GNUNET_i2s (&queue->neighbour->pid));
11812
11813
11814 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
11815 qep = qep->next)
11816 {
11817 if (qep->mid != GNUNET_ntohll (sma->mid) || queue->qid != ntohl (
11818 sma->qid))
11819 continue;
11821 "QueueEntry MID: %" PRIu64 " on queue QID: %u, Ack MID: %"
11822 PRIu64 " Ack QID %u\n",
11823 qep->mid,
11824 queue->qid,
11825 GNUNET_ntohll (sma->mid),
11826 ntohl (sma->qid));
11827 qe = qep;
11828 if ((NULL != qe->pm) && (qe->pm->qe != qe))
11830 "For pending message %" PRIu64 " we had retransmissions.\n",
11831 qe->pm->logging_uuid);
11832 break;
11833 }
11834 }
11835 if (NULL == qe)
11836 {
11838 "No QueueEntry found for Ack MID %" PRIu64 " QID: %u\n",
11839 GNUNET_ntohll (sma->mid),
11840 ntohl (sma->qid));
11841 // TODO I guess this can happen, if the Ack from the peer comes before the Ack from the queue.
11842 // Update: Maybe QueueEntry was accidentally freed during freeing PendingMessage.
11843 /* this should never happen */
11844 // GNUNET_break (0);
11845 // GNUNET_SERVICE_client_drop (tc->client);
11847 return;
11848 }
11851}

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 11860 of file gnunet-service-transport.c.

11862{
11864}

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 11877 of file gnunet-service-transport.c.

11880{
11881 struct TransportClient *tc = cls;
11882 struct Neighbour *neighbour = value;
11883
11884 GNUNET_assert (CT_MONITOR == tc->type);
11885 for (struct Queue *q = neighbour->queue_head; NULL != q;
11886 q = q->next_neighbour)
11887 {
11888 struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
11889 .cs = q->cs,
11890 .num_msg_pending = q->num_msg_pending,
11891 .num_bytes_pending = q->num_bytes_pending };
11892
11893 notify_monitor (tc, pid, q->address, q->nt, &me);
11894 }
11895 return GNUNET_OK;
11896}

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 11906 of file gnunet-service-transport.c.

11908{
11909 struct TransportClient *tc = cls;
11910
11911 if (CT_NONE != tc->type)
11912 {
11913 GNUNET_break (0);
11915 return;
11916 }
11917 tc->type = CT_MONITOR;
11918 tc->details.monitor.peer = start->peer;
11919 tc->details.monitor.one_shot = ntohl (start->one_shot);
11923}

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 11934 of file gnunet-service-transport.c.

11935{
11936 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
11937 {
11938 if (CT_COMMUNICATOR != tc->type)
11939 continue;
11940 if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
11941 return tc;
11942 }
11943 GNUNET_log (
11945 "Someone suggested use of communicator for `%s', but we do not have such a communicator!\n",
11946 prefix);
11947 return NULL;
11948}

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 12160 of file gnunet-service-transport.c.

12163{
12164 struct QueueQualityContext *ctx = cls;
12165 struct Neighbour *n = value;
12166 int do_inc;
12167
12168 (void) pid;
12169 do_inc = GNUNET_NO;
12170 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
12171 {
12172 ctx->num_queues++;
12173 if (0 == ctx->k--)
12174 ctx->q = q;
12175 /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
12176 statistics and consider those as well here? */
12177 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
12178 do_inc = GNUNET_YES;
12179 }
12180 if (GNUNET_YES == do_inc)
12181 ctx->quality_count++;
12182 return GNUNET_OK;
12183}

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 12264 of file gnunet-service-transport.c.

12265{
12266 struct LearnLaunchEntry *lle;
12267 struct QueueQualityContext qqc;
12268 struct TransportDVLearnMessage dvl;
12269
12270 (void) cls;
12271 dvlearn_task = NULL;
12273 return; /* lost all connectivity, cannot do learning */
12274 qqc.quality_count = 0;
12275 qqc.num_queues = 0;
12279 &qqc);
12280 if (qqc.quality_count > DV_LEARN_QUALITY_THRESHOLD)
12281 {
12282 struct GNUNET_TIME_Relative delay;
12283 unsigned int factor;
12284
12285 /* scale our retries by how far we are above the threshold */
12286 factor = qqc.quality_count / DV_LEARN_QUALITY_THRESHOLD;
12289 "At connection quality %u, will launch DV learn in %s\n",
12290 qqc.quality_count,
12293 return;
12294 }
12295 /* remove old entries in #dvlearn_map if it has grown too big */
12296 while (MAX_DV_LEARN_PENDING <=
12298 {
12299 lle = lle_tail;
12302 &lle->challenge.value,
12303 lle));
12305 GNUNET_free (lle);
12306 }
12307 /* setup data structure for learning */
12308 lle = GNUNET_new (struct LearnLaunchEntry);
12310 &lle->challenge,
12311 sizeof(lle->challenge));
12313 "Starting launch DV learn with challenge %s\n",
12314 GNUNET_sh2s (&lle->challenge.value));
12319 &lle->challenge.value,
12320 lle,
12322 dvl.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN);
12323 dvl.header.size = htons (sizeof(dvl));
12324 dvl.num_hops = htons (0);
12325 dvl.bidirectional = htons (0);
12326 dvl.non_network_delay = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO);
12327 dvl.monotonic_time =
12329 // We will set the below again later
12330 memset (&dvl.init_sig, 0, sizeof dvl.init_sig);
12331 dvl.challenge = lle->challenge;
12332 dvl.initiator = *GST_my_identity;
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, TransportDVLearnMessage::challenge, 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, GST_my_identity, TransportDVLearnMessage::header, TransportDVLearnMessage::init_sig, TransportDVLearnMessage::initiator, 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_SignaturePurpose::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 12211 of file gnunet-service-transport.c.

12214{
12215 struct SignDvInitCls *sign_dv_init_cls = cls;
12216 struct TransportDVLearnMessage dvl = sign_dv_init_cls->dvl;
12217 struct LearnLaunchEntry *lle = sign_dv_init_cls->lle;
12218 struct QueueQualityContext qqc = sign_dv_init_cls->qqc;
12219
12220 sign_dv_init_cls->pr->op = NULL;
12223 sign_dv_init_cls->pr);
12224 GNUNET_free (sign_dv_init_cls->pr);
12225
12226 dvl.init_sig = *sig;
12228 dvl.challenge = lle->challenge;
12229
12230 qqc.quality_count = 0;
12232 qqc.num_queues = 0;
12233 qqc.q = NULL;
12236 &qqc);
12237 GNUNET_assert (NULL != qqc.q);
12238
12239 /* Do this as close to transmission time as possible! */
12241
12242 queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
12243 /* reschedule this job, randomizing the time it runs (but no
12244 actual backoff!) */
12248 NULL);
12249}

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 retu