GNUnet 0.28.0-dev.3-7-g31e20e2e6
 
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  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 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 const char * get_client_type_name (enum ClientType type)
 
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.
 
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 90 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 95 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 101 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 115 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 121 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 127 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 133 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 143 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 149 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 159 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 168 of file gnunet-service-transport.c.

◆ MAX_DV_HOPS_ALLOWED

#define MAX_DV_HOPS_ALLOWED   16

Maximum DV distance allowed ever.

Definition at line 173 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 179 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 184 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 192 of file gnunet-service-transport.c.

351{
356 uint64_t uuid GNUNET_PACKED;
357};
358
359
364{
368 struct GNUNET_Uuid value;
369};
370
375{
380
381 /* Followed by *another* message header which is the message to
382 the communicator */
383
384 /* Followed by a 0-terminated name of the communicator */
385};
386
387
392{
397
413
418
424};
425
426
432{
437
443
455
456 /* Followed by a `struct GNUNET_MessageHeader` with a message
457 for the target peer */
458};
459
460
466{
471
479
486};
487
488
493{
501
506};
507
508
517{
522
527 uint32_t ack_counter GNUNET_PACKED;
528
529 /* followed by any number of `struct TransportCummulativeAckPayloadP`
530 messages providing ACKs */
531};
532
533
538{
543
547 uint16_t frag_off GNUNET_PACKED;
548
552 uint16_t msg_size GNUNET_PACKED;
553
562
567 struct MessageUUIDP msg_uuid;
568};
569
570
588struct DvInitPS
589{
594
608
613};
614
615
632struct DvHopPS
633{
638
643
648
653};
654
655
660struct DVPathEntryP
661{
666
672};
673
674
689{
694
699 uint16_t num_hops GNUNET_PACKED;
700
710
717
731
737
742
747
748 /* Followed by @e num_hops `struct DVPathEntryP` values,
749 excluding the initiator of the DV trace; the last entry is the
750 current sender; the current peer must not be included. */
751};
752
753
777{
782
786 unsigned int without_fc;
787
794 uint16_t total_hops GNUNET_PACKED;
795
801 uint16_t num_hops GNUNET_PACKED;
802
808
815
822
828 uint16_t orig_size GNUNET_PACKED;
829
830 /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values;
831 excluding the @e origin and the current peer, the last must be
832 the ultimate target; if @e num_hops is zero, the receiver of this
833 message is the ultimate target. */
834
835 /* Followed by encrypted, variable-size payload, which
836 must begin with a `struct TransportDVBoxPayloadP` */
837
838 /* Followed by the actual message, which itself must not be a
839 a DV_LEARN or DV_BOX message! */
840};
841
842
848{
853
857 uint32_t reserved GNUNET_PACKED;
858
863
869};
870
871
877{
882
888
893};
894
895
901{
906
910 uint32_t reserved GNUNET_PACKED;
911
917
922
927 struct GNUNET_TIME_AbsoluteNBO origin_time;
928
933 struct GNUNET_TIME_RelativeNBO validity_duration;
934};
935
937{
941 unsigned int address_length;
942
943 /* Followed by @e address_length bytes of the address. */
944};
945
955{
960
968 uint32_t seq GNUNET_PACKED;
969
975
982
992
1002
1007
1011 unsigned int sync_ready;
1012
1016 unsigned int number_of_addresses;
1017
1021 size_t size_of_addresses;
1022
1023 /* Followed by @e number_of_addresses struct TransportGlobalNattedAddress. */
1024};
1025
1027
1028
1032enum ClientType
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};
1059
1060
1066{
1070 RMO_NONE = 0,
1071
1075 RMO_DV_ALLOWED = 1,
1076
1081
1086
1092 RMO_REDUNDANT = 4
1093};
1094
1095
1099struct LearnLaunchEntry
1100{
1104 struct LearnLaunchEntry *prev;
1105
1109 struct LearnLaunchEntry *next;
1110
1115
1121};
1122
1123
1129{
1133 uint64_t bytes_sent;
1134
1139 uint64_t bytes_received;
1140};
1141
1142
1146struct PerformanceData
1147{
1152
1158
1163 unsigned int last_age;
1164};
1165
1166
1170struct TransportClient;
1171
1175struct Neighbour;
1176
1181struct DistanceVector;
1182
1187struct Queue;
1188
1192struct PendingMessage;
1193
1197struct DistanceVectorHop;
1198
1207struct VirtualLink;
1208
1209
1215{
1221
1227
1231 struct TransportClient *tc;
1232
1237
1241 const struct GNUNET_MessageHeader *mh;
1242
1247 uint16_t total_hops;
1248
1252 unsigned int continue_send;
1253};
1254
1255
1259struct RingBufferEntry
1260{
1265
1269 struct GNUNET_MessageHeader *mh;
1270};
1271
1272
1276struct CoreSentContext
1277{
1281 struct CoreSentContext *next;
1282
1286 struct CoreSentContext *prev;
1287
1291 struct VirtualLink *vl;
1292
1296 uint16_t size;
1297
1304 uint16_t isize;
1305};
1306
1307
1311struct ReassemblyContext
1312{
1317 struct MessageUUIDP msg_uuid;
1318
1322 struct VirtualLink *virtual_link;
1323
1328
1336 uint8_t *bitfield;
1337
1342
1348
1352 uint16_t msg_size;
1353
1358 uint16_t msg_missing;
1359
1360 /* Followed by @e msg_size bytes of the (partially) defragmented original
1361 * message */
1362
1363 /* Followed by @e bitfield data */
1364};
1365
1366
1375struct VirtualLink
1376{
1381
1388
1395
1400
1406
1412
1417
1422
1426 struct CoreSentContext *csc_tail;
1427
1431 struct CoreSentContext *csc_head;
1432
1440
1446
1451
1455 char *burst_addr;
1456
1460 unsigned int fc_retransmit_count;
1461
1466 unsigned int confirmed;
1467
1471 struct Neighbour *n;
1472
1476 struct DistanceVector *dv;
1477
1484
1491
1500
1506
1512
1517
1522 uint64_t message_uuid_ctr;
1523
1531 uint64_t available_fc_window_size;
1532
1540
1546 uint64_t incoming_fc_window_size;
1547
1556
1569
1574 uint64_t outbound_fc_window_size;
1575
1582
1593
1598 uint32_t fc_seq_gen;
1599
1605 uint32_t last_fc_seq;
1606
1618 int core_recv_window;
1619
1624};
1625
1626
1631{
1637
1643
1650
1657
1664
1671
1678
1685
1690
1695 struct PendingMessage *pm;
1696
1701 struct DistanceVectorHop *dvh;
1702
1707 struct Queue *queue;
1708
1713
1717 uint16_t message_size;
1718
1722 unsigned int num_send;
1723};
1724
1725
1729struct DistanceVectorHop
1730{
1734 struct DistanceVectorHop *next_dv;
1735
1739 struct DistanceVectorHop *prev_dv;
1740
1745
1750
1755
1760
1764 struct Neighbour *next_hop;
1765
1769 struct DistanceVector *dv;
1770
1776 const struct GNUNET_PeerIdentity *path;
1777
1783
1792
1796 struct PerformanceData pd;
1797
1803 unsigned int distance;
1804};
1805
1806
1811struct DistanceVector
1812{
1817
1821 struct DistanceVectorHop *dv_head;
1822
1826 struct DistanceVectorHop *dv_tail;
1827
1832
1837 struct VirtualLink *vl;
1838
1844
1849
1854
1859
1863 struct GNUNET_ShortHashCode *km;
1864};
1865
1866
1876struct QueueEntry
1877{
1881 struct QueueEntry *next;
1882
1886 struct QueueEntry *prev;
1887
1891 struct Queue *queue;
1892
1896 struct PendingMessage *pm;
1897
1901 uint64_t mid;
1902
1907};
1908
1909
1914struct Queue
1915{
1919 struct Queue *next_neighbour;
1920
1924 struct Queue *prev_neighbour;
1925
1929 struct Queue *prev_client;
1930
1934 struct Queue *next_client;
1935
1940
1945
1949 struct QueueEntry *queue_head;
1950
1954 struct QueueEntry *queue_tail;
1955
1959 struct Neighbour *neighbour;
1960
1964 struct TransportClient *tc;
1965
1969 const char *address;
1970
1974 unsigned int unlimited_length;
1975
1981
1990
1994 struct PerformanceData pd;
1995
2001
2006 uint64_t mid_gen;
2007
2011 uint32_t qid;
2012
2016 uint32_t mtu;
2017
2021 uint32_t num_msg_pending;
2022
2026 uint32_t num_bytes_pending;
2027
2031 unsigned int queue_length;
2032
2036 uint64_t q_capacity;
2037
2041 uint32_t priority;
2042
2047
2052
2057 int idle;
2058
2063};
2064
2065
2069struct Neighbour
2070{
2074 struct GNUNET_PeerIdentity pid;
2075
2080 struct DistanceVectorHop *dv_head;
2081
2086 struct DistanceVectorHop *dv_tail;
2087
2091 struct Queue *queue_head;
2092
2096 struct Queue *queue_tail;
2097
2103
2109
2114 struct VirtualLink *vl;
2115
2121
2127
2132
2136 unsigned int number_of_addresses;
2137
2142
2147};
2148
2149
2154struct IncomingRequest
2155{
2159 struct IncomingRequest *next;
2160
2164 struct IncomingRequest *prev;
2165
2170
2174 struct GNUNET_PeerIdentity pid;
2175};
2176
2177
2181struct PeerRequest
2182{
2186 struct GNUNET_PeerIdentity pid;
2187
2191 struct TransportClient *tc;
2192
2197
2204
2209};
2210
2211
2216{
2220 PMT_CORE = 0,
2221
2225 PMT_FRAGMENT_BOX = 1,
2226
2231
2235 PMT_DV_BOX = 3
2236};
2237
2238
2265struct PendingMessage
2266{
2270 struct PendingMessage *next_vl;
2271
2275 struct PendingMessage *prev_vl;
2276
2281
2286
2291 struct PendingMessage *next_frag;
2292
2297 struct PendingMessage *prev_frag;
2298
2303
2308
2313 struct PendingMessage *bpm;
2314
2319 struct VirtualLink *vl;
2320
2325
2334 struct QueueEntry *qe;
2335
2339 struct TransportClient *client;
2340
2344 struct PendingMessage *head_frag;
2345
2349 struct PendingMessage *tail_frag;
2350
2355
2360
2365
2370 struct MessageUUIDP msg_uuid;
2371
2376 uint64_t logging_uuid;
2377
2382
2388
2393
2397 uint16_t bytes_msg;
2398
2402 uint16_t frag_off;
2403
2407 uint32_t frags_in_flight;
2408
2412 uint32_t frags_in_flight_round;
2413
2417 uint16_t frag_count;
2418
2422 int16_t msg_uuid_set;
2423
2424 /* Followed by @e bytes_msg to transmit */
2425};
2426
2427
2432{
2438
2443};
2444
2445
2451{
2456
2461
2468
2473
2479 uint32_t ack_counter;
2480
2484 unsigned int num_acks;
2485};
2486
2487
2491struct AddressListEntry
2492{
2496 struct AddressListEntry *next;
2497
2501 struct AddressListEntry *prev;
2502
2506 struct TransportClient *tc;
2507
2512
2516 const char *address;
2517
2521 void *signed_address;
2522
2526 size_t signed_address_len;
2527
2532
2536 struct GNUNET_SCHEDULER_Task *st;
2537
2543
2547 uint32_t aid;
2548
2553};
2554
2555
2559struct TransportClient
2560{
2564 struct TransportClient *next;
2565
2569 struct TransportClient *prev;
2570
2575
2579 struct GNUNET_MQ_Handle *mq;
2580
2584 enum ClientType type;
2585
2586 union
2587 {
2591 struct
2592 {
2598
2603 } core;
2604
2608 struct
2609 {
2616
2620 int one_shot;
2621 } monitor;
2622
2623
2627 struct
2628 {
2633 char *address_prefix;
2634
2638 struct Queue *queue_head;
2639
2643 struct Queue *queue_tail;
2644
2650
2656
2662 unsigned int total_queue_length;
2663
2668
2673
2678
2679 } communicator;
2680
2684 struct
2685 {
2691 } application;
2692 } details;
2693};
2694
2695
2700struct ValidationState
2701{
2706 struct GNUNET_PeerIdentity pid;
2707
2715
2721
2728 struct GNUNET_TIME_Absolute first_challenge_use;
2729
2736 struct GNUNET_TIME_Absolute last_challenge_use;
2737
2745 struct GNUNET_TIME_Absolute next_challenge;
2746
2755 struct GNUNET_TIME_Relative challenge_backoff;
2756
2761 struct GNUNET_TIME_Relative validation_rtt;
2762
2770 struct GNUNET_CRYPTO_ChallengeNonceP challenge;
2771
2775 struct GNUNET_HashCode hc;
2776
2780 struct GNUNET_SCHEDULER_Task *revalidation_task;
2781
2785 char *address;
2786
2792 struct GNUNET_CONTAINER_HeapNode *hn;
2793
2799
2805 uint32_t last_window_consum_limit;
2806
2811 int awaiting_queue;
2812};
2813
2814
2821struct Backtalker
2822{
2826 struct GNUNET_PeerIdentity pid;
2827
2832
2837
2842
2848
2853
2859
2865
2870 size_t body_size;
2871};
2872
2877
2881static unsigned int ring_buffer_head;
2882
2886static unsigned int is_ring_buffer_full;
2887
2892
2896static unsigned int ring_buffer_dv_head;
2897
2901static unsigned int is_ring_buffer_dv_full;
2902
2906static struct TransportClient *clients_head;
2907
2911static struct TransportClient *clients_tail;
2912
2916static struct GNUNET_STATISTICS_Handle *GST_stats;
2917
2921static const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
2922
2927
2933
2939
2945
2951
2957
2963
2969
2975
2980
2984static struct LearnLaunchEntry *lle_head = NULL;
2985
2989static struct LearnLaunchEntry *lle_tail = NULL;
2990
2997
3001struct GNUNET_NAT_Handle *nh;
3002
3006static struct GNUNET_PEERSTORE_Handle *peerstore;
3007
3011static struct GNUNET_PILS_Handle *pils;
3012
3016struct PilsRequest
3017{
3021 struct PilsRequest *prev;
3022
3026 struct PilsRequest *next;
3027
3031 struct GNUNET_PILS_Operation *op;
3032};
3033
3037static struct PilsRequest *pils_requests_head;
3038
3042static struct PilsRequest *pils_requests_tail;
3043
3047static struct GNUNET_SCHEDULER_Task *dvlearn_task;
3048
3053
3058
3064static struct IncomingRequest *ir_head;
3065
3069static struct IncomingRequest *ir_tail;
3070
3074static unsigned int ir_total;
3075
3079static unsigned long long logging_uuid_gen;
3080
3085
3095
3100static int in_shutdown;
3101
3105static struct GNUNET_SCHEDULER_Task *burst_task;
3106
3108
3110
3121static unsigned int
3122get_age ()
3123{
3124 struct GNUNET_TIME_Absolute now;
3125
3126 now = GNUNET_TIME_absolute_get ();
3127 return now.abs_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us / 15;
3128}
3129
3130
3136static void
3138{
3140 GNUNET_assert (ir_total > 0);
3141 ir_total--;
3142 if (NULL != ir->nc)
3144 ir->nc = NULL;
3145 GNUNET_free (ir);
3146}
3147
3148
3154static void
3156{
3157 struct Queue *q = pa->queue;
3158 struct PendingMessage *pm = pa->pm;
3159 struct DistanceVectorHop *dvh = pa->dvh;
3160
3162 "free_pending_acknowledgement\n");
3163 if (NULL != q)
3164 {
3165 GNUNET_CONTAINER_MDLL_remove (queue, q->pa_head, q->pa_tail, pa);
3166 pa->queue = NULL;
3167 }
3168 if (NULL != pm)
3169 {
3171 "remove pa from message\n");
3173 "remove pa from message %" PRIu64 "\n",
3174 pm->logging_uuid);
3176 "remove pa from message %u\n",
3177 pm->pmt);
3179 "remove pa from message %s\n",
3181 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3182 pa->pm = NULL;
3183 }
3184 if (NULL != dvh)
3185 {
3186 GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
3187 pa->queue = NULL;
3188 }
3191 &pa->ack_uuid.value,
3192 pa));
3193 GNUNET_free (pa);
3194}
3195
3196
3205static void
3207{
3208 struct PendingMessage *frag;
3209
3210 while (NULL != (frag = root->head_frag))
3211 {
3212 struct PendingAcknowledgement *pa;
3213
3214 free_fragment_tree (frag);
3215 while (NULL != (pa = frag->pa_head))
3216 {
3217 GNUNET_CONTAINER_MDLL_remove (pm, frag->pa_head, frag->pa_tail, pa);
3218 pa->pm = NULL;
3219 }
3220 GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag);
3221 if (NULL != frag->qe)
3222 {
3223 GNUNET_assert (frag == frag->qe->pm);
3224 frag->qe->pm = NULL;
3225 }
3227 "Free frag %p\n",
3228 frag);
3229 GNUNET_free (frag);
3230 }
3231}
3232
3233
3241static void
3243{
3244 struct TransportClient *tc = pm->client;
3245 struct VirtualLink *vl = pm->vl;
3246 struct PendingAcknowledgement *pa;
3247
3249 "Freeing pm %p\n",
3250 pm);
3251 if (NULL != tc)
3252 {
3254 tc->details.core.pending_msg_head,
3255 tc->details.core.pending_msg_tail,
3256 pm);
3257 }
3258 if ((NULL != vl) && (NULL == pm->frag_parent))
3259 {
3261 "Removing pm %" PRIu64 "\n",
3262 pm->logging_uuid);
3264 vl->pending_msg_head,
3265 vl->pending_msg_tail,
3266 pm);
3267 }
3268 else if (NULL != pm->frag_parent && PMT_DV_BOX != pm->pmt)
3269 {
3270 struct PendingMessage *root = pm->frag_parent;
3271
3272 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
3273 root = root->frag_parent;
3274
3275 root->frag_count--;
3276 }
3277 while (NULL != (pa = pm->pa_head))
3278 {
3279 if (NULL == pa)
3281 "free pending pa null\n");
3282 if (NULL == pm->pa_tail)
3284 "free pending pa_tail null\n");
3285 if (NULL == pa->prev_pa)
3287 "free pending pa prev null\n");
3288 if (NULL == pa->next_pa)
3290 "free pending pa next null\n");
3291 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3292 pa->pm = NULL;
3293 }
3294
3296 if (NULL != pm->qe)
3297 {
3298 GNUNET_assert (pm == pm->qe->pm);
3299 pm->qe->pm = NULL;
3300 }
3301 if (NULL != pm->bpm)
3302 {
3303 free_fragment_tree (pm->bpm);
3304 if (NULL != pm->bpm->qe)
3305 {
3306 struct QueueEntry *qe = pm->bpm->qe;
3307
3308 qe->pm = NULL;
3309 }
3310 GNUNET_free (pm->bpm);
3311 }
3312
3313 GNUNET_free (pm);
3315 "Freeing pm done\n");
3316}
3317
3318
3324static void
3326{
3327 struct VirtualLink *vl = rc->virtual_link;
3328
3332 rc->msg_uuid.uuid,
3333 rc));
3334 GNUNET_free (rc);
3335}
3336
3337
3343static void
3344reassembly_cleanup_task (void *cls)
3345{
3346 struct VirtualLink *vl = cls;
3347 struct ReassemblyContext *rc;
3348
3349 vl->reassembly_timeout_task = NULL;
3350 while (NULL != (rc = GNUNET_CONTAINER_heap_peek (vl->reassembly_heap)))
3351 {
3353 .rel_value_us)
3354 {
3356 continue;
3357 }
3362 vl);
3363 return;
3364 }
3365}
3366
3367
3376static int
3377free_reassembly_cb (void *cls, uint32_t key, void *value)
3378{
3379 struct ReassemblyContext *rc = value;
3380
3381 (void) cls;
3382 (void) key;
3384 return GNUNET_OK;
3385}
3386
3387
3393static void
3394free_virtual_link (struct VirtualLink *vl)
3395{
3396 struct PendingMessage *pm;
3397 struct CoreSentContext *csc;
3398
3400 "free virtual link %p\n",
3401 vl);
3402
3403 if (NULL != vl->reassembly_map)
3404 {
3407 NULL);
3409 vl->reassembly_map = NULL;
3411 vl->reassembly_heap = NULL;
3412 }
3413 if (NULL != vl->reassembly_timeout_task)
3414 {
3417 }
3418 while (NULL != (pm = vl->pending_msg_head))
3422 if (NULL != vl->visibility_task)
3423 {
3425 vl->visibility_task = NULL;
3426 }
3427 if (NULL != vl->fc_retransmit_task)
3428 {
3430 vl->fc_retransmit_task = NULL;
3431 }
3432 while (NULL != (csc = vl->csc_head))
3433 {
3435 GNUNET_assert (vl == csc->vl);
3436 csc->vl = NULL;
3437 }
3438 GNUNET_break (NULL == vl->n);
3439 GNUNET_break (NULL == vl->dv);
3440 GNUNET_free (vl);
3441}
3442
3443
3449static void
3451{
3452 if (NULL != vs->revalidation_task)
3453 {
3454 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
3455 vs->revalidation_task = NULL;
3456 }
3457 /*memcpy (&hkey,
3458 &hc,
3459 sizeof (hkey));*/
3461 "Remove key %s for address %s map size %u contains %u during freeing state\n",
3462 GNUNET_h2s (&vs->hc),
3463 vs->address,
3466 &vs->hc));
3469 GNUNET_YES ==
3472 vs->hn = NULL;
3473 if (NULL != vs->sc)
3474 {
3476 "store cancel\n");
3478 vs->sc = NULL;
3479 }
3480 GNUNET_free (vs->address);
3481 GNUNET_free (vs);
3482}
3483
3484
3491static struct Neighbour *
3493{
3495}
3496
3497
3504static struct VirtualLink *
3506{
3508}
3509
3510
3514struct MonitorEvent
3515{
3522
3527
3532
3536 uint32_t num_msg_pending;
3537
3541 uint32_t num_bytes_pending;
3542};
3543
3544
3553static void
3555{
3556 struct Neighbour *n = dvh->next_hop;
3557 struct DistanceVector *dv = dvh->dv;
3558 struct PendingAcknowledgement *pa;
3559
3560 while (NULL != (pa = dvh->pa_head))
3561 {
3563 pa->dvh = NULL;
3564 }
3565 GNUNET_CONTAINER_MDLL_remove (neighbour, n->dv_head, n->dv_tail, dvh);
3567 GNUNET_free (dvh);
3568}
3569
3570
3577static void
3578check_link_down (void *cls);
3579
3580
3586static void
3588{
3590 "Informing CORE clients about disconnect from %s\n",
3591 GNUNET_i2s (pid));
3592 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3593 {
3594 struct GNUNET_MQ_Envelope *env;
3595 struct DisconnectInfoMessage *dim;
3596
3597 if (CT_CORE != tc->type)
3598 continue;
3600 dim->peer = *pid;
3601 GNUNET_MQ_send (tc->mq, env);
3602 }
3603}
3604
3605
3612static void
3613free_dv_route (struct DistanceVector *dv)
3614{
3615 struct DistanceVectorHop *dvh;
3616 struct VirtualLink *vl;
3617
3618 while (NULL != (dvh = dv->dv_head))
3620
3622 GNUNET_YES ==
3624 if (NULL != (vl = dv->vl))
3625 {
3626 GNUNET_assert (dv == vl->dv);
3627 vl->dv = NULL;
3628 if (NULL == vl->n)
3629 {
3631 free_virtual_link (vl);
3632 }
3633 else
3634 {
3637 }
3638 dv->vl = NULL;
3639 }
3640
3641 if (NULL != dv->timeout_task)
3642 {
3644 dv->timeout_task = NULL;
3645 }
3646 GNUNET_free (dv->km);
3647 GNUNET_free (dv);
3648}
3649
3650
3664static void
3666 const struct GNUNET_PeerIdentity *peer,
3667 const char *address,
3669 const struct MonitorEvent *me)
3670{
3671 struct GNUNET_MQ_Envelope *env;
3673 size_t addr_len = strlen (address) + 1;
3674
3676 addr_len,
3678 md->nt = htonl ((uint32_t) nt);
3679 md->peer = *peer;
3680 md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
3681 md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
3682 md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
3683 md->rtt = GNUNET_TIME_relative_hton (me->rtt);
3684 md->cs = htonl ((uint32_t) me->cs);
3685 md->num_msg_pending = htonl (me->num_msg_pending);
3686 md->num_bytes_pending = htonl (me->num_bytes_pending);
3687 memcpy (&md[1], address, addr_len);
3688 GNUNET_MQ_send (tc->mq, env);
3689}
3690
3691
3701static void
3703 const char *address,
3705 const struct MonitorEvent *me)
3706{
3707 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3708 {
3709 if (CT_MONITOR != tc->type)
3710 continue;
3711 if (tc->details.monitor.one_shot)
3712 continue;
3713 if ((GNUNET_NO == GNUNET_is_zero (&tc->details.monitor.peer)) &&
3714 (0 != GNUNET_memcmp (&tc->details.monitor.peer, peer)))
3715 continue;
3717 }
3718}
3719
3720
3730static void *
3731client_connect_cb (void *cls,
3732 struct GNUNET_SERVICE_Client *client,
3733 struct GNUNET_MQ_Handle *mq)
3734{
3735 struct TransportClient *tc;
3736
3737 (void) cls;
3738 tc = GNUNET_new (struct TransportClient);
3739 tc->client = client;
3740 tc->mq = mq;
3743 "Client %p of type %u connected\n",
3744 tc,
3745 tc->type);
3746 return tc;
3747}
3748
3749
3750static enum GNUNET_GenericReturnValue
3751remove_global_addresses (void *cls,
3752 const struct GNUNET_PeerIdentity *pid,
3753 void *value)
3754{
3755 struct TransportGlobalNattedAddress *tgna = value;
3756 (void) cls;
3757
3758 GNUNET_free (tgna);
3759
3760 return GNUNET_OK;
3761}
3762
3763
3770static void
3771free_neighbour (struct Neighbour *neighbour,
3772 enum GNUNET_GenericReturnValue drop_link)
3773{
3774 struct DistanceVectorHop *dvh;
3775 struct VirtualLink *vl;
3776
3777 GNUNET_assert (NULL == neighbour->queue_head);
3780 &neighbour->pid,
3781 neighbour));
3783 "Freeing neighbour\n");
3786 NULL);
3788 while (NULL != (dvh = neighbour->dv_head))
3789 {
3790 struct DistanceVector *dv = dvh->dv;
3791
3793 if (NULL == dv->dv_head)
3794 free_dv_route (dv);
3795 }
3796 if (NULL != neighbour->get)
3797 {
3799 neighbour->get = NULL;
3800 }
3801 if (NULL != neighbour->sc)
3802 {
3804 "store cancel\n");
3805 GNUNET_PEERSTORE_store_cancel (neighbour->sc);
3806 neighbour->sc = NULL;
3807 }
3808 if (NULL != (vl = neighbour->vl))
3809 {
3810 GNUNET_assert (neighbour == vl->n);
3811 vl->n = NULL;
3812 if ((GNUNET_YES == drop_link) || (NULL == vl->dv))
3813 {
3816 }
3817 else
3818 {
3821 }
3822 neighbour->vl = NULL;
3823 }
3824 GNUNET_free (neighbour);
3825}
3826
3827
3834static void
3836 const struct GNUNET_PeerIdentity *pid)
3837{
3838 struct GNUNET_MQ_Envelope *env;
3839 struct ConnectInfoMessage *cim;
3840
3841 GNUNET_assert (CT_CORE == tc->type);
3843 cim->id = *pid;
3844 GNUNET_MQ_send (tc->mq, env);
3845}
3846
3847
3853static void
3855{
3857 "Informing CORE clients about connection to %s\n",
3858 GNUNET_i2s (pid));
3859 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3860 {
3861 if (CT_CORE != tc->type)
3862 continue;
3864 }
3865}
3866
3867
3875static void
3876transmit_on_queue (void *cls);
3877
3878
3882static unsigned int
3884{
3885 for (struct Queue *s = queue_head; NULL != s;
3886 s = s->next_client)
3887 {
3888 if (s->tc->details.communicator.address_prefix !=
3889 queue->tc->details.communicator.address_prefix)
3890 {
3892 "queue address %s qid %u compare with queue: address %s qid %u\n",
3893 queue->address,
3894 queue->qid,
3895 s->address,
3896 s->qid);
3897 if ((s->priority > queue->priority) && (0 < s->q_capacity) &&
3898 (QUEUE_LENGTH_LIMIT > s->queue_length) )
3899 return GNUNET_YES;
3901 "Lower prio\n");
3902 }
3903 }
3904 return GNUNET_NO;
3905}
3906
3907
3915static void
3917 struct Queue *queue,
3919{
3921
3922 if (queue->validated_until.abs_value_us < now.abs_value_us)
3923 return;
3925 queue->tc->details.communicator.
3926 queue_head))
3927 return;
3928
3929 if (queue->tc->details.communicator.total_queue_length >=
3931 {
3933 "Transmission on queue %s (QID %u) throttled due to communicator queue limit\n",
3934 queue->address,
3935 queue->qid);
3937 GST_stats,
3938 "# Transmission throttled due to communicator queue limit",
3939 1,
3940 GNUNET_NO);
3941 queue->idle = GNUNET_NO;
3942 return;
3943 }
3944 if (queue->queue_length >= QUEUE_LENGTH_LIMIT)
3945 {
3947 "Transmission on queue %s (QID %u) throttled due to communicator queue length limit\n",
3948 queue->address,
3949 queue->qid);
3951 "# Transmission throttled due to queue queue limit",
3952 1,
3953 GNUNET_NO);
3954 queue->idle = GNUNET_NO;
3955 return;
3956 }
3957 if (0 == queue->q_capacity)
3958 {
3960 "Transmission on queue %s (QID %u) throttled due to communicator message has capacity %"
3961 PRIu64 ".\n",
3962 queue->address,
3963 queue->qid,
3964 queue->q_capacity);
3966 "# Transmission throttled due to message queue capacity",
3967 1,
3968 GNUNET_NO);
3969 queue->idle = GNUNET_NO;
3970 return;
3971 }
3972 /* queue might indeed be ready, schedule it */
3973 if (NULL != queue->transmit_task)
3974 GNUNET_SCHEDULER_cancel (queue->transmit_task);
3975 queue->transmit_task =
3977 queue);
3979 "Considering transmission on queue `%s' QID %llu to %s\n",
3980 queue->address,
3981 (unsigned long long) queue->qid,
3982 GNUNET_i2s (&queue->neighbour->pid));
3983}
3984
3985
3992static void
3993check_link_down (void *cls)
3994{
3995 struct VirtualLink *vl = cls;
3996 struct DistanceVector *dv = vl->dv;
3997 struct Neighbour *n = vl->n;
3998 struct GNUNET_TIME_Absolute dvh_timeout;
3999 struct GNUNET_TIME_Absolute q_timeout;
4000
4002 "Checking if link is down\n");
4003 vl->visibility_task = NULL;
4004 dvh_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
4005 if (NULL != dv)
4006 {
4007 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4008 pos = pos->next_dv)
4009 dvh_timeout = GNUNET_TIME_absolute_max (dvh_timeout,
4010 pos->path_valid_until);
4011 if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
4012 {
4013 vl->dv->vl = NULL;
4014 vl->dv = NULL;
4015 }
4016 }
4017 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
4018 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
4019 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
4021 {
4022 vl->n->vl = NULL;
4023 vl->n = NULL;
4024 }
4025 if ((NULL == vl->n) && (NULL == vl->dv))
4026 {
4028 free_virtual_link (vl);
4029 return;
4030 }
4031 vl->visibility_task =
4032 GNUNET_SCHEDULER_add_at (GNUNET_TIME_absolute_max (q_timeout, dvh_timeout),
4034 vl);
4035}
4036
4037
4043static void
4044free_queue (struct Queue *queue)
4045{
4046 struct Neighbour *neighbour = queue->neighbour;
4047 struct TransportClient *tc = queue->tc;
4048 struct MonitorEvent me = { .cs = GNUNET_TRANSPORT_CS_DOWN,
4050 struct QueueEntry *qe;
4051 int maxxed;
4052 struct PendingAcknowledgement *pa;
4053 struct VirtualLink *vl;
4054
4056 "Cleaning up queue %u\n", queue->qid);
4057 if (NULL != queue->mo)
4058 {
4060 queue->mo = NULL;
4061 }
4062 if (NULL != queue->transmit_task)
4063 {
4064 GNUNET_SCHEDULER_cancel (queue->transmit_task);
4065 queue->transmit_task = NULL;
4066 }
4067 while (NULL != (pa = queue->pa_head))
4068 {
4069 GNUNET_CONTAINER_MDLL_remove (queue, queue->pa_head, queue->pa_tail, pa);
4070 pa->queue = NULL;
4071 }
4072
4074 neighbour->queue_head,
4075 neighbour->queue_tail,
4076 queue);
4078 tc->details.communicator.queue_head,
4079 tc->details.communicator.queue_tail,
4080 queue);
4082 tc->details.communicator.total_queue_length);
4084 "Cleaning up queue with length %u\n",
4085 queue->queue_length);
4086 while (NULL != (qe = queue->queue_head))
4087 {
4088 GNUNET_CONTAINER_DLL_remove (queue->queue_head, queue->queue_tail, qe);
4089 queue->queue_length--;
4090 tc->details.communicator.total_queue_length--;
4091 if (NULL != qe->pm)
4092 {
4093 GNUNET_assert (qe == qe->pm->qe);
4094 qe->pm->qe = NULL;
4095 }
4096 GNUNET_free (qe);
4097 }
4098 GNUNET_assert (0 == queue->queue_length);
4099 if ((maxxed) && (COMMUNICATOR_TOTAL_QUEUE_LIMIT >
4100 tc->details.communicator.total_queue_length))
4101 {
4102 /* Communicator dropped below threshold, resume all _other_ queues */
4104 GST_stats,
4105 "# Transmission throttled due to communicator queue limit",
4106 -1,
4107 GNUNET_NO);
4108 for (struct Queue *s = tc->details.communicator.queue_head; NULL != s;
4109 s = s->next_client)
4111 s,
4113 }
4114 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
4116
4117 vl = lookup_virtual_link (&neighbour->pid);
4118 if ((NULL != vl) && (neighbour == vl->n))
4119 {
4121 check_link_down (vl);
4122 }
4123 if (NULL == neighbour->queue_head)
4124 {
4125 free_neighbour (neighbour, GNUNET_NO);
4126 }
4127}
4128
4129
4135static void
4137{
4138 struct TransportClient *tc = ale->tc;
4139
4140 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
4141 tc->details.communicator.addr_tail,
4142 ale);
4143 if (NULL != ale->sc)
4144 {
4146 "store cancel\n");
4148 ale->sc = NULL;
4149 }
4150 if (NULL != ale->st)
4151 {
4153 ale->st = NULL;
4154 }
4155 if (NULL != ale->signed_address)
4157 GNUNET_free (ale);
4158}
4159
4160
4169static int
4170stop_peer_request (void *cls,
4171 const struct GNUNET_PeerIdentity *pid,
4172 void *value)
4173{
4174 struct TransportClient *tc = cls;
4175 struct PeerRequest *pr = value;
4176
4177 if (NULL != pr->nc)
4179 pr->nc = NULL;
4181 GNUNET_YES ==
4182 GNUNET_CONTAINER_multipeermap_remove (tc->details.application.requests,
4183 pid,
4184 pr));
4185 GNUNET_free (pr);
4186
4187 return GNUNET_OK;
4188}
4189
4190
4191static void
4192do_shutdown (void *cls);
4193
4202static void
4203client_disconnect_cb (void *cls,
4204 struct GNUNET_SERVICE_Client *client,
4205 void *app_ctx)
4206{
4207 struct TransportClient *tc = app_ctx;
4208
4209 (void) cls;
4210 (void) client;
4212 switch (tc->type)
4213 {
4214 case CT_NONE:
4216 "Unknown Client %p disconnected, cleaning up.\n",
4217 tc);
4218 break;
4219
4220 case CT_CORE: {
4221 struct PendingMessage *pm;
4223 "CORE Client %p disconnected, cleaning up.\n",
4224 tc);
4225
4226
4227 while (NULL != (pm = tc->details.core.pending_msg_head))
4228 {
4230 tc->details.core.pending_msg_head,
4231 tc->details.core.pending_msg_tail,
4232 pm);
4233 pm->client = NULL;
4234 }
4235 }
4236 break;
4237
4238 case CT_MONITOR:
4240 "MONITOR Client %p disconnected, cleaning up.\n",
4241 tc);
4242
4243 break;
4244
4245 case CT_COMMUNICATOR: {
4246 struct Queue *q;
4247 struct AddressListEntry *ale;
4248
4250 "COMMUNICATOR Client %p disconnected, cleaning up.\n",
4251 tc);
4252
4253 if (NULL != tc->details.communicator.free_queue_entry_task)
4255 tc->details.communicator.free_queue_entry_task);
4256 while (NULL != (q = tc->details.communicator.queue_head))
4257 free_queue (q);
4258 while (NULL != (ale = tc->details.communicator.addr_head))
4260 GNUNET_free (tc->details.communicator.address_prefix);
4261 }
4262 break;
4263
4264 case CT_APPLICATION:
4266 "APPLICATION Client %p disconnected, cleaning up.\n",
4267 tc);
4268
4269 GNUNET_CONTAINER_multipeermap_iterate (tc->details.application.requests,
4271 tc);
4272 GNUNET_CONTAINER_multipeermap_destroy (tc->details.application.requests);
4273 break;
4274 }
4275 GNUNET_free (tc);
4276 if ((GNUNET_YES == in_shutdown) && (NULL == clients_head))
4277 {
4279 "Our last client disconnected\n");
4280 do_shutdown (cls);
4281 }
4282}
4283
4284
4294static int
4296 const struct GNUNET_PeerIdentity *pid,
4297 void *value)
4298{
4299 struct TransportClient *tc = cls;
4300 struct VirtualLink *vl = value;
4301
4302 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
4303 return GNUNET_OK;
4304
4306 "Telling new CORE client about existing connection to %s\n",
4307 GNUNET_i2s (pid));
4309 return GNUNET_OK;
4310}
4311
4312
4318static void
4320 unsigned
4321 int free_cmc);
4322
4323static enum GNUNET_GenericReturnValue
4324resume_communicators (void *cls,
4325 const struct GNUNET_PeerIdentity *pid,
4326 void *value)
4327{
4328 struct VirtualLink *vl = value;
4329 struct CommunicatorMessageContext *cmc;
4330
4331 /* resume communicators */
4332 while (NULL != (cmc = vl->cmc_tail))
4333 {
4335 if (GNUNET_NO == cmc->continue_send)
4337 }
4338 return GNUNET_OK;
4339}
4340
4341
4350static void
4351handle_client_start (void *cls, const struct StartMessage *start)
4352{
4353 // const struct GNUNET_PeerIdentity *my_identity;
4354 struct TransportClient *tc = cls;
4355 // uint32_t options;
4356 //
4357 // my_identity = GNUNET_PILS_get_identity (pils);
4358 // GNUNET_assert (my_identity);
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, 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] =
4506 GNUNET_CRYPTO_random_u64 (num_dv);
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 const struct GNUNET_PeerIdentity *my_identity;
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 if (NULL != my_identity)
4685 {
4687 "Communicator for peer %s with prefix '%s' connected %s\n",
4689 tc->details.communicator.address_prefix,
4690 tc->details.communicator.can_burst ? "can burst" :
4691 "can not burst");
4692 }
4693 else
4694 {
4696 "Communicator for local peer with prefix '%s' connected %s\n",
4697 tc->details.communicator.address_prefix,
4698 tc->details.communicator.can_burst ? "can burst" :
4699 "can not burst");
4700 }
4702}
4703
4704
4712static int
4714 void *cls,
4716{
4717 const struct GNUNET_MessageHeader *inbox;
4718 const char *is;
4719 uint16_t msize;
4720 uint16_t isize;
4721
4722 (void) cls;
4723 msize = ntohs (cb->header.size) - sizeof(*cb);
4724 inbox = (const struct GNUNET_MessageHeader *) &cb[1];
4725 isize = ntohs (inbox->size);
4726 if (isize >= msize)
4727 {
4728 GNUNET_break (0);
4729 return GNUNET_SYSERR;
4730 }
4731 is = (const char *) inbox;
4732 is += isize;
4733 msize -= isize;
4734 GNUNET_assert (0 < msize);
4735 if ('\0' != is[msize - 1])
4736 {
4737 GNUNET_break (0);
4738 return GNUNET_SYSERR;
4739 }
4740 return GNUNET_OK;
4741}
4742
4743
4744struct SignDvCls
4745{
4746 struct DistanceVector *dv;
4747 struct PilsRequest *req;
4748};
4749
4750
4751static void
4752sign_dv_cb (void *cls,
4753 const struct GNUNET_PeerIdentity *pid,
4754 const struct GNUNET_CRYPTO_EddsaSignature *sig)
4755{
4756 struct SignDvCls *sign_dv_cls = cls;
4757 struct DistanceVector *dv = sign_dv_cls->dv;
4758 struct PilsRequest *pr = sign_dv_cls->req;
4759
4760 pr->op = NULL;
4763 pr);
4764 GNUNET_free (pr);
4765
4766 dv->sender_sig = *sig;
4767}
4768
4769
4775static void
4776sign_ephemeral (struct DistanceVector *dv)
4777{
4778 struct EphemeralConfirmationPS ec;
4779 struct SignDvCls *sign_dv_cls;
4780
4784 ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL);
4785 ec.target = dv->target;
4786 ec.ephemeral_key = dv->ephemeral_key;
4787 ec.sender_monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
4788 ec.purpose.size = htonl (sizeof(ec));
4789 sign_dv_cls = GNUNET_new (struct SignDvCls);
4790 sign_dv_cls->req = GNUNET_new (struct PilsRequest);
4791 sign_dv_cls->dv = dv;
4794 sign_dv_cls->req);
4796 &ec.purpose,
4797 sign_dv_cb,
4798 sign_dv_cls);
4799}
4800
4801
4802static void
4804 struct TransportClient *tc);
4805
4806
4807static void
4808free_timedout_queue_entry (void *cls)
4809{
4810 struct TransportClient *tc = cls;
4812
4814 "freeing timedout queue entries\n");
4815
4816 tc->details.communicator.free_queue_entry_task = NULL;
4817 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
4818 queue = queue->next_client)
4819 {
4820 struct QueueEntry *qep = queue->queue_head;
4821
4823 "checking QID %u for timedout queue entries\n",
4824 queue->qid);
4825 while (NULL != qep)
4826 {
4827 struct QueueEntry *pos = qep;
4829 pos->creation_timestamp, now);
4830 qep = qep->next;
4831
4833 "diff to now %s \n",
4836 {
4838 "Freeing timed out QueueEntry with MID %" PRIu64
4839 " and QID %u\n",
4840 pos->mid,
4841 queue->qid);
4842 free_queue_entry (pos, tc);
4843 }
4844 }
4845 }
4846}
4847
4848
4858static void
4859queue_send_msg (struct Queue *queue,
4860 struct PendingMessage *pm,
4861 const void *payload,
4862 size_t payload_size)
4863{
4864 struct Neighbour *n = queue->neighbour;
4866 struct GNUNET_MQ_Envelope *env;
4867 struct PendingAcknowledgement *pa;
4868
4869 GNUNET_log (
4871 "Queueing %u bytes of payload for transmission <%" PRIu64
4872 "> on queue %llu to %s\n",
4873 (unsigned int) payload_size,
4874 (NULL == pm) ? 0 : pm->logging_uuid,
4875 (unsigned long long) queue->qid,
4876 GNUNET_i2s (&queue->neighbour->pid));
4877 env = GNUNET_MQ_msg_extra (smt,
4878 payload_size,
4880 smt->qid = htonl (queue->qid);
4881 smt->mid = GNUNET_htonll (queue->mid_gen);
4882 smt->receiver = n->pid;
4883 memcpy (&smt[1], payload, payload_size);
4884 {
4885 /* Pass the env to the communicator of queue for transmission. */
4886 struct QueueEntry *qe;
4887
4888 qe = GNUNET_new (struct QueueEntry);
4889 qe->creation_timestamp = GNUNET_TIME_absolute_get ();
4890 qe->mid = queue->mid_gen;
4892 "Create QueueEntry with MID %" PRIu64
4893 " and QID %u and prefix %s\n",
4894 qe->mid,
4895 queue->qid,
4896 queue->tc->details.communicator.address_prefix);
4897 queue->mid_gen++;
4898 qe->queue = queue;
4899 if (NULL != pm)
4900 {
4901 qe->pm = pm;
4902 // TODO Why do we have a retransmission. When we know, make decision if we still want this.
4903 // GNUNET_assert (NULL == pm->qe);
4904 if (NULL != pm->qe)
4905 {
4907 "Retransmitting message <%" PRIu64
4908 "> remove pm from qe with MID: %llu \n",
4909 pm->logging_uuid,
4910 (unsigned long long) pm->qe->mid);
4911 pm->qe->pm = NULL;
4912 }
4913 pm->qe = qe;
4914 }
4915 GNUNET_assert (CT_COMMUNICATOR == queue->tc->type);
4916 if (0 == queue->q_capacity)
4917 {
4918 // Messages without FC or fragments can get here.
4919 if (NULL != pm)
4920 {
4922 "Message %" PRIu64
4923 " (pm type %u) was not send because queue has no capacity.\n",
4924 pm->logging_uuid,
4925 pm->pmt);
4926 pm->qe = NULL;
4927 }
4928 GNUNET_free (env);
4929 GNUNET_free (qe);
4930 return;
4931 }
4932 GNUNET_CONTAINER_DLL_insert (queue->queue_head, queue->queue_tail, qe);
4933 queue->queue_length++;
4934 queue->tc->details.communicator.total_queue_length++;
4935 if (GNUNET_NO == queue->unlimited_length)
4936 queue->q_capacity--;
4938 "Queue %s with qid %u has capacity %" PRIu64 "\n",
4939 queue->address,
4940 queue->qid,
4941 queue->q_capacity);
4943 queue->tc->details.communicator.total_queue_length)
4944 queue->idle = GNUNET_NO;
4945 if (QUEUE_LENGTH_LIMIT == queue->queue_length)
4946 queue->idle = GNUNET_NO;
4947 if (0 == queue->q_capacity)
4948 queue->idle = GNUNET_NO;
4949
4950 if (GNUNET_NO == queue->idle)
4951 {
4952 struct TransportClient *tc = queue->tc;
4953
4954 if (NULL == tc->details.communicator.free_queue_entry_task)
4955 tc->details.communicator.free_queue_entry_task =
4957 &
4959 tc);
4960 }
4961 if (NULL != pm && NULL != (pa = pm->pa_head))
4962 {
4963 while (pm != pa->pm)
4964 pa = pa->next_pa;
4965 pa->num_send++;
4966 }
4967 // GNUNET_CONTAINER_multiuuidmap_get (pending_acks, &ack[i].ack_uuid.value);
4969 "Sending message MID %" PRIu64
4970 " of type %u (%u) and size %lu with MQ %p queue %s (QID %u) pending %"
4971 PRIu64 "\n",
4972 GNUNET_ntohll (smt->mid),
4973 ntohs (((const struct GNUNET_MessageHeader *) payload)->type),
4974 ntohs (smt->header.size),
4975 (unsigned long) payload_size,
4976 queue->tc->mq,
4977 queue->address,
4978 queue->qid,
4979 (NULL == pm) ? 0 : pm->logging_uuid);
4980 GNUNET_MQ_send (queue->tc->mq, env);
4981 }
4982}
4983
4984
4995static struct GNUNET_TIME_Relative
4996route_via_neighbour (const struct Neighbour *n,
4997 const struct GNUNET_MessageHeader *hdr,
4999{
5000 struct GNUNET_TIME_Absolute now;
5001 unsigned int candidates;
5002 unsigned int sel1;
5003 unsigned int sel2;
5004 struct GNUNET_TIME_Relative rtt;
5005
5006 /* Pick one or two 'random' queues from n (under constraints of options) */
5007 now = GNUNET_TIME_absolute_get ();
5008 /* FIXME-OPTIMIZE: give queues 'weights' and pick proportional to
5009 weight in the future; weight could be assigned by observed
5010 bandwidth (note: not sure if we should do this for this type
5011 of control traffic though). */
5012 candidates = 0;
5013 for (struct Queue *pos = n->queue_head; NULL != pos;
5014 pos = pos->next_neighbour)
5015 {
5016 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
5017 (pos->validated_until.abs_value_us > now.abs_value_us))
5018 candidates++;
5019 }
5020 if (0 == candidates)
5021 {
5022 /* This can happen rarely if the last confirmed queue timed
5023 out just as we were beginning to process this message. */
5025 "Could not route message of type %u to %s: no valid queue\n",
5026 ntohs (hdr->type),
5027 GNUNET_i2s (&n->pid));
5029 "# route selection failed (all no valid queue)",
5030 1,
5031 GNUNET_NO);
5033 }
5034
5036 sel1 = GNUNET_CRYPTO_random_u32 (candidates);
5037 if (0 == (options & RMO_REDUNDANT))
5038 sel2 = candidates; /* picks none! */
5039 else
5040 sel2 = GNUNET_CRYPTO_random_u32 (candidates);
5041 candidates = 0;
5042 for (struct Queue *pos = n->queue_head; NULL != pos;
5043 pos = pos->next_neighbour)
5044 {
5045 if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
5046 (pos->validated_until.abs_value_us > now.abs_value_us))
5047 {
5048 if ((sel1 == candidates) || (sel2 == candidates))
5049 {
5051 "Routing message of type %u to %s using %s (#%u)\n",
5052 ntohs (hdr->type),
5053 GNUNET_i2s (&n->pid),
5054 pos->address,
5055 (sel1 == candidates) ? 1 : 2);
5056 rtt = GNUNET_TIME_relative_min (rtt, pos->pd.aged_rtt);
5057 queue_send_msg (pos, NULL, hdr, ntohs (hdr->size));
5058 }
5059 candidates++;
5060 }
5061 }
5062 return rtt;
5063}
5064
5065
5076typedef void (*DVMessageHandler) (void *cls,
5077 struct Neighbour *next_hop,
5078 const struct GNUNET_MessageHeader *hdr,
5080
5095static struct GNUNET_TIME_Relative
5097 unsigned int num_dvhs,
5098 struct DistanceVectorHop **dvhs,
5099 const struct GNUNET_MessageHeader *hdr,
5100 DVMessageHandler use,
5101 void *use_cls,
5103 enum GNUNET_GenericReturnValue without_fc)
5104{
5105 const struct GNUNET_PeerIdentity *my_identity;
5106 struct TransportDVBoxMessage box_hdr;
5107 struct TransportDVBoxPayloadP *payload_hdr;
5108 uint16_t body_len_hbo = ntohs (hdr->size);
5109 unsigned char pt[sizeof(struct TransportDVBoxPayloadP) + body_len_hbo]
5111 unsigned char ct[sizeof(struct TransportDVBoxPayloadP) + body_len_hbo]
5113 struct GNUNET_TIME_Relative rtt;
5115
5116 payload_hdr = (struct TransportDVBoxPayloadP*) pt;
5119
5120 /* Encrypt payload */
5121 box_hdr.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX);
5122 box_hdr.total_hops = htons (0);
5123 box_hdr.without_fc = htons (without_fc);
5124 // update_ephemeral (dv);
5125 if (0 ==
5126 GNUNET_TIME_absolute_get_remaining (dv->ephemeral_validity).rel_value_us)
5127 {
5128 GNUNET_CRYPTO_eddsa_kem_encaps (&dv->target.public_key,
5129 &dv->ephemeral_key,
5130 (struct GNUNET_ShortHashCode*) &km);
5131 dv->km = GNUNET_new (struct GNUNET_ShortHashCode);
5132 GNUNET_memcpy (dv->km, &km, sizeof(struct GNUNET_ShortHashCode));
5133 sign_ephemeral (dv);
5134 }
5135 box_hdr.ephemeral_key = dv->ephemeral_key;
5136 payload_hdr->sender_sig = dv->sender_sig;
5137 memcpy (&payload_hdr[1], hdr, body_len_hbo);
5138 GNUNET_CRYPTO_random_block (&box_hdr.iv,
5139 sizeof(box_hdr.iv));
5140 payload_hdr->sender = *my_identity;
5141 payload_hdr->monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
5142 GNUNET_CRYPTO_aead_encrypt (sizeof pt,
5143 pt,
5144 0,
5145 NULL,
5146 &km,
5147 &box_hdr.iv,
5148 ct,
5149 &box_hdr.mac);
5151 /* For each selected path, take the pre-computed header and body
5152 and add the path in the middle of the message; then send it. */
5153 for (unsigned int i = 0; i < num_dvhs; i++)
5154 {
5155 struct DistanceVectorHop *dvh = dvhs[i];
5156 unsigned int num_hops = dvh->distance + 1;
5157 char buf[sizeof(struct TransportDVBoxMessage)
5158 + sizeof(struct GNUNET_PeerIdentity) * num_hops
5159 + sizeof(struct TransportDVBoxPayloadP)
5160 + body_len_hbo] GNUNET_ALIGN;
5161 struct GNUNET_PeerIdentity *dhops;
5162
5163 box_hdr.header.size = htons (sizeof(buf));
5164 box_hdr.orig_size = htons (sizeof(buf));
5165 box_hdr.num_hops = htons (num_hops);
5166 memcpy (buf, &box_hdr, sizeof(box_hdr));
5167 dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
5168 memcpy (dhops,
5169 dvh->path,
5170 dvh->distance * sizeof(struct GNUNET_PeerIdentity));
5171 dhops[dvh->distance] = dv->target;
5172 if (GNUNET_EXTRA_LOGGING > 0)
5173 {
5174 char *path;
5175
5177 for (unsigned int j = 0; j < num_hops; j++)
5178 {
5179 char *tmp;
5180
5181 GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
5182 GNUNET_free (path);
5183 path = tmp;
5184 }
5186 "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
5187 ntohs (hdr->type),
5188 GNUNET_i2s (&dv->target),
5189 i + 1,
5190 num_dvhs,
5191 path);
5192 GNUNET_free (path);
5193 }
5194 rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
5195 memcpy (&dhops[num_hops], ct, sizeof(ct));
5196 use (use_cls,
5197 dvh->next_hop,
5198 (const struct GNUNET_MessageHeader *) buf,
5199 options);
5200 }
5201 return rtt;
5202}
5203
5204
5214static void
5215send_dv_to_neighbour (void *cls,
5216 struct Neighbour *next_hop,
5217 const struct GNUNET_MessageHeader *hdr,
5219{
5220 (void) cls;
5221 (void) route_via_neighbour (next_hop, hdr, RMO_UNCONFIRMED_ALLOWED);
5222}
5223
5224
5236static struct GNUNET_TIME_Relative
5238// route_control_message_without_fc (const struct GNUNET_PeerIdentity *target,
5239 const struct GNUNET_MessageHeader *hdr,
5241{
5242 // struct VirtualLink *vl;
5243 struct Neighbour *n;
5244 struct DistanceVector *dv;
5245 struct GNUNET_TIME_Relative rtt1;
5246 struct GNUNET_TIME_Relative rtt2;
5247 const struct GNUNET_PeerIdentity *target = &vl->target;
5248
5250 "Trying to route message of type %u to %s without fc\n",
5251 ntohs (hdr->type),
5252 GNUNET_i2s (target));
5253
5254 // TODO Do this elsewhere. vl should be given as parameter to method.
5255 // vl = lookup_virtual_link (target);
5256 GNUNET_assert (NULL != vl && GNUNET_YES == vl->confirmed);
5257 if (NULL == vl)
5259 n = vl->n;
5260 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
5261 if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
5262 {
5263 /* if confirmed is required, and we do not have anything
5264 confirmed, drop respective options */
5265 if (NULL == n)
5266 n = lookup_neighbour (target);
5267 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
5269 }
5270 if ((NULL == n) && (NULL == dv))
5271 {
5273 "Cannot route message of type %u to %s: no route\n",
5274 ntohs (hdr->type),
5275 GNUNET_i2s (target));
5277 "# Messages dropped in routing: no acceptable method",
5278 1,
5279 GNUNET_NO);
5281 }
5283 "Routing message of type %u to %s with options %X\n",
5284 ntohs (hdr->type),
5285 GNUNET_i2s (target),
5286 (unsigned int) options);
5287 /* If both dv and n are possible and we must choose:
5288 flip a coin for the choice between the two; for now 50/50 */
5289 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
5290 {
5291 if (0 == GNUNET_CRYPTO_random_u32 (2))
5292 n = NULL;
5293 else
5294 dv = NULL;
5295 }
5296 if ((NULL != n) && (NULL != dv))
5297 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
5298 enough for redundancy, so clear the flag. */
5301 if (NULL != n)
5302 {
5304 "Try to route message of type %u to %s without fc via neighbour\n",
5305 ntohs (hdr->type),
5306 GNUNET_i2s (target));
5307 rtt1 = route_via_neighbour (n, hdr, options);
5308 }
5309 if (NULL != dv)
5310 {
5311 struct DistanceVectorHop *hops[2];
5312 unsigned int res;
5313
5315 options,
5316 hops,
5317 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
5318 if (0 == res)
5319 {
5321 "Failed to route message, could not determine DV path\n");
5322 return rtt1;
5323 }
5325 "encapsulate_for_dv 1\n");
5326 rtt2 = encapsulate_for_dv (dv,
5327 res,
5328 hops,
5329 hdr,
5331 NULL,
5333 GNUNET_YES);
5334 }
5335 return GNUNET_TIME_relative_min (rtt1, rtt2);
5336}
5337
5338
5339static void
5340consider_sending_fc (void *cls);
5341
5348static void
5349task_consider_sending_fc (void *cls)
5350{
5351 struct VirtualLink *vl = cls;
5352 vl->fc_retransmit_task = NULL;
5353 consider_sending_fc (cls);
5354}
5355
5356
5357static char *
5358get_address_without_port (const char *address);
5359
5360
5362{
5363 size_t off;
5364 char *tgnas;
5365};
5366
5367
5368static enum GNUNET_GenericReturnValue
5369add_global_addresses (void *cls,
5370 const struct GNUNET_PeerIdentity *pid,
5371 void *value)
5372{
5373 struct AddGlobalAddressesContext *ctx = cls;
5374 struct TransportGlobalNattedAddress *tgna = value;
5375 char *addr = (char *) &tgna[1];
5376
5378 "sending address %s length %u\n",
5379 addr,
5380 ntohl (tgna->address_length));
5381 GNUNET_memcpy (&(ctx->tgnas[ctx->off]), tgna, sizeof (struct
5383 + ntohl (tgna->address_length));
5384 ctx->off += sizeof(struct TransportGlobalNattedAddress) + ntohl (tgna->
5386
5387 return GNUNET_OK;
5388}
5389
5390
5391static struct GNUNET_TIME_Relative
5392calculate_rtt (struct DistanceVector *dv);
5393
5394
5401static void
5402consider_sending_fc (void *cls)
5403{
5404 struct VirtualLink *vl = cls;
5405 struct GNUNET_TIME_Absolute monotime;
5406 struct TransportFlowControlMessage *fc;
5408 struct GNUNET_TIME_Relative rtt;
5409 struct GNUNET_TIME_Relative rtt_average;
5410 struct Neighbour *n = vl->n;
5411
5412 if (NULL != n && 0 < n->number_of_addresses)
5413 {
5414 size_t addresses_size =
5415 n->number_of_addresses * sizeof (struct TransportGlobalNattedAddress) + n
5416 ->size_of_global_addresses;
5417 char *tgnas = GNUNET_malloc (addresses_size);
5419 ctx.off = 0;
5420 ctx.tgnas = tgnas;
5421
5423 + addresses_size);
5424 fc->header.size = htons (sizeof(struct TransportFlowControlMessage)
5425 + addresses_size);
5426 fc->size_of_addresses = htonl (n->size_of_global_addresses);
5427 fc->number_of_addresses = htonl (n->number_of_addresses);
5430 &ctx);
5433 }
5434 else
5435 {
5436 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage));
5437 fc->header.size = htons (sizeof(struct TransportFlowControlMessage));
5438 }
5439
5441 /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
5442 it always! */
5443 /* For example, we should probably ONLY do this if a bit more than
5444 an RTT has passed, or if the window changed "significantly" since
5445 then. See vl->last_fc_rtt! NOTE: to do this properly, we also
5446 need an estimate for the bandwidth-delay-product for the entire
5447 VL, as that determines "significantly". We have the delay, but
5448 the bandwidth statistics need to be added for the VL!*/(void) duration;
5449
5450 if (NULL != vl->dv)
5451 rtt_average = calculate_rtt (vl->dv);
5452 else
5453 rtt_average = GNUNET_TIME_UNIT_FOREVER_REL;
5454 fc->rtt = GNUNET_TIME_relative_hton (rtt_average);
5456 "Sending FC seq %u to %s with new window %llu %lu %u\n",
5457 (unsigned int) vl->fc_seq_gen,
5458 GNUNET_i2s (&vl->target),
5459 (unsigned long long) vl->incoming_fc_window_size,
5460 (unsigned long) rtt_average.rel_value_us,
5461 vl->sync_ready);
5463 vl->last_fc_transmission = monotime;
5464 fc->sync_ready = vl->sync_ready;
5466 fc->seq = htonl (vl->fc_seq_gen++);
5467 fc->inbound_window_size = GNUNET_htonll (vl->incoming_fc_window_size
5470 fc->outbound_sent = GNUNET_htonll (vl->outbound_fc_window_size_used);
5471 fc->outbound_window_size = GNUNET_htonll (vl->outbound_fc_window_size);
5472 fc->sender_time = GNUNET_TIME_absolute_hton (monotime);
5474 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
5475 {
5478 "FC retransmission to %s failed, will retry in %s\n",
5479 GNUNET_i2s (&vl->target),
5482 }
5483 else
5484 {
5485 /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
5486 vl->last_fc_rtt = rtt;
5487 }
5488 if (NULL != vl->fc_retransmit_task)
5491 {
5493 vl->fc_retransmit_count = 0;
5494 }
5495 vl->fc_retransmit_task =
5497 vl->fc_retransmit_count++;
5498 GNUNET_free (fc);
5499}
5500
5501
5518static void
5520{
5521 struct Neighbour *n = vl->n;
5522 struct DistanceVector *dv = vl->dv;
5523 struct GNUNET_TIME_Absolute now;
5524 struct VirtualLink *vl_next_hop;
5525 int elig;
5526
5528 "check_vl_transmission to target %s\n",
5529 GNUNET_i2s (&vl->target));
5530 /* Check that we have an eligible pending message!
5531 (cheaper than having #transmit_on_queue() find out!) */
5532 elig = GNUNET_NO;
5533 for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
5534 pm = pm->next_vl)
5535 {
5537 "check_vl_transmission loop\n");
5538 if (NULL != pm->qe)
5539 continue; /* not eligible, is in a queue! */
5540 if (pm->bytes_msg + vl->outbound_fc_window_size_used >
5542 {
5544 "Stalled message %" PRIu64
5545 " transmission on VL %s due to flow control: %llu < %llu\n",
5546 pm->logging_uuid,
5547 GNUNET_i2s (&vl->target),
5548 (unsigned long long) vl->outbound_fc_window_size,
5549 (unsigned long long) (pm->bytes_msg
5552 return; /* We have a message, but flow control says "nope" */
5553 }
5555 "Target window on VL %s not stalled. Scheduling transmission on queue\n",
5556 GNUNET_i2s (&vl->target));
5557 /* Notify queues at direct neighbours that we are interested */
5558 now = GNUNET_TIME_absolute_get ();
5559 if (NULL != n)
5560 {
5561 for (struct Queue *queue = n->queue_head; NULL != queue;
5562 queue = queue->next_neighbour)
5563 {
5564 if ((GNUNET_YES == queue->idle) &&
5565 (queue->validated_until.abs_value_us > now.abs_value_us))
5566 {
5568 "Direct neighbour %s not stalled\n",
5569 GNUNET_i2s (&n->pid));
5571 queue,
5573 elig = GNUNET_YES;
5574 }
5575 else
5577 "Neighbour Queue QID: %u (%u) busy or invalid\n",
5578 queue->qid,
5579 queue->idle);
5580 }
5581 }
5582 /* Notify queues via DV that we are interested */
5583 if (NULL != dv)
5584 {
5585 /* Do DV with lower scheduler priority, which effectively means that
5586 IF a neighbour exists and is available, we prefer it. */
5587 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5588 pos = pos->next_dv)
5589 {
5590 struct Neighbour *nh_iter = pos->next_hop;
5591
5592
5593 if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
5594 continue; /* skip this one: path not validated */
5595 else
5596 {
5597 vl_next_hop = lookup_virtual_link (&nh_iter->pid);
5598 GNUNET_assert (NULL != vl_next_hop);
5599 if (pm->bytes_msg + vl_next_hop->outbound_fc_window_size_used >
5600 vl_next_hop->outbound_fc_window_size)
5601 {
5603 "Stalled message %" PRIu64
5604 " transmission on next hop %s due to flow control: %llu < %llu\n",
5605 pm->logging_uuid,
5606 GNUNET_i2s (&vl_next_hop->target),
5607 (unsigned long
5608 long) vl_next_hop->outbound_fc_window_size,
5609 (unsigned long long) (pm->bytes_msg
5610 + vl_next_hop->
5611 outbound_fc_window_size_used));
5612 consider_sending_fc (vl_next_hop);
5613 continue; /* We have a message, but flow control says "nope" for the first hop of this path */
5614 }
5615 for (struct Queue *queue = nh_iter->queue_head; NULL != queue;
5616 queue = queue->next_neighbour)
5617 if ((GNUNET_YES == queue->idle) &&
5618 (queue->validated_until.abs_value_us > now.abs_value_us))
5619 {
5621 "Next hop neighbour %s not stalled\n",
5622 GNUNET_i2s (&nh_iter->pid));
5624 queue,
5626 elig = GNUNET_YES;
5627 }
5628 else
5630 "DV Queue QID: %u (%u) busy or invalid\n",
5631 queue->qid,
5632 queue->idle);
5633 }
5634 }
5635 }
5636 if (GNUNET_YES == elig)
5638 "Eligible message %" PRIu64 " of size %u to %s: %llu/%llu\n",
5639 pm->logging_uuid,
5640 pm->bytes_msg,
5641 GNUNET_i2s (&vl->target),
5642 (unsigned long long) vl->outbound_fc_window_size,
5643 (unsigned long long) (pm->bytes_msg
5645 break;
5646 }
5647}
5648
5649
5656static void
5657handle_client_send (void *cls, const struct OutboundMessage *obm)
5658{
5659 struct TransportClient *tc = cls;
5660 struct PendingMessage *pm;
5661 const struct GNUNET_MessageHeader *obmm;
5662 uint32_t bytes_msg;
5663 struct VirtualLink *vl;
5665
5666 GNUNET_assert (CT_CORE == tc->type);
5667 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
5668 bytes_msg = ntohs (obmm->size);
5669 pp = ntohl (obm->priority);
5670 vl = lookup_virtual_link (&obm->peer);
5671 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
5672 {
5674 "Don't have %s as a neighbour (anymore).\n",
5675 GNUNET_i2s (&obm->peer));
5676 /* Failure: don't have this peer as a neighbour (anymore).
5677 Might have gone down asynchronously, so this is NOT
5678 a protocol violation by CORE. Still count the event,
5679 as this should be rare. */
5682 "# messages dropped (neighbour unknown)",
5683 1,
5684 GNUNET_NO);
5685 return;
5686 }
5687
5688 pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
5690 "1 created pm %p storing vl %p\n",
5691 pm,
5692 vl);
5693 pm->logging_uuid = logging_uuid_gen++;
5694 pm->prefs = pp;
5695 pm->client = tc;
5696 pm->vl = vl;
5697 pm->bytes_msg = bytes_msg;
5698 memcpy (&pm[1], obmm, bytes_msg);
5700 "Sending message of type %u with %u bytes as <%" PRIu64
5701 "> to %s\n",
5702 ntohs (obmm->type),
5703 bytes_msg,
5704 pm->logging_uuid,
5705 GNUNET_i2s (&obm->peer));
5707 tc->details.core.pending_msg_head,
5708 tc->details.core.pending_msg_tail,
5709 pm);
5711 vl->pending_msg_head,
5712 vl->pending_msg_tail,
5713 pm);
5716}
5717
5718
5728static void
5730 void *cls,
5732{
5733 struct Neighbour *n;
5734 struct VirtualLink *vl;
5735 struct TransportClient *tc = cls;
5736 const struct GNUNET_MessageHeader *inbox =
5737 (const struct GNUNET_MessageHeader *) &cb[1];
5738 uint16_t isize = ntohs (inbox->size);
5739 const char *is = ((const char *) &cb[1]) + isize;
5740 size_t slen = strlen (is) + 1;
5741 char
5742 mbuf[slen + isize
5743 + sizeof(struct
5747
5748 /* 0-termination of 'is' was checked already in
5749 #check_communicator_backchannel() */
5751 "Preparing backchannel transmission to %s:%s of type %u and size %u\n",
5752 GNUNET_i2s (&cb->pid),
5753 is,
5754 ntohs (inbox->type),
5755 ntohs (inbox->size));
5756 /* encapsulate and encrypt message */
5757 be->header.type =
5759 be->header.size = htons (sizeof(mbuf));
5760 memcpy (&be[1], inbox, isize);
5761 memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
5762 + isize],
5763 is,
5764 strlen (is) + 1);
5765 // route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
5766 vl = lookup_virtual_link (&cb->pid);
5767 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
5768 {
5770 }
5771 else
5772 {
5773 /* Use route via neighbour */
5774 n = lookup_neighbour (&cb->pid);
5775 if (NULL != n)
5777 n,
5778 &be->header,
5779 RMO_NONE);
5780 }
5782}
5783
5784
5792static int
5793check_add_address (void *cls,
5794 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5795{
5796 struct TransportClient *tc = cls;
5797
5798 if (CT_COMMUNICATOR != tc->type)
5799 {
5800 GNUNET_break (0);
5801 return GNUNET_SYSERR;
5802 }
5804 return GNUNET_OK;
5805}
5806
5807
5813static void
5814store_pi (void *cls);
5815
5816
5821{
5822
5826 struct AddressListEntry *ale;
5827
5831 struct PilsRequest *req;
5832
5833
5837 struct GNUNET_TIME_Absolute et;
5838};
5839
5840
5841static void
5842shc_cont (void *cls, int success)
5843{
5844 struct PilsAddressSignContext *pc = cls;
5845
5846 GNUNET_assert (NULL == pc->req);
5847 if (GNUNET_OK != success)
5848 {
5850 "Failed to store our address `%s' with peerstore\n",
5851 pc->ale->address);
5852 if (NULL == pc->ale->st)
5853 {
5855 &store_pi,
5856 pc->ale);
5857 }
5858 }
5859 GNUNET_free (pc);
5860}
5861
5862
5866static void
5867pils_sign_hello_cb (void *cls,
5868 const struct GNUNET_PeerIdentity *pid,
5869 const struct GNUNET_CRYPTO_EddsaSignature *sig)
5870{
5871 struct PilsAddressSignContext *pc = cls;
5872 struct GNUNET_MQ_Envelope *env;
5873 const struct GNUNET_MessageHeader *msg;
5874
5875 pc->req->op = NULL;
5878 pc->req);
5879 GNUNET_free (pc->req);
5880 pc->req = NULL;
5883 pid,
5884 sig,
5885 pc->et);
5888 "store_pi 1\n");
5890 msg,
5891 shc_cont,
5892 pc);
5893 GNUNET_free (env);
5894}
5895
5896
5903static void
5904peerstore_store_own_cb (void *cls, int success)
5905{
5906 struct PilsAddressSignContext *pc = cls;
5907
5908 pc->ale->sc = NULL;
5909 if (GNUNET_YES != success)
5911 "Failed to store our own address `%s' in peerstore!\n",
5912 pc->ale->address);
5913 else
5915 "Successfully stored our own address `%s' in peerstore!\n",
5916 pc->ale->address);
5917 /* refresh period is 1/4 of expiration time, that should be plenty
5918 without being excessive. */
5919 if (NULL == pc->ale->st)
5920 {
5921 pc->ale->st =
5923 GNUNET_TIME_relative_divide (pc->ale->expiration,
5924 4ULL),
5925 &store_pi,
5926 pc->ale);
5927 }
5928
5929 /* Now we have to update our HELLO! */
5931 pc->req = GNUNET_new (struct PilsRequest);
5934 pc->req);
5935 pc->req->op = GNUNET_PILS_sign_hello (pils,
5937 pc->et,
5939 pc);
5940}
5941
5942
5943// This function
5944static void
5945pils_sign_addr_cb (void *cls,
5946 const struct GNUNET_PeerIdentity *pid,
5947 const struct GNUNET_CRYPTO_EddsaSignature *sig)
5948{
5949 struct PilsAddressSignContext *pc = cls;
5950 char *sig_str;
5951 void *result;
5952 size_t result_size;
5953
5954 pc->req->op = NULL;
5957 pc->req);
5958 GNUNET_free (pc->req);
5959 sig_str = NULL;
5960 (void) GNUNET_STRINGS_base64_encode (sig, sizeof(*sig), &sig_str);
5961 result_size =
5962 1 + GNUNET_asprintf (
5963 (char **) &result,
5964 "%s;%llu;%u;%s",
5965 sig_str,
5966 (unsigned long long) pc->et.abs_value_us,
5967 (unsigned int) pc->ale->nt,
5968 pc->ale->address);
5969 GNUNET_free (sig_str);
5970
5972 "Build our HELLO URI `%s'\n",
5973 (char*) result);
5974
5975 pc->ale->signed_address = result;
5976 pc->ale->signed_address_len = result_size;
5978
5979 expiration = GNUNET_TIME_relative_to_absolute (pc->ale->expiration);
5981 "transport",
5982 pid,
5984 result,
5985 result_size,
5986 expiration,
5989 pc);
5990}
5991
5992
5996struct SignedAddress
5997{
6002
6007
6011 struct GNUNET_HashCode addr_hash GNUNET_PACKED;
6012};
6013
6014
6028void
6030 struct AddressListEntry *ale,
6031 struct GNUNET_TIME_Absolute mono_time)
6032{
6033 struct SignedAddress sa;
6034 struct PilsAddressSignContext *pc;
6035
6036 sa.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS);
6037 sa.purpose.size = htonl (sizeof(sa));
6038 sa.mono_time = GNUNET_TIME_absolute_hton (mono_time);
6039 GNUNET_CRYPTO_hash (ale->address, strlen (ale->address), &sa.addr_hash);
6041 pc->ale = ale;
6042 pc->et = mono_time;
6043 pc->req = GNUNET_new (struct PilsRequest);
6045 &sa.purpose,
6047 pc);
6050 pc->req);
6051}
6052
6053
6059static void
6060store_pi (void *cls)
6061{
6062 struct AddressListEntry *ale = cls;
6063 const char *dash;
6064 char *address_uri;
6065 char *prefix;
6066 unsigned int add_success;
6067
6068 if (NULL == GNUNET_PILS_get_identity (pils))
6069 {
6071 &store_pi,
6072 ale);
6073 return;
6074 }
6076 dash = strchr (ale->address, '-');
6077 GNUNET_assert (NULL != dash);
6078 dash++;
6079 GNUNET_asprintf (&address_uri,
6080 "%s://%s",
6081 prefix,
6082 dash);
6084 ale->st = NULL;
6086 "Storing our address `%s' in peerstore until %s!\n",
6087 ale->address,
6090 address_uri);
6091 if (GNUNET_OK != add_success)
6092 {
6094 "Storing our address `%s' %s\n",
6095 address_uri,
6096 GNUNET_NO == add_success ? "not done" : "failed");
6097 GNUNET_free (address_uri);
6098 return;
6099 }
6100 else
6101 {
6102
6104 "Storing our address `%s'\n",
6105 address_uri);
6106 }
6107 // FIXME hello_mono_time used here?? What about expiration in ale?
6108 pils_sign_address (ale,
6110 // TODO keep track of op and potentially cancel/clean
6111 GNUNET_free (address_uri);
6112}
6113
6114
6115static struct AddressListEntry *
6119 const char *address,
6120 uint32_t aid,
6121 size_t slen)
6122{
6123 struct AddressListEntry *ale;
6124 char *address_without_port;
6125
6126 ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
6127 ale->tc = tc;
6128 ale->address = (const char *) &ale[1];
6129 ale->expiration = expiration;
6130 ale->aid = aid;
6131 ale->nt = nt;
6132 memcpy (&ale[1], address, slen);
6133 address_without_port = get_address_without_port (ale->address);
6135 "Is this %s a local address (%s)\n",
6136 address_without_port,
6137 ale->address);
6138 if (0 != strcmp ("127.0.0.1", address_without_port))
6139 {
6140 if (NULL != ale->st)
6141 {
6143 }
6144 ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
6145 }
6146 GNUNET_free (address_without_port);
6147
6148 return ale;
6149}
6150
6151
6152static void
6153feed_addresses_to_pils (void *cls)
6154{
6155
6157 "Feeding addresses to PILS\n");
6158 pils_feed_task = NULL;
6159
6161 GST_my_hello);
6162}
6163
6164
6171static void
6172handle_add_address (void *cls,
6173 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
6174{
6175 struct TransportClient *tc = cls;
6176 struct AddressListEntry *ale;
6177 size_t slen;
6178 char *address;
6179
6180 /* 0-termination of &aam[1] was checked in #check_add_address */
6182 "Communicator added address `%s'!\n",
6183 (const char *) &aam[1]);
6184 slen = ntohs (aam->header.size) - sizeof(*aam);
6185 address = GNUNET_malloc (slen);
6186 memcpy (address, &aam[1], slen);
6187 ale = create_address_entry (tc,
6189 ntohl (aam->nt),
6190 address,
6191 aam->aid,
6192 slen);
6193 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
6194 tc->details.communicator.addr_tail,
6195 ale);
6196 {
6197 for (struct AddressListEntry *iter = tc->details.communicator.addr_head;
6198 (NULL != iter && NULL != iter->next);
6199 iter = iter->next)
6200 {
6201 char *address_uri;
6202 const char *dash = strchr (ale->address, '-');
6204 GNUNET_assert (NULL != dash);
6205 dash++;
6206 GNUNET_asprintf (&address_uri,
6207 "%s://%s",
6208 prefix,
6209 dash);
6212 GNUNET_free (address_uri);
6213 }
6214 if (NULL != pils_feed_task)
6218 NULL);
6219 }
6222}
6223
6224
6231static void
6232handle_del_address (void *cls,
6233 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
6234{
6235 struct TransportClient *tc = cls;
6236 struct AddressListEntry *alen;
6237
6238 if (CT_COMMUNICATOR != tc->type)
6239 {
6240 GNUNET_break (0);
6242 return;
6243 }
6244 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
6245 NULL != ale;
6246 ale = alen)
6247 {
6248 alen = ale->next;
6249 if (dam->aid != ale->aid)
6250 continue;
6251 GNUNET_assert (ale->tc == tc);
6253 "Communicator deleted address `%s'!\n",
6254 ale->address);
6256 ale->address);
6257 if (NULL != pils_feed_task)
6261 NULL);
6264 return;
6265 }
6267 "Communicator removed address we did not even have.\n");
6269 // GNUNET_SERVICE_client_drop (tc->client);
6270}
6271
6272
6280static void
6282
6283
6291static void
6292core_env_sent_cb (void *cls)
6293{
6294 struct CoreSentContext *ctx = cls;
6295 struct VirtualLink *vl = ctx->vl;
6296
6297 if (NULL == vl)
6298 {
6299 /* lost the link in the meantime, ignore */
6300 GNUNET_free (ctx);
6301 return;
6302 }
6305 vl->incoming_fc_window_size_ram -= ctx->size;
6306 vl->incoming_fc_window_size_used += ctx->isize;
6308 GNUNET_free (ctx);
6309}
6310
6311
6312static void
6314 const struct GNUNET_MessageHeader *mh,
6315 struct CommunicatorMessageContext *cmc,
6316 unsigned int free_cmc)
6317{
6318 uint16_t size = ntohs (mh->size);
6319 int have_core;
6320
6321 if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
6322 {
6324 "# CORE messages dropped (FC arithmetic overflow)",
6325 1,
6326 GNUNET_NO);
6328 "CORE messages of type %u with %u bytes dropped (FC arithmetic overflow)\n",
6329 (unsigned int) ntohs (mh->type),
6330 (unsigned int) ntohs (mh->size));
6331 if (GNUNET_YES == free_cmc)
6333 return;
6334 }
6336 {
6338 "# CORE messages dropped (FC window overflow)",
6339 1,
6340 GNUNET_NO);
6342 "CORE messages of type %u with %u bytes dropped (FC window overflow)\n",
6343 (unsigned int) ntohs (mh->type),
6344 (unsigned int) ntohs (mh->size));
6345 if (GNUNET_YES == free_cmc)
6347 return;
6348 }
6349
6350 /* Forward to all CORE clients */
6351 have_core = GNUNET_NO;
6352 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
6353 {
6354 struct GNUNET_MQ_Envelope *env;
6355 struct InboundMessage *im;
6356 struct CoreSentContext *ctx;
6357
6358 if (CT_CORE != tc->type)
6359 continue;
6362 ctx = GNUNET_new (struct CoreSentContext);
6363 ctx->vl = vl;
6364 ctx->size = size;
6365 ctx->isize = (GNUNET_NO == have_core) ? size : 0;
6366 have_core = GNUNET_YES;
6369 im->peer = cmc->im.sender;
6370 memcpy (&im[1], mh, size);
6371 GNUNET_MQ_send (tc->mq, env);
6373 }
6374 if (GNUNET_NO == have_core)
6375 {
6377 "Dropped message to CORE: no CORE client connected!\n");
6378 /* Nevertheless, count window as used, as it is from the
6379 perspective of the other peer! */
6381 /* TODO-M1 */
6383 "Dropped message of type %u with %u bytes to CORE: no CORE client connected!\n",
6384 (unsigned int) ntohs (mh->type),
6385 (unsigned int) ntohs (mh->size));
6386 if (GNUNET_YES == free_cmc)
6388 return;
6389 }
6391 "Delivered message from %s of type %u to CORE recv window %d\n",
6392 GNUNET_i2s (&cmc->im.sender),
6393 ntohs (mh->type),
6395 if (vl->core_recv_window > 0)
6396 {
6397 if (GNUNET_YES == free_cmc)
6399 return;
6400 }
6401 /* Wait with calling #finish_cmc_handling(cmc) until the message
6402 was processed by CORE MQs (for CORE flow control)! */
6403 if (GNUNET_YES == free_cmc)
6405}
6406
6407
6416static void
6417handle_raw_message (void *cls, const struct GNUNET_MessageHeader *mh)
6418{
6419 struct CommunicatorMessageContext *cmc = cls;
6420 // struct CommunicatorMessageContext *cmc_copy =
6421 // GNUNET_new (struct CommunicatorMessageContext);
6422 struct GNUNET_MessageHeader *mh_copy;
6423 struct RingBufferEntry *rbe;
6424 struct VirtualLink *vl;
6425 uint16_t size = ntohs (mh->size);
6426
6428 "Handling raw message of type %u with %u bytes\n",
6429 (unsigned int) ntohs (mh->type),
6430 (unsigned int) ntohs (mh->size));
6431
6432 if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
6433 (size < sizeof(struct GNUNET_MessageHeader)))
6434 {
6435 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6436
6437 GNUNET_break (0);
6438 finish_cmc_handling (cmc);
6440 return;
6441 }
6442 vl = lookup_virtual_link (&cmc->im.sender);
6443 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6444 {
6445 /* FIXME: sender is giving us messages for CORE but we don't have
6446 the link up yet! I *suspect* this can happen right now (i.e.
6447 sender has verified us, but we didn't verify sender), but if
6448 we pass this on, CORE would be confused (link down, messages
6449 arrive). We should investigate more if this happens often,
6450 or in a persistent manner, and possibly do "something" about
6451 it. Thus logging as error for now. */
6452
6453 mh_copy = GNUNET_malloc (size);
6454 rbe = GNUNET_new (struct RingBufferEntry);
6455 rbe->cmc = cmc;
6456 /*cmc_copy->tc = cmc->tc;
6457 cmc_copy->im = cmc->im;*/
6458 GNUNET_memcpy (mh_copy, mh, size);
6459
6460 rbe->mh = mh_copy;
6461
6463 {
6464 struct RingBufferEntry *rbe_old = ring_buffer[ring_buffer_head];
6465 GNUNET_free (rbe_old->cmc);
6466 GNUNET_free (rbe_old->mh);
6467 GNUNET_free (rbe_old);
6468 }
6469 ring_buffer[ring_buffer_head] = rbe;// cmc_copy;
6470 // cmc_copy->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6471 cmc->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6473 "Storing message for %s and type %u (%u) in ring buffer head %u is full %u\n",
6474 GNUNET_i2s (&cmc->im.sender),
6475 (unsigned int) ntohs (mh->type),
6476 (unsigned int) ntohs (mh_copy->type),
6480 {
6481 ring_buffer_head = 0;
6483 }
6484 else
6486
6488 "%u items stored in ring buffer\n",
6491
6492 /*GNUNET_break_op (0);
6493 GNUNET_STATISTICS_update (GST_stats,
6494 "# CORE messages dropped (virtual link still down)",
6495 1,
6496 GNUNET_NO);
6497
6498 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6499 "CORE messages of type %u with %u bytes dropped (virtual link still down)\n",
6500 (unsigned int) ntohs (mh->type),
6501 (unsigned int) ntohs (mh->size));
6502 finish_cmc_handling (cmc);*/
6505 // GNUNET_free (cmc);
6506 return;
6507 }
6509}
6510
6511
6519static int
6520check_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
6521{
6522 uint16_t size = ntohs (fb->header.size);
6523 uint16_t bsize = size - sizeof(*fb);
6524
6525 (void) cls;
6526 if (0 == bsize)
6527 {
6528 GNUNET_break_op (0);
6529 return GNUNET_SYSERR;
6530 }
6531 if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
6532 {
6533 GNUNET_break_op (0);
6534 return GNUNET_SYSERR;
6535 }
6536 if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
6537 {
6538 GNUNET_break_op (0);
6539 return GNUNET_SYSERR;
6540 }
6541 return GNUNET_YES;
6542}
6543
6544
6550static void
6551destroy_ack_cummulator (void *cls)
6552{
6553 struct AcknowledgementCummulator *ac = cls;
6554
6555 ac->task = NULL;
6556 GNUNET_assert (0 == ac->num_acks);
6558 GNUNET_YES ==
6560 GNUNET_free (ac);
6561}
6562
6563
6569static void
6571{
6572 struct Neighbour *n;
6573 struct VirtualLink *vl;
6574 struct AcknowledgementCummulator *ac = cls;
6575 char buf[sizeof(struct TransportReliabilityAckMessage)
6576 + ac->num_acks
6578 struct TransportReliabilityAckMessage *ack =
6579 (struct TransportReliabilityAckMessage *) buf;
6581
6582 ac->task = NULL;
6584 "Sending ACK with %u components to %s\n",
6585 ac->num_acks,
6586 GNUNET_i2s (&ac->target));
6587 GNUNET_assert (0 < ac->num_acks);
6589 ack->header.size =
6590 htons (sizeof(*ack)
6591 + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP));
6592 ack->ack_counter = htonl (ac->ack_counter += ac->num_acks);
6593 ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
6594 for (unsigned int i = 0; i < ac->num_acks; i++)
6595 {
6596 ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
6599 }
6600 /*route_control_message_without_fc (
6601 &ac->target,
6602 &ack->header,
6603 RMO_DV_ALLOWED);*/
6604 vl = lookup_virtual_link (&ac->target);
6605 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
6606 {
6608 vl,
6609 &ack->header,
6611 }
6612 else
6613 {
6614 /* Use route via neighbour */
6615 n = lookup_neighbour (&ac->target);
6616 if (NULL != n)
6618 n,
6619 &ack->header,
6620 RMO_NONE);
6621 }
6622 ac->num_acks = 0;
6625 ac);
6626}
6627
6628
6637static void
6639 const struct AcknowledgementUUIDP *ack_uuid,
6640 struct GNUNET_TIME_Absolute max_delay)
6641{
6642 struct AcknowledgementCummulator *ac;
6643
6645 "Scheduling ACK %s for transmission to %s\n",
6646 GNUNET_uuid2s (&ack_uuid->value),
6647 GNUNET_i2s (pid));
6649 if (NULL == ac)
6650 {
6652 ac->target = *pid;
6653 ac->min_transmission_time = max_delay;
6657 &ac->target,
6658 ac,
6660 }
6661 else
6662 {
6663 if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
6664 {
6665 /* must run immediately, ack buffer full! */
6667 }
6671 }
6674 ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
6675 ac->num_acks++;
6678 ac);
6679}
6680
6681
6686{
6691
6695 struct ReassemblyContext *rc;
6696};
6697
6698
6708static int
6709find_by_message_uuid (void *cls, uint32_t key, void *value)
6710{
6711 struct FindByMessageUuidContext *fc = cls;
6712 struct ReassemblyContext *rc = value;
6713
6714 (void) key;
6715 if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
6716 {
6717 fc->rc = rc;
6718 return GNUNET_NO;
6719 }
6720 return GNUNET_YES;
6721}
6722
6723
6731static void
6732handle_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
6733{
6734 struct CommunicatorMessageContext *cmc = cls;
6735 struct VirtualLink *vl;
6736 struct ReassemblyContext *rc;
6737 const struct GNUNET_MessageHeader *msg;
6738 uint16_t msize;
6739 uint16_t fsize;
6740 uint16_t frag_off;
6741 char *target;
6742 struct GNUNET_TIME_Relative cdelay;
6743 struct FindByMessageUuidContext fc;
6744
6745 vl = lookup_virtual_link (&cmc->im.sender);
6746 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6747 {
6748 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6749
6751 "No virtual link for %s to handle fragment\n",
6752 GNUNET_i2s (&cmc->im.sender));
6753 GNUNET_break (0);
6754 finish_cmc_handling (cmc);
6756 return;
6757 }
6758 if (NULL == vl->reassembly_map)
6759 {
6761 vl->reassembly_heap =
6766 vl);
6767 }
6768 msize = ntohs (fb->msg_size);
6769 fc.message_uuid = fb->msg_uuid;
6770 fc.rc = NULL;
6772 fb->msg_uuid.uuid,
6774 &fc);
6775 fsize = ntohs (fb->header.size) - sizeof(*fb);
6776 if (NULL == (rc = fc.rc))
6777 {
6778 rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */
6779 + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
6780 rc->msg_uuid = fb->msg_uuid;
6781 rc->virtual_link = vl;
6782 rc->msg_size = msize;
6783 rc->reassembly_timeout =
6787 rc,
6791 vl->reassembly_map,
6792 rc->msg_uuid.uuid,
6793 rc,
6795 target = (char *) &rc[1];
6796 rc->bitfield = (uint8_t *) (target + rc->msg_size);
6797 if (fsize != rc->msg_size)
6798 rc->msg_missing = rc->msg_size;
6799 else
6800 rc->msg_missing = 0;
6802 "Received fragment with size %u at offset %u/%u %u bytes missing from %s for NEW message %"
6803 PRIu64 "\n",
6804 fsize,
6805 ntohs (fb->frag_off),
6806 msize,
6807 rc->msg_missing,
6808 GNUNET_i2s (&cmc->im.sender),
6809 fb->msg_uuid.uuid);
6810 }
6811 else
6812 {
6813 target = (char *) &rc[1];
6815 "Received fragment at offset %u/%u from %s for message %u\n",
6816 ntohs (fb->frag_off),
6817 msize,
6818 GNUNET_i2s (&cmc->im.sender),
6819 (unsigned int) fb->msg_uuid.uuid);
6820 }
6821 if (msize != rc->msg_size)
6822 {
6823 GNUNET_break (0);
6824 finish_cmc_handling (cmc);
6825 return;
6826 }
6827
6828 /* reassemble */
6829 if (0 == fsize)
6830 {
6831 GNUNET_break (0);
6832 finish_cmc_handling (cmc);
6833 return;
6834 }
6835 frag_off = ntohs (fb->frag_off);
6836 if (frag_off + fsize > msize)
6837 {
6838 /* Fragment (plus fragment size) exceeds message size! */
6839 GNUNET_break_op (0);
6840 finish_cmc_handling (cmc);
6841 return;
6842 }
6843 memcpy (&target[frag_off], &fb[1], fsize);
6844 /* update bitfield and msg_missing */
6845 for (unsigned int i = frag_off; i < frag_off + fsize; i++)
6846 {
6847 if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
6848 {
6849 rc->bitfield[i / 8] |= (1 << (i % 8));
6850 rc->msg_missing--;
6851 }
6852 }
6853
6854 /* Compute cumulative ACK */
6856 cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
6857 if (0 == rc->msg_missing)
6858 cdelay = GNUNET_TIME_UNIT_ZERO;
6859 cummulative_ack (&cmc->im.sender,
6860 &fb->ack_uuid,
6863 /* is reassembly complete? */
6864 if (0 != rc->msg_missing)
6865 {
6866 finish_cmc_handling (cmc);
6867 return;
6868 }
6869 /* reassembly is complete, verify result */
6870 msg = (const struct GNUNET_MessageHeader *) &rc[1];
6871 if (ntohs (msg->size) != rc->msg_size)
6872 {
6873 GNUNET_break (0);
6875 finish_cmc_handling (cmc);
6876 return;
6877 }
6878 /* successful reassembly */
6880 "Fragment reassembly complete for message %u\n",
6881 (unsigned int) fb->msg_uuid.uuid);
6882 /* FIXME: check that the resulting msg is NOT a
6883 DV Box or Reliability Box, as that is NOT allowed! */
6884 cmc->mh = msg;
6886 /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
6887 en-route and we forget that we finished this reassembly immediately!
6888 -> keep around until timeout?
6889 -> shorten timeout based on ACK? */
6891}
6892
6893
6901static int
6902check_reliability_box (void *cls,
6903 const struct TransportReliabilityBoxMessage *rb)
6904{
6905 const struct GNUNET_MessageHeader *box = (const struct
6906 GNUNET_MessageHeader *) &rb[1];
6907 (void) cls;
6908
6910 "check_send_msg with size %u: inner msg type %u and size %u (%lu %lu)\n",
6911 ntohs (rb->header.size),
6912 ntohs (box->type),
6913 ntohs (box->size),
6914 sizeof (struct TransportReliabilityBoxMessage),
6915 sizeof (struct GNUNET_MessageHeader));
6917 return GNUNET_YES;
6918}
6919
6920
6928static void
6929handle_reliability_box (void *cls,
6930 const struct TransportReliabilityBoxMessage *rb)
6931{
6932 struct CommunicatorMessageContext *cmc = cls;
6933 const struct GNUNET_MessageHeader *inbox =
6934 (const struct GNUNET_MessageHeader *) &rb[1];
6935 struct GNUNET_TIME_Relative rtt;
6936
6938 "Received reliability box from %s with UUID %s of type %u\n",
6939 GNUNET_i2s (&cmc->im.sender),
6941 (unsigned int) ntohs (inbox->type));
6942 rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
6943 do not really have an RTT for the
6944 * incoming* queue (should we have
6945 the sender add it to the rb message?) */
6947 &cmc->im.sender,
6948 &rb->ack_uuid,
6949 (0 == ntohl (rb->ack_countdown))
6952 GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
6953 /* continue with inner message */
6954 /* FIXME: check that inbox is NOT a DV Box, fragment or another
6955 reliability box (not allowed!) */
6956 cmc->mh = inbox;
6958}
6959
6960
6969static void
6970update_pd_age (struct PerformanceData *pd, unsigned int age)
6971{
6972 unsigned int sage;
6973
6974 if (age == pd->last_age)
6975 return; /* nothing to do */
6976 sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
6977 for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
6978 {
6979 struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
6980
6981 the->bytes_sent = 0;
6982 the->bytes_received = 0;
6983 }
6984 pd->last_age = age;
6985}
6986
6987
6996static void
6998 struct GNUNET_TIME_Relative rtt,
6999 uint16_t bytes_transmitted_ok)
7000{
7001 uint64_t nval = rtt.rel_value_us;
7002 uint64_t oval = pd->aged_rtt.rel_value_us;
7003 unsigned int age = get_age ();
7004 struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
7005
7006 if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
7007 pd->aged_rtt = rtt;
7008 else
7009 pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
7010 update_pd_age (pd, age);
7011 the->bytes_received += bytes_transmitted_ok;
7012}
7013
7014
7022static void
7024 struct GNUNET_TIME_Relative rtt,
7025 uint16_t bytes_transmitted_ok)
7026{
7027 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
7028}
7029
7030
7038static void
7040 struct GNUNET_TIME_Relative rtt,
7041 uint16_t bytes_transmitted_ok)
7042{
7043 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
7044}
7045
7046
7054static void
7056{
7057 struct PendingMessage *pos;
7058
7060 "Complete transmission of message %" PRIu64 " %u\n",
7061 pm->logging_uuid,
7062 pm->pmt);
7063 switch (pm->pmt)
7064 {
7065 case PMT_CORE:
7067 /* Full message sent, we are done */
7069 return;
7070
7071 case PMT_FRAGMENT_BOX:
7072 /* Fragment sent over reliable channel */
7073 pos = pm->frag_parent;
7077 "pos frag_off %lu pos bytes_msg %lu pmt %u parent %u\n",
7078 (unsigned long) pos->frag_off,
7079 (unsigned long) pos->bytes_msg,
7080 pos->pmt,
7081 NULL == pos->frag_parent ? 1 : 0);
7082 /* check if subtree is done */
7083 while ((NULL == pos->head_frag) && (pos->frag_off == (pos->bytes_msg
7084 - sizeof(struct
7086 &&
7087 (NULL != pos->frag_parent))
7088 {
7089 pm = pos;
7090 pos = pm->frag_parent;
7091 if ((NULL == pos) && (PMT_DV_BOX == pm->pmt))
7092 {
7094 return;
7095 }
7096 else if (PMT_DV_BOX == pm->pmt)
7097 {
7099 return;
7100 }
7103 }
7104
7105 /* Was this the last applicable fragment? */
7106 if ((NULL == pos->head_frag) && (NULL == pos->frag_parent || PMT_DV_BOX ==
7107 pos->pmt) &&
7108 (pos->frag_off == pos->bytes_msg))
7110 return;
7111
7112 case PMT_DV_BOX:
7114 "Completed transmission of message %" PRIu64 " (DV Box)\n",
7115 pm->logging_uuid);
7116 if (NULL != pm->frag_parent)
7117 {
7118 pos = pm->frag_parent;
7120 pos->bpm = NULL;
7122 }
7123 else
7125 return;
7126 }
7127}
7128
7129
7137static void
7139 struct GNUNET_TIME_Relative ack_delay)
7140{
7141 struct GNUNET_TIME_Relative delay;
7142
7144 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
7145 if (NULL != pa->queue && 1 == pa->num_send)
7147 if (NULL != pa->dvh && 1 == pa->num_send)
7148 update_dvh_performance (pa->dvh, delay, pa->message_size);
7149 if (NULL != pa->pm)
7152}
7153
7154
7162static int
7163check_reliability_ack (void *cls,
7164 const struct TransportReliabilityAckMessage *ra)
7165{
7166 unsigned int n_acks;
7167
7168 (void) cls;
7169 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7170 / sizeof(struct TransportCummulativeAckPayloadP);
7171 if (0 == n_acks)
7172 {
7173 GNUNET_break_op (0);
7174 return GNUNET_SYSERR;
7175 }
7176 if ((ntohs (ra->header.size) - sizeof(*ra)) !=
7177 n_acks * sizeof(struct TransportCummulativeAckPayloadP))
7178 {
7179 GNUNET_break_op (0);
7180 return GNUNET_SYSERR;
7181 }
7182 return GNUNET_OK;
7183}
7184
7185
7193static void
7194handle_reliability_ack (void *cls,
7195 const struct TransportReliabilityAckMessage *ra)
7196{
7197 struct CommunicatorMessageContext *cmc = cls;
7198 const struct TransportCummulativeAckPayloadP *ack;
7199 unsigned int n_acks;
7200 uint32_t ack_counter;
7201
7202 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7203 / sizeof(struct TransportCummulativeAckPayloadP);
7204 ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
7205 for (unsigned int i = 0; i < n_acks; i++)
7206 {
7207 struct PendingAcknowledgement *pa =
7209 if (NULL == pa)
7210 {
7212 "Received ACK from %s with UUID %s which is unknown to us!\n",
7213 GNUNET_i2s (&cmc->im.sender),
7214 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7216 GST_stats,
7217 "# FRAGMENT_ACKS dropped, no matching pending message",
7218 1,
7219 GNUNET_NO);
7220 continue;
7221 }
7223 "Received ACK from %s with UUID %s\n",
7224 GNUNET_i2s (&cmc->im.sender),
7225 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7226 handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
7227 }
7228
7229 ack_counter = htonl (ra->ack_counter);
7230 (void) ack_counter; /* silence compiler warning for now */
7231 // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
7232 // (DV and/or Neighbour?)
7233 finish_cmc_handling (cmc);
7234}
7235
7236
7244static int
7246 void *cls,
7248{
7249 uint16_t size = ntohs (be->header.size) - sizeof(*be);
7250 const struct GNUNET_MessageHeader *inbox =
7251 (const struct GNUNET_MessageHeader *) &be[1];
7252 const char *is;
7253 uint16_t isize;
7254
7255 (void) cls;
7256 if (ntohs (inbox->size) >= size)
7257 {
7258 GNUNET_break_op (0);
7259 return GNUNET_SYSERR;
7260 }
7261 isize = ntohs (inbox->size);
7262 is = ((const char *) inbox) + isize;
7263 size -= isize;
7264 if ('\0' != is[size - 1])
7265 {
7266 GNUNET_break_op (0);
7267 return GNUNET_SYSERR;
7268 }
7269 return GNUNET_YES;
7270}
7271
7272
7281static void
7283 void *cls,
7285{
7286 const struct GNUNET_PeerIdentity *my_identity;
7287 struct CommunicatorMessageContext *cmc = cls;
7289 struct GNUNET_MQ_Envelope *env;
7290 struct TransportClient *tc;
7291 const struct GNUNET_MessageHeader *inbox =
7292 (const struct GNUNET_MessageHeader *) &be[1];
7293 uint16_t isize = ntohs (inbox->size);
7294 const char *target_communicator = ((const char *) inbox) + isize;
7295 char *sender;
7296 char *self;
7297
7300
7301 GNUNET_asprintf (&sender,
7302 "%s",
7303 GNUNET_i2s (&cmc->im.sender));
7304 GNUNET_asprintf (&self,
7305 "%s",
7307
7308 /* Find client providing this communicator */
7309 for (tc = clients_head; NULL != tc; tc = tc->next)
7310 if ((CT_COMMUNICATOR == tc->type) &&
7311 (0 ==
7312 strcmp (tc->details.communicator.address_prefix, target_communicator)))
7313 break;
7314 if (NULL == tc)
7315 {
7316 char *stastr;
7317
7319 &stastr,
7320 "# Backchannel message dropped: target communicator `%s' unknown",
7321 target_communicator);
7323 GNUNET_free (stastr);
7324 finish_cmc_handling (cmc);
7325 return;
7326 }
7327 /* Finally, deliver backchannel message to communicator */
7329 "Delivering backchannel message from %s to %s of type %u to %s\n",
7330 sender,
7331 self,
7332 ntohs (inbox->type),
7333 target_communicator);
7335 cbi,
7336 isize,
7338 cbi->pid = cmc->im.sender;
7339 memcpy (&cbi[1], inbox, isize);
7340 GNUNET_MQ_send (tc->mq, env);
7341 finish_cmc_handling (cmc);
7342}
7343
7344
7354static void
7355path_cleanup_cb (void *cls)
7356{
7357 struct DistanceVector *dv = cls;
7358 struct DistanceVectorHop *pos;
7359
7360 dv->timeout_task = NULL;
7361 while (NULL != (pos = dv->dv_head))
7362 {
7363 GNUNET_assert (dv == pos->dv);
7365 break;
7367 }
7368 if (NULL == pos)
7369 {
7370 free_dv_route (dv);
7371 return;
7372 }
7373 dv->timeout_task =
7375}
7376
7377
7378static void
7380{
7381
7382 const struct GNUNET_PeerIdentity target = vl->target;
7383
7384
7386 {
7387 struct RingBufferEntry *ring_buffer_copy[RING_BUFFER_SIZE];
7388 unsigned int tail = GNUNET_YES == is_ring_buffer_full ? ring_buffer_head :
7389 0;
7390 unsigned int head = GNUNET_YES == is_ring_buffer_full ? RING_BUFFER_SIZE :
7393 struct CommunicatorMessageContext *cmc;
7394 struct RingBufferEntry *rbe;
7395 struct GNUNET_MessageHeader *mh;
7396
7398 "Sending from ring buffer, which has %u items\n",
7399 head);
7400
7401 ring_buffer_head = 0;
7402 for (unsigned int i = 0; i < head; i++)
7403 {
7404 rbe = ring_buffer[(i + tail) % RING_BUFFER_SIZE];
7405 cmc = rbe->cmc;
7406 mh = rbe->mh;
7407
7408 im = cmc->im;
7409 // mh = cmc->mh;
7411 "Sending message of type %u to ring buffer target %s using vl target %s index %u\n",
7412 mh->type,
7413 GNUNET_i2s (&im.sender),
7414 GNUNET_i2s2 (&target),
7415 (i + tail) % RING_BUFFER_SIZE);
7416 if (0 == GNUNET_memcmp (&target, &im.sender))
7417 {
7419 "Finish handling message of type %u and size %u\n",
7420 (unsigned int) ntohs (mh->type),
7421 (unsigned int) ntohs (mh->size));
7423 GNUNET_free (mh);
7424 GNUNET_free (rbe->cmc);
7425 GNUNET_free (rbe);
7426 }
7427 else
7428 {
7429 ring_buffer_copy[ring_buffer_head] = rbe;
7431 }
7432 }
7433
7436 {
7438 }
7439
7440 for (unsigned int i = 0; i < ring_buffer_head; i++)
7441 {
7442 ring_buffer[i] = ring_buffer_copy[i];
7444 "ring_buffer_copy[i]->mh->type for i %u %u\n",
7445 i,
7446 ring_buffer_copy[i]->mh->type);
7448 "ring_buffer[i]->mh->type for i %u %u\n",
7449 i,
7450 ring_buffer[i]->mh->type);
7451 }
7452
7454 "%u items still in ring buffer\n",
7456 }
7457
7459 {
7460 struct PendingMessage *ring_buffer_dv_copy[RING_BUFFER_SIZE];
7461 struct PendingMessage *pm;
7462 unsigned int tail = GNUNET_YES == is_ring_buffer_dv_full ?
7464 0;
7465 unsigned int head = GNUNET_YES == is_ring_buffer_dv_full ?
7468
7470 "Sending from ring buffer dv, which has %u items\n",
7471 head);
7472
7474 for (unsigned int i = 0; i < head; i++)
7475 {
7476 pm = ring_buffer_dv[(i + tail) % RING_BUFFER_SIZE];
7477
7479 "Sending to ring buffer target %s using vl target %s\n",
7480 GNUNET_i2s (&pm->target),
7481 GNUNET_i2s2 (&target));
7482 if (0 == GNUNET_memcmp (&target, &pm->target))
7483 {
7485 "Adding PendingMessage to vl, checking transmission.\n");
7486 pm->vl = vl;
7490 pm);
7491
7493 }
7494 else
7495 {
7496 ring_buffer_dv_copy[ring_buffer_dv_head] = pm;
7498 }
7499 }
7500
7502 {
7504 }
7505
7506 for (unsigned int i = 0; i < ring_buffer_dv_head; i++)
7507 ring_buffer_dv[i] = ring_buffer_dv_copy[i];
7508
7510 "%u items still in ring buffer dv.\n",
7512
7513 }
7514}
7515
7516
7524static void
7526{
7527 struct DistanceVector *dv = hop->dv;
7528 struct VirtualLink *vl;
7529
7530 vl = lookup_virtual_link (&dv->target);
7531 if (NULL == vl)
7532 {
7533
7534 vl = GNUNET_new (struct VirtualLink);
7536 "Creating new virtual link %p to %s using DV!\n",
7537 vl,
7538 GNUNET_i2s (&dv->target));
7539 vl->burst_addr = NULL;
7540 vl->confirmed = GNUNET_YES;
7541 vl->message_uuid_ctr =
7542 GNUNET_CRYPTO_random_u64 (UINT64_MAX);
7543 vl->target = dv->target;
7549 links,
7550 &vl->target,
7551 vl,
7553 vl->dv = dv;
7554 dv->vl = vl;
7555 vl->visibility_task =
7558 /* We lacked a confirmed connection to the target
7559 before, so tell CORE about it (finally!) */
7562 }
7563 else
7564 {
7565 /* Link was already up, remember dv is also now available and we are done */
7566 vl->dv = dv;
7567 dv->vl = vl;
7568 if (GNUNET_NO == vl->confirmed)
7569 {
7570 vl->confirmed = GNUNET_YES;
7571 vl->visibility_task =
7574 /* We lacked a confirmed connection to the target
7575 before, so tell CORE about it (finally!) */
7578 }
7579 else
7581 "Virtual link to %s could now also use DV!\n",
7582 GNUNET_i2s (&dv->target));
7583 }
7584}
7585
7586
7612static int
7613learn_dv_path (const struct GNUNET_PeerIdentity *path,
7614 unsigned int path_len,
7615 struct GNUNET_TIME_Relative network_latency,
7616 struct GNUNET_TIME_Absolute path_valid_until)
7617{
7618 const struct GNUNET_PeerIdentity *my_identity;
7619 struct DistanceVectorHop *hop;
7620 struct DistanceVector *dv;
7621 struct Neighbour *next_hop;
7622 unsigned int shorter_distance;
7623
7624 if (path_len < 3)
7625 {
7626 /* what a boring path! not allowed! */
7627 GNUNET_break (0);
7628 return GNUNET_SYSERR;
7629 }
7630
7633
7634 GNUNET_assert (0 == GNUNET_memcmp (my_identity, &path[0]));
7635 next_hop = lookup_neighbour (&path[1]);
7636 if (NULL == next_hop)
7637 {
7638 /* next hop must be a neighbour, otherwise this whole thing is useless! */
7639 GNUNET_break (0);
7640 return GNUNET_SYSERR;
7641 }
7642 for (unsigned int i = 2; i < path_len; i++)
7643 {
7644 struct Neighbour *n = lookup_neighbour (&path[i]);
7645 struct GNUNET_TIME_Absolute q_timeout;
7646
7647 if (NULL != n)
7648 {
7649 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
7650 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
7651 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
7653 "remaining %lu to %s\n",
7654 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout)
7655 .rel_value_us,
7656 GNUNET_i2s (&n->pid));
7657 if (0 != GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
7658 {
7659 /* Useless path: we have a direct active connection to some hop
7660 in the middle of the path, so this one is not even
7661 terribly useful for redundancy */
7663 "Path of %u hops useless: directly link to hop %u (%s)\n",
7664 path_len,
7665 i,
7666 GNUNET_i2s (&path[i]));
7668 "# Useless DV path ignored: hop is neighbour",
7669 1,
7670 GNUNET_NO);
7671 return GNUNET_SYSERR;
7672 }
7673 }
7674 }
7675 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
7676 if (NULL == dv)
7677 {
7678 dv = GNUNET_new (struct DistanceVector);
7679 dv->target = path[path_len - 1];
7682 dv);
7685 dv_routes,
7686 &dv->target,
7687 dv,
7689 }
7690 /* Check if we have this path already! */
7691 shorter_distance = 0;
7692 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
7693 pos = pos->next_dv)
7694 {
7695 if (pos->distance < path_len - 3)
7696 shorter_distance++;
7697 /* Note that the distances in 'pos' excludes us (path[0]),
7698 the next_hop (path[1]) and the target so we need to subtract three
7699 and check next_hop explicitly */
7700 if ((pos->distance == path_len - 3) && (pos->next_hop == next_hop))
7701 {
7702 int match = GNUNET_YES;
7703
7704 for (unsigned int i = 0; i < pos->distance; i++)
7705 {
7706 if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
7707 {
7708 match = GNUNET_NO;
7709 break;
7710 }
7711 }
7712 if (GNUNET_YES == match)
7713 {
7714 struct GNUNET_TIME_Relative last_timeout;
7715
7716 /* Re-discovered known path, update timeout */
7718 "# Known DV path refreshed",
7719 1,
7720 GNUNET_NO);
7721 last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
7722 pos->timeout =
7724 pos->path_valid_until =
7725 GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
7726 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
7727 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
7728 if (0 <
7731 if (last_timeout.rel_value_us <
7734 .rel_value_us)
7735 {
7736 /* Some peer send DV learn messages too often, we are learning
7737 the same path faster than it would be useful; do not forward! */
7739 "Rediscovered path too quickly, not forwarding further\n")
7740 ;
7741 return GNUNET_NO;
7742 }
7744 "Refreshed known path to %s valid until %s, forwarding further\n",
7745 GNUNET_i2s (&dv->target),
7747 pos->path_valid_until));
7748 return GNUNET_YES;
7749 }
7750 }
7751 }
7752 /* Count how many shorter paths we have (incl. direct
7753 neighbours) before simply giving up on this one! */
7754 if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
7755 {
7756 /* We have a shorter path already! */
7758 "Have many shorter DV paths %s, not forwarding further\n",
7759 GNUNET_i2s (&dv->target));
7760 return GNUNET_NO;
7761 }
7762 /* create new DV path entry */
7764 "Discovered new DV path to %s valid until %s\n",
7765 GNUNET_i2s (&dv->target),
7766 GNUNET_STRINGS_absolute_time_to_string (path_valid_until));
7767 hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
7768 + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7769 hop->next_hop = next_hop;
7770 hop->dv = dv;
7771 hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
7772 memcpy (&hop[1],
7773 &path[2],
7774 sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7776 hop->path_valid_until = path_valid_until;
7777 hop->distance = path_len - 3;
7778 hop->pd.aged_rtt = network_latency;
7779 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
7781 next_hop->dv_head,
7782 next_hop->dv_tail,
7783 hop);
7784 if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
7786 return GNUNET_YES;
7787}
7788
7789
7797static int
7798check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
7799{
7800 const struct GNUNET_PeerIdentity *my_identity;
7801 uint16_t size = ntohs (dvl->header.size);
7802 uint16_t num_hops = ntohs (dvl->num_hops);
7803 const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
7804
7805 (void) cls;
7806 if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
7807 {
7808 GNUNET_break_op (0);
7809 return GNUNET_SYSERR;
7810 }
7811 if (num_hops > MAX_DV_HOPS_ALLOWED)
7812 {
7813 GNUNET_break_op (0);
7814 return GNUNET_SYSERR;
7815 }
7816
7819
7820 for (unsigned int i = 0; i < num_hops; i++)
7821 {
7822 if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
7823 {
7824 GNUNET_break_op (0);
7825 return GNUNET_SYSERR;
7826 }
7827 if (0 == GNUNET_memcmp (my_identity, &hops[i].hop))
7828 {
7829 GNUNET_break_op (0);
7830 return GNUNET_SYSERR;
7831 }
7832 }
7833 return GNUNET_YES;
7834}
7835
7836
7837struct SignDhpCls
7838{
7839 struct DVPathEntryP *dhops;
7840 uint16_t nhops;
7841 const struct GNUNET_PeerIdentity *next_hop;
7843 struct PilsRequest *pr;
7844};
7845
7846
7847static void
7848sign_dhp_cp (void *cls,
7849 const struct GNUNET_PeerIdentity *pid,
7850 const struct GNUNET_CRYPTO_EddsaSignature *sig)
7851{
7852 struct SignDhpCls *sign_dhp_cls = cls;
7853 struct VirtualLink *vl;
7854 struct DVPathEntryP *dhops = sign_dhp_cls->dhops;
7855 uint16_t nhops = sign_dhp_cls->nhops;
7856 const struct GNUNET_PeerIdentity *next_hop = sign_dhp_cls->next_hop;
7857 struct TransportDVLearnMessage *fwd = sign_dhp_cls->fwd;
7858 struct Neighbour *n;
7859
7860 sign_dhp_cls->pr->op = NULL;
7863 sign_dhp_cls->pr);
7864 GNUNET_free (sign_dhp_cls->pr);
7865 dhops[nhops].hop_sig = *sig;
7866
7867 /*route_control_message_without_fc (next_hop,
7868 &fwd->header,
7869 RMO_UNCONFIRMED_ALLOWED);*/
7870 vl = lookup_virtual_link (next_hop);
7871 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
7872 {
7874 &fwd->header,
7876 }
7877 else
7878 {
7879 /* Use route via neighbour */
7880 n = lookup_neighbour (next_hop);
7881 if (NULL != n)
7883 n,
7884 &fwd->header,
7886 }
7887 GNUNET_free (sign_dhp_cls);
7888}
7889
7890
7902static void
7903forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop,
7904 const struct TransportDVLearnMessage *msg,
7905 uint16_t bi_history,
7906 uint16_t nhops,
7907 const struct DVPathEntryP *hops,
7908 struct GNUNET_TIME_Absolute in_time)
7909{
7910 struct DVPathEntryP *dhops;
7911 char buf[sizeof(struct TransportDVLearnMessage)
7912 + (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
7913 struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
7914 struct GNUNET_TIME_Relative nnd;
7915 const struct GNUNET_PeerIdentity *my_identity;
7916
7917 /* compute message for forwarding */
7919 "Forwarding DV learn message originating from %s to %s\n",
7920 GNUNET_i2s (&msg->initiator),
7921 GNUNET_i2s2 (next_hop));
7924 fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
7925 + (nhops + 1) * sizeof(struct DVPathEntryP));
7926 fwd->num_hops = htons (nhops + 1);
7927 fwd->bidirectional = htons (bi_history);
7930 msg->non_network_delay));
7932 fwd->init_sig = msg->init_sig;
7933 fwd->initiator = msg->initiator;
7934 fwd->challenge = msg->challenge;
7935 fwd->monotonic_time = msg->monotonic_time;
7936
7939
7940 dhops = (struct DVPathEntryP *) &fwd[1];
7941 GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
7942 dhops[nhops].hop = *my_identity;
7943 {
7944 struct DvHopPS dhp = {
7946 .purpose.size = htonl (sizeof(dhp)),
7947 .pred = (0 == nhops) ? msg->initiator : dhops[nhops - 1].hop,
7948 .succ = *next_hop,
7950 };
7951 struct SignDhpCls *sign_dhp_cls = GNUNET_new (struct SignDhpCls);
7952 sign_dhp_cls->dhops = dhops;
7953 sign_dhp_cls->nhops = nhops;
7954 sign_dhp_cls->next_hop = next_hop;
7955 sign_dhp_cls->fwd = fwd;
7956 sign_dhp_cls->pr = GNUNET_new (struct PilsRequest);
7959 sign_dhp_cls->pr);
7960 sign_dhp_cls->pr->op =
7962 &dhp.purpose,
7964 sign_dhp_cls);
7965 }
7966}
7967
7968
7978static int
7980 struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
7981 const struct GNUNET_PeerIdentity *init,
7982 const struct GNUNET_CRYPTO_ChallengeNonceP *challenge,
7983 const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
7984{
7985 struct DvInitPS ip = { .purpose.purpose = htonl (
7987 .purpose.size = htonl (sizeof(ip)),
7988 .monotonic_time = sender_monotonic_time,
7989 .challenge = *challenge };
7990
7991 if (
7992 GNUNET_OK !=
7994 &ip,
7995 init_sig,
7996 &init->public_key))
7997 {
7998 GNUNET_break_op (0);
7999 return GNUNET_SYSERR;
8000 }
8001 return GNUNET_OK;
8002}
8003
8004
8009{
8013 const struct TransportDVLearnMessage *dvl;
8014
8018 const struct DVPathEntryP *hops;
8019
8024
8029
8033 unsigned int num_eligible;
8034
8038 unsigned int num_selections;
8039
8043 uint16_t nhops;
8044
8048 uint16_t bi_history;
8049};
8050
8051
8060static int
8061dv_neighbour_selection (void *cls,
8062 const struct GNUNET_PeerIdentity *pid,
8063 void *value)
8064{
8065 struct NeighbourSelectionContext *nsc = cls;
8066
8067 (void) value;
8068 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8069 return GNUNET_YES; /* skip initiator */
8070 for (unsigned int i = 0; i < nsc->nhops; i++)
8071 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8072 return GNUNET_YES;
8073 /* skip peers on path */
8074 nsc->num_eligible++;
8075 return GNUNET_YES;
8076}
8077
8078
8089static int
8090dv_neighbour_transmission (void *cls,
8091 const struct GNUNET_PeerIdentity *pid,
8092 void *value)
8093{
8094 struct NeighbourSelectionContext *nsc = cls;
8095
8097 "transmission %s\n",
8098 GNUNET_i2s (pid));
8099 (void) value;
8100 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8101 return GNUNET_YES; /* skip initiator */
8102 for (unsigned int i = 0; i < nsc->nhops; i++)
8103 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8104 return GNUNET_YES;
8105 /* skip peers on path */
8106 for (unsigned int i = 0; i < nsc->num_selections; i++)
8107 {
8108 if (nsc->selections[i] == nsc->num_eligible)
8109 {
8111 nsc->dvl,
8112 nsc->bi_history,
8113 nsc->nhops,
8114 nsc->hops,
8115 nsc->in_time);
8116 break;
8117 }
8118 }
8119 nsc->num_eligible++;
8120 return GNUNET_YES;
8121}
8122
8123
8167static unsigned int
8168calculate_fork_degree (unsigned int hops_taken,
8169 unsigned int neighbour_count,
8170 unsigned int eligible_count)
8171{
8172 double target_total = 50.0; /* FIXME: use LOG(NSE)? */
8173 double eligible_ratio =
8174 ((double) eligible_count) / ((double) neighbour_count);
8175 double boost_factor = eligible_ratio * eligible_ratio;
8176 unsigned int rnd;
8177 double left;
8178
8179 if (hops_taken >= 64)
8180 {
8181 GNUNET_break (0);
8182 return 0; /* precaution given bitshift below */
8183 }
8184 for (unsigned int i = 1; i < hops_taken; i++)
8185 {
8186 /* For each hop, subtract the expected number of targets
8187 reached at distance d (so what remains divided by 2^d) */
8188 target_total -= (target_total * boost_factor / (1LLU << i));
8189 }
8190 rnd =
8191 (unsigned int) floor (target_total * boost_factor / (1LLU << hops_taken));
8192 /* round up or down probabilistically depending on how close we were
8193 when floor()ing to rnd */
8194 left = target_total - (double) rnd;
8195 if (UINT32_MAX * left >
8196 GNUNET_CRYPTO_random_u64 (UINT32_MAX))
8197 rnd++; /* round up */
8199 "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
8200 hops_taken,
8201 rnd,
8202 eligible_count,
8203 neighbour_count);
8204 return rnd;
8205}
8206
8207
8214static void
8215neighbour_store_dvmono_cb (void *cls, int success)
8216{
8217 struct Neighbour *n = cls;
8218
8219 n->sc = NULL;
8220 if (GNUNET_YES != success)
8222 "Failed to store other peer's monotonic time in peerstore!\n");
8223}
8224
8225
8226static struct GNUNET_TIME_Relative
8228{
8229 struct GNUNET_TIME_Relative host_latency_sum;
8230 struct GNUNET_TIME_Relative latency;
8231 struct GNUNET_TIME_Relative network_latency;
8232 uint16_t nhops = ntohs (dvl->num_hops);;
8233
8234 /* We initiated this, learn the forward path! */
8235 host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
8236
8237 // Need also something to lookup initiation time
8238 // to compute RTT! -> add RTT argument here?
8240 dvl->monotonic_time));
8241 GNUNET_assert (latency.rel_value_us >= host_latency_sum.rel_value_us);
8242 // latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
8243 // (based on dvl->challenge, we can identify time of origin!)
8244
8245 network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
8246 /* assumption: latency on all links is the same */
8247 network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
8248
8249 return network_latency;
8250}
8251
8252
8260static void
8261handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
8262{
8263 struct CommunicatorMessageContext *cmc = cls;
8265 int bi_hop;
8266 uint16_t nhops;
8267 uint16_t bi_history;
8268 const struct DVPathEntryP *hops;
8269 int do_fwd;
8270 int did_initiator;
8271 struct GNUNET_TIME_Absolute in_time;
8272 struct Neighbour *n;
8273 const struct GNUNET_PeerIdentity *my_identity;
8274
8275 nhops = ntohs (dvl->num_hops); /* 0 = sender is initiator */
8276 bi_history = ntohs (dvl->bidirectional);
8277 hops = (const struct DVPathEntryP *) &dvl[1];
8278 if (0 == nhops)
8279 {
8280 /* sanity check */
8281 if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
8282 {
8283 GNUNET_break (0);
8284 finish_cmc_handling (cmc);
8285 return;
8286 }
8287 }
8288 else
8289 {
8291 "handle dv learn message last hop %s\n",
8292 GNUNET_i2s (&hops[nhops - 1].hop));
8293 /* sanity check */
8294 if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
8295 {
8296 GNUNET_break (0);
8297 finish_cmc_handling (cmc);
8298 return;
8299 }
8300 }
8301
8303 cc = cmc->tc->details.communicator.cc;
8304 bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
8305 cc); // FIXME: add bi-directional flag to cc?
8306 in_time = GNUNET_TIME_absolute_get ();
8307
8308 /* continue communicator here, everything else can happen asynchronous! */
8309 finish_cmc_handling (cmc);
8310
8311 n = lookup_neighbour (&dvl->initiator);
8312 if (NULL != n)
8313 {
8314 if ((n->dv_monotime_available == GNUNET_YES) &&
8317 {
8319 "DV learn from %s discarded due to time travel",
8320 GNUNET_i2s (&dvl->initiator));
8322 "# DV learn discarded due to time travel",
8323 1,
8324 GNUNET_NO);
8325 return;
8326 }
8328 &dvl->initiator,
8329 &dvl->challenge,
8330 &dvl->init_sig))
8331 {
8333 "DV learn signature from %s invalid\n",
8334 GNUNET_i2s (&dvl->initiator));
8335 GNUNET_break_op (0);
8336 return;
8337 }
8340 {
8341 if (NULL != n->sc)
8342 {
8344 "store cancel\n");
8346 }
8347 n->sc =
8349 "transport",
8350 &dvl->initiator,
8352 &dvl->monotonic_time,
8353 sizeof(dvl->monotonic_time),
8357 n);
8358 }
8359 }
8360
8363
8364 /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
8365 If signature verification load too high, implement random drop strategy */
8366 for (unsigned int i = 0; i < nhops; i++)
8367 {
8368 struct DvHopPS dhp = { .purpose.purpose =
8370 .purpose.size = htonl (sizeof(dhp)),
8371 .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
8372 .succ = (nhops == i + 1) ? *my_identity
8373 : hops[i + 1].hop,
8374 .challenge = dvl->challenge };
8375
8376 if (GNUNET_OK !=
8378 &dhp,
8379 &hops[i].hop_sig,
8380 &hops[i].hop.public_key))
8381 {
8383 "DV learn from %s signature of hop %u invalid\n",
8384 GNUNET_i2s (&dvl->initiator),
8385 i);
8387 "signature of hop %s invalid\n",
8388 GNUNET_i2s (&hops[i].hop));
8390 "pred %s\n",
8391 GNUNET_i2s (&dhp.pred));
8393 "succ %s\n",
8394 GNUNET_i2s (&dhp.succ));
8396 "hash %s\n",
8397 GNUNET_sh2s (&dhp.challenge.value));
8398 GNUNET_break_op (0);
8399 return;
8400 }
8401 }
8402 if (GNUNET_EXTRA_LOGGING > 0)
8403 {
8404 char *path;
8405
8406 path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
8407 for (unsigned int i = 0; i < nhops; i++)
8408 {
8409 char *tmp;
8410
8411 GNUNET_asprintf (&tmp,
8412 "%s%s%s",
8413 path,
8414 (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
8415 GNUNET_i2s (&hops[i].hop));
8416 GNUNET_free (path);
8417 path = tmp;
8418 }
8420 "Received DVInit via %s%s%s\n",
8421 path,
8422 bi_hop ? "<->" : "-->",
8424 GNUNET_free (path);
8425 }
8426 do_fwd = GNUNET_YES;
8427 if (0 == GNUNET_memcmp (my_identity, &dvl->initiator))
8428 {
8429 struct GNUNET_PeerIdentity path[nhops + 1];
8430 struct GNUNET_TIME_Relative network_latency;
8431
8432 /* We initiated this, learn the forward path! */
8433 path[0] = *my_identity;
8434 path[1] = hops[0].hop;
8435
8436 network_latency = get_network_latency (dvl);
8437
8438 for (unsigned int i = 2; i <= nhops; i++)
8439 {
8440 struct GNUNET_TIME_Relative ilat;
8441
8442 /* assumption: linear latency increase per hop */
8443 ilat = GNUNET_TIME_relative_multiply (network_latency, i);
8444 path[i] = hops[i - 1].hop;
8446 "Learned path with %u hops to %s with latency %s\n",
8447 i,
8448 GNUNET_i2s (&path[i]),
8450 learn_dv_path (path,
8451 i + 1,
8452 ilat,
8455 }
8456 /* as we initiated, do not forward again (would be circular!) */
8457 do_fwd = GNUNET_NO;
8458 return;
8459 }
8460 if (bi_hop)
8461 {
8462 /* last hop was bi-directional, we could learn something here! */
8463 struct GNUNET_PeerIdentity path[nhops + 2];
8464 struct GNUNET_TIME_Relative ilat;
8465 struct GNUNET_TIME_Relative network_latency;
8466
8467 path[0] = *my_identity;
8468 path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
8469 for (unsigned int i = 0; i < nhops; i++)
8470 {
8471 int iret;
8472
8473 if (0 == (bi_history & (1 << i)))
8474 break; /* i-th hop not bi-directional, stop learning! */
8475 if (i == nhops - 1)
8476 {
8477 path[i + 2] = dvl->initiator;
8478 }
8479 else
8480 {
8481 path[i + 2] = hops[nhops - i - 2].hop;
8482 }
8483
8485 "Learned inverse path with %u hops to %s\n",
8486 i + 2,
8487 GNUNET_i2s (&path[i + 2]));
8488 network_latency = get_network_latency (dvl);
8489 ilat = GNUNET_TIME_relative_multiply (network_latency, i + 2);
8490 iret = learn_dv_path (path,
8491 i + 3,
8492 ilat,
8495 if (GNUNET_SYSERR == iret)
8496 {
8497 /* path invalid or too long to be interesting for US, thus should also
8498 not be interesting to our neighbours, cut path when forwarding to
8499 'i' hops, except of course for the one that goes back to the
8500 initiator */
8502 "# DV learn not forwarded due invalidity of path",
8503 1,
8504 GNUNET_NO);
8505 do_fwd = GNUNET_NO;
8506 break;
8507 }
8508 if ((GNUNET_NO == iret) && (nhops == i + 1))
8509 {
8510 /* we have better paths, and this is the longest target,
8511 so there cannot be anything interesting later */
8513 "# DV learn not forwarded, got better paths",
8514 1,
8515 GNUNET_NO);
8516 do_fwd = GNUNET_NO;
8517 break;
8518 }
8519 }
8520 }
8521 if (MAX_DV_HOPS_ALLOWED == nhops)
8522 {
8523 /* At limit, we're out of here! */
8524 return;
8525 }
8526
8527 /* Forward to initiator, if path non-trivial and possible */
8528 bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
8529 did_initiator = GNUNET_NO;
8530 if ((1 <= nhops) &&
8531 (GNUNET_YES ==
8533 {
8534 /* send back to origin! */
8536 "Sending DVL back to initiator %s\n",
8537 GNUNET_i2s (&dvl->initiator));
8538 forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
8539 did_initiator = GNUNET_YES;
8540 }
8541 /* We forward under two conditions: either we still learned something
8542 ourselves (do_fwd), or the path was darn short and thus the initiator is
8543 likely to still be very interested in this (and we did NOT already
8544 send it back to the initiator) */
8545 if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
8546 (GNUNET_NO == did_initiator)))
8547 {
8548 /* Pick random neighbours that are not yet on the path */
8549 struct NeighbourSelectionContext nsc;
8550 unsigned int n_cnt;
8551
8553 nsc.nhops = nhops;
8554 nsc.dvl = dvl;
8555 nsc.bi_history = bi_history;
8556 nsc.hops = hops;
8557 nsc.in_time = in_time;
8558 nsc.num_eligible = 0;
8561 &nsc);
8562 if (0 == nsc.num_eligible)
8563 return; /* done here, cannot forward to anyone else */
8565 nsc.num_selections =
8568 "Forwarding DVL to %u other peers\n",
8569 nsc.num_selections);
8570 for (unsigned int i = 0; i < nsc.num_selections; i++)
8571 nsc.selections[i] =
8572 (nsc.num_selections == n_cnt)
8573 ? i /* all were selected, avoid collisions by chance */
8574 : GNUNET_CRYPTO_random_u32 (n_cnt);
8575 nsc.num_eligible = 0;
8578 &nsc);
8579 }
8580}
8581
8582
8590static int
8591check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
8592{
8593 uint16_t size = ntohs (dvb->header.size);
8594 uint16_t num_hops = ntohs (dvb->num_hops);
8595 const struct GNUNET_PeerIdentity *hops =
8596 (const struct GNUNET_PeerIdentity *) &dvb[1];
8597 const struct GNUNET_PeerIdentity *my_identity;
8598
8599 (void) cls;
8600 if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
8601 + sizeof(struct GNUNET_MessageHeader))
8602 {
8603 GNUNET_break_op (0);
8604 return GNUNET_SYSERR;
8605 }
8606
8609
8610 /* This peer must not be on the path */
8611 for (unsigned int i = 0; i < num_hops; i++)
8612 if (0 == GNUNET_memcmp (&hops[i], my_identity))
8613 {
8614 GNUNET_break_op (0);
8615 return GNUNET_SYSERR;
8616 }
8617 return GNUNET_YES;
8618}
8619
8620
8633static void
8634forward_dv_box (struct Neighbour *next_hop,
8635 struct TransportDVBoxMessage *hdr,
8636 uint16_t total_hops,
8637 uint16_t num_hops,
8638 const struct GNUNET_PeerIdentity *hops,
8639 const void *enc_payload,
8640 uint16_t enc_payload_size)
8641{
8642 struct VirtualLink *vl = next_hop->vl;
8643 struct PendingMessage *pm;
8644 size_t msg_size = sizeof(struct TransportDVBoxMessage)
8645 + num_hops * sizeof(struct GNUNET_PeerIdentity)
8646 + enc_payload_size;
8647 char *buf;
8648 char msg_buf[msg_size] GNUNET_ALIGN;
8649 struct GNUNET_PeerIdentity *dhops;
8650
8651 hdr->num_hops = htons (num_hops);
8652 hdr->total_hops = htons (total_hops);
8653 hdr->header.size = htons (msg_size);
8654 memcpy (msg_buf, hdr, sizeof(*hdr));
8655 dhops = (struct GNUNET_PeerIdentity *) &msg_buf[sizeof(struct
8657 ;
8658 memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
8659 memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
8660
8661 if (GNUNET_YES == ntohs (hdr->without_fc))
8662 {
8664 "Forwarding control message (payload size %u) in DV Box to next hop %s (%u/%u) \n",
8665 enc_payload_size,
8666 GNUNET_i2s (&next_hop->pid),
8667 (unsigned int) num_hops,
8668 (unsigned int) total_hops);
8669 route_via_neighbour (next_hop, (const struct
8670 GNUNET_MessageHeader *) msg_buf,
8672 }
8673 else
8674 {
8675 pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
8677 "2 created pm %p storing vl %p \n",
8678 pm,
8679 vl);
8680 pm->pmt = PMT_DV_BOX;
8681 pm->vl = vl;
8682 pm->target = next_hop->pid;
8684 pm->logging_uuid = logging_uuid_gen++;
8686 pm->bytes_msg = msg_size;
8687 buf = (char *) &pm[1];
8688 memcpy (buf, msg_buf, msg_size);
8689
8691 "Created pending message %" PRIu64
8692 " for DV Box with next hop %s (%u/%u)\n",
8693 pm->logging_uuid,
8694 GNUNET_i2s (&next_hop->pid),
8695 (unsigned int) num_hops,
8696 (unsigned int) total_hops);
8697
8698 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
8699 {
8701 vl->pending_msg_head,
8702 vl->pending_msg_tail,
8703 pm);
8704
8706 }
8707 else
8708 {
8710 "The virtual link is not ready for forwarding a DV Box with payload, storing PendingMessage in ring buffer.\n");
8711
8713 {
8715
8716 GNUNET_free (pm_old);
8717 }
8720 {
8723 }
8724 else
8726
8728 "%u items stored in DV ring buffer\n",
8731 }
8732 }
8733}
8734
8735
8741static void
8742free_backtalker (struct Backtalker *b)
8743{
8744 if (NULL != b->get)
8745 {
8747 b->get = NULL;
8748 GNUNET_assert (NULL != b->cmc);
8750 b->cmc = NULL;
8751 }
8752 if (NULL != b->task)
8753 {
8755 b->task = NULL;
8756 }
8757 if (NULL != b->sc)
8758 {
8760 "store cancel\n");
8762 b->sc = NULL;
8763 }
8765 "Removing backtalker for %s\n",
8766 GNUNET_i2s (&b->pid));
8768 GNUNET_YES ==
8770 GNUNET_free (b);
8771}
8772
8773
8782static int
8783free_backtalker_cb (void *cls,
8784 const struct GNUNET_PeerIdentity *pid,
8785 void *value)
8786{
8787 struct Backtalker *b = value;
8788
8789 (void) cls;
8790 (void) pid;
8791 free_backtalker (b);
8792 return GNUNET_OK;
8793}
8794
8795
8801static void
8802backtalker_timeout_cb (void *cls)
8803{
8804 struct Backtalker *b = cls;
8805
8807 "backtalker timeout.\n");
8808 b->task = NULL;
8810 {
8812 return;
8813 }
8814 GNUNET_assert (NULL == b->sc);
8815 free_backtalker (b);
8816}
8817
8818
8827static void
8828backtalker_monotime_cb (void *cls,
8829 const struct GNUNET_PEERSTORE_Record *record,
8830 const char *emsg)
8831{
8832 struct Backtalker *b = cls;
8833 struct GNUNET_TIME_AbsoluteNBO *mtbe;
8834 struct GNUNET_TIME_Absolute mt;
8835
8836 (void) emsg;
8837 if (NULL == record)
8838 {
8839 /* we're done with #backtalker_monotime_cb() invocations,
8840 continue normal processing */
8841 b->get = NULL;
8842 GNUNET_assert (NULL != b->cmc);
8843 b->cmc->mh = (const struct GNUNET_MessageHeader *) &b[1];
8844 if (0 != b->body_size)
8846 else
8848 b->cmc = NULL;
8849 return;
8850 }
8851 if (sizeof(*mtbe) != record->value_size)
8852 {
8854 GNUNET_break (0);
8855 return;
8856 }
8857 mtbe = record->value;
8858 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
8859 if (mt.abs_value_us > b->monotonic_time.abs_value_us)
8860 {
8862 "Backtalker message from %s dropped, monotime in the past\n",
8863 GNUNET_i2s (&b->pid));
8865 GST_stats,
8866 "# Backchannel messages dropped: monotonic time not increasing",
8867 1,
8868 GNUNET_NO);
8869 b->monotonic_time = mt;
8870 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
8871 */
8872 b->body_size = 0;
8873 }
8875}
8876
8877
8885static void
8886backtalker_monotime_store_cb (void *cls, int success)
8887{
8888 struct Backtalker *b = cls;
8889
8890 if (GNUNET_OK != success)
8891 {
8893 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
8894 }
8895 b->sc = NULL;
8896 if (NULL != b->task)
8897 {
8899 b->task = NULL;
8900 }
8902}
8903
8904
8910static void
8912{
8913 struct GNUNET_TIME_AbsoluteNBO mtbe;
8914
8915 if (NULL != b->sc)
8916 {
8918 "store cancel before store with sc %p\n",
8919 b->sc);
8920 /*GNUNET_PEERSTORE_store_cancel (b->sc);
8921 b->sc = NULL;*/
8923 "store cancel before store with sc %p is null\n",
8924 b->sc);
8925 }
8926 else
8927 {
8929 b->task = NULL;
8930 }
8932 b->sc =
8934 "transport",
8935 &b->pid,
8937 &mtbe,
8938 sizeof(mtbe),
8942 b);
8943}
8944
8945
8946struct DecapsDvBoxCls
8947{
8949 const struct TransportDVBoxMessage *dvb;
8950 struct PilsRequest *pr;
8951};
8952
8953
8954static void
8955decaps_dv_box_cb (void *cls, const struct GNUNET_ShortHashCode *km)
8956{
8957 struct DecapsDvBoxCls *decaps_dv_box_cls = cls;
8958 struct CommunicatorMessageContext *cmc = decaps_dv_box_cls->cmc;
8959 const struct TransportDVBoxMessage *dvb = decaps_dv_box_cls->dvb;
8960 const unsigned char *hdr;
8961 size_t hdr_len;
8963
8964 decaps_dv_box_cls->pr->op = NULL;
8967 decaps_dv_box_cls->pr);
8968 GNUNET_free (decaps_dv_box_cls->pr);
8969 if (NULL == km)
8970 {
8971 GNUNET_break_op (0);
8972 finish_cmc_handling (cmc);
8973 return;
8974 }
8975 key = (struct GNUNET_CRYPTO_AeadSecretKey*) km;
8976 hdr = (const unsigned char *) &dvb[1];
8977 hdr_len = ntohs (dvb->orig_size) - sizeof(*dvb) - sizeof(struct
8979 * ntohs (dvb->total_hops);
8980
8981 /* begin actual decryption */
8982 {
8983 struct Backtalker *b;
8984 struct GNUNET_TIME_Absolute monotime;
8985 struct TransportDVBoxPayloadP *ppay;
8986 unsigned char pt[hdr_len + sizeof *ppay] GNUNET_ALIGN;
8987 unsigned char *body;
8988 const struct GNUNET_MessageHeader *mh;
8989
8990 ppay = (struct TransportDVBoxPayloadP *) pt;
8991 body = &pt[sizeof *ppay];
8992 GNUNET_assert (hdr_len >=
8993 sizeof(*ppay) + sizeof(struct GNUNET_MessageHeader));
8994 if (GNUNET_OK != GNUNET_CRYPTO_aead_decrypt (hdr_len,
8995 hdr,
8996 0,
8997 NULL,
8998 key,
8999 &dvb->iv,
9000 &dvb->mac,
9001 pt))
9002 {
9004 "Error decrypting DV payload header\n");
9005 GNUNET_break_op (0);
9006 finish_cmc_handling (cmc);
9007 return;
9008 }
9009 mh = (const struct GNUNET_MessageHeader *) body;
9010 if (ntohs (mh->size) != sizeof(body))
9011 {
9012 GNUNET_break_op (0);
9013 finish_cmc_handling (cmc);
9014 return;
9015 }
9016 /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
9017 switch (ntohs (mh->type))
9018 {
9020 GNUNET_break_op (0);
9021 finish_cmc_handling (cmc);
9022 return;
9023
9025 GNUNET_break_op (0);
9026 finish_cmc_handling (cmc);
9027 return;
9028
9029 default:
9030 /* permitted, continue */
9031 break;
9032 }
9033 monotime = GNUNET_TIME_absolute_ntoh (ppay->monotonic_time);
9035 "Decrypted backtalk from %s\n",
9036 GNUNET_i2s (&ppay->sender));
9038 &ppay->sender);
9039 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
9040 {
9042 GST_stats,
9043 "# Backchannel messages dropped: monotonic time not increasing",
9044 1,
9045 GNUNET_NO);
9046 finish_cmc_handling (cmc);
9047 return;
9048 }
9049 if ((NULL == b) ||
9050 (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
9051 {
9052 /* Check signature */
9053 const struct GNUNET_PeerIdentity *my_identity;
9054 struct EphemeralConfirmationPS ec;
9055
9058
9059 ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL);
9060 ec.target = *my_identity;
9061 ec.ephemeral_key = dvb->ephemeral_key;
9062 ec.purpose.size = htonl (sizeof(ec));
9063 ec.sender_monotonic_time = ppay->monotonic_time;
9064 if (
9065 GNUNET_OK !=
9068 &ec,
9069 &ppay->sender_sig,
9070 &ppay->sender.public_key))
9071 {
9072 /* Signature invalid, discard! */
9073 GNUNET_break_op (0);
9074 finish_cmc_handling (cmc);
9075 return;
9076 }
9077 }
9078 /* Update sender, we now know the real origin! */
9080 "DVBox received for me from %s via %s\n",
9081 GNUNET_i2s2 (&ppay->sender),
9082 GNUNET_i2s (&cmc->im.sender));
9083 cmc->im.sender = ppay->sender;
9084
9085 if (NULL != b)
9086 {
9087 /* update key cache and mono time */
9088 b->last_ephemeral = dvb->ephemeral_key;
9089 b->monotonic_time = monotime;
9091 b->timeout =
9093 cmc->mh = mh;
9095 return;
9096 }
9097 /* setup data structure to cache signature AND check
9098 monotonic time with PEERSTORE before forwarding backchannel payload */
9099 b = GNUNET_malloc (sizeof(struct Backtalker) + sizeof(hdr_len));
9100 b->pid = ppay->sender;
9101 b->body_size = hdr_len;
9102 memcpy (&b[1], body, hdr_len);
9106 &b->pid,
9107 b,
9109 b->monotonic_time = monotime; /* NOTE: to be checked still! */
9110 b->cmc = cmc;
9111 b->timeout =
9114 b->get =
9116 "transport",
9117 &b->pid,
9120 b);
9121 } /* end actual decryption */
9122}
9123
9124
9132static void
9133handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
9134{
9135 struct CommunicatorMessageContext *cmc = cls;
9136 uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
9137 uint16_t num_hops = ntohs (dvb->num_hops);
9138 const struct GNUNET_PeerIdentity *hops =
9139 (const struct GNUNET_PeerIdentity *) &dvb[1];
9140 const char *enc_payload = (const char *) &hops[num_hops];
9141 uint16_t enc_payload_size =
9142 size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
9143 struct DecapsDvBoxCls *decaps_dv_box_cls;
9144 const struct GNUNET_PeerIdentity *my_identity;
9145
9148
9149 if (GNUNET_EXTRA_LOGGING > 0)
9150 {
9151 char *path;
9152
9154 for (unsigned int i = 0; i < num_hops; i++)
9155 {
9156 char *tmp;
9157
9158 GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
9159 GNUNET_free (path);
9160 path = tmp;
9161 }
9163 "Received DVBox with remaining path %s\n",
9164 path);
9165 GNUNET_free (path);
9166 }
9167
9168 if (num_hops > 0)
9169 {
9170 /* We're trying from the end of the hops array, as we may be
9171 able to find a shortcut unknown to the origin that way */
9172 for (int i = num_hops - 1; i >= 0; i--)
9173 {
9174 struct Neighbour *n;
9175
9176 if (0 == GNUNET_memcmp (&hops[i], my_identity))
9177 {
9178 GNUNET_break_op (0);
9179 finish_cmc_handling (cmc);
9180 return;
9181 }
9182 n = lookup_neighbour (&hops[i]);
9183 if (NULL == n)
9184 continue;
9186 "Skipping %u/%u hops ahead while routing DV Box\n",
9187 i,
9188 num_hops);
9189
9190 forward_dv_box (n,
9191 (struct TransportDVBoxMessage *) dvb,
9192 ntohs (dvb->total_hops) + 1,
9193 num_hops - i - 1, /* number of hops left */
9194 &hops[i + 1], /* remaining hops */
9195 enc_payload,
9196 enc_payload_size);
9198 "# DV hops skipped routing boxes",
9199 i,
9200 GNUNET_NO);
9202 "# DV boxes routed (total)",
9203 1,
9204 GNUNET_NO);
9205 finish_cmc_handling (cmc);
9206 return;
9207 }
9208 /* Woopsie, next hop not in neighbours, drop! */
9210 "# DV Boxes dropped: next hop unknown",
9211 1,
9212 GNUNET_NO);
9213 finish_cmc_handling (cmc);
9214 return;
9215 }
9216 /* We are the target. Unbox and handle message. */
9218 "# DV boxes opened (ultimate target)",
9219 1,
9220 GNUNET_NO);
9221 cmc->total_hops = ntohs (dvb->total_hops);
9222
9223 {
9224 // DH key derivation with received DV, could be garbage.
9225 decaps_dv_box_cls = GNUNET_new (struct DecapsDvBoxCls);
9226 decaps_dv_box_cls->cmc = cmc;
9227 decaps_dv_box_cls->dvb = dvb;
9228 decaps_dv_box_cls->pr = GNUNET_new (struct PilsRequest);
9229
9232 decaps_dv_box_cls->pr);
9233 decaps_dv_box_cls->pr->op = GNUNET_PILS_kem_decaps (pils,
9234 &dvb->ephemeral_key,
9236 decaps_dv_box_cls);
9237 }
9238 // TODO keep track of cls and potentially clean
9239}
9240
9241
9249static int
9250check_incoming_msg (void *cls,
9251 const struct GNUNET_TRANSPORT_IncomingMessage *im)
9252{
9253 struct TransportClient *tc = cls;
9254
9255 if (CT_COMMUNICATOR != tc->type)
9256 {
9257 GNUNET_break (0);
9258 return GNUNET_SYSERR;
9259 }
9261 return GNUNET_OK;
9262}
9263
9264
9269{
9273 const char *address;
9274
9278 struct ValidationState *vs;
9279};
9280
9281
9291static int
9292check_known_address (void *cls,
9293 const struct GNUNET_PeerIdentity *pid,
9294 void *value)
9295{
9296 struct CheckKnownAddressContext *ckac = cls;
9297 struct ValidationState *vs = value;
9298
9299 (void) pid;
9300 if (0 != strcmp (vs->address, ckac->address))
9301 return GNUNET_OK;
9302 ckac->vs = vs;
9303 return GNUNET_NO;
9304}
9305
9306
9312static void
9313validation_start_cb (void *cls);
9314
9315
9323static void
9325 struct GNUNET_TIME_Absolute new_time)
9326{
9328
9329 if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
9330 return; /* be lazy */
9331 vs->next_challenge = new_time;
9332 if (NULL == vs->hn)
9333 vs->hn =
9335 else
9338 (NULL != validation_task))
9339 return;
9340 if (NULL != validation_task)
9342 /* randomize a bit */
9345 new_time = GNUNET_TIME_absolute_add (new_time, delta);
9348}
9349
9350
9357static void
9359 const char *address)
9360{
9361 struct GNUNET_TIME_Absolute now;
9362 struct ValidationState *vs;
9363 struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
9364
9366 pid,
9368 &ckac);
9369 if (NULL != (vs = ckac.vs))
9370 {
9371 /* if 'vs' is not currently valid, we need to speed up retrying the
9372 * validation */
9373 if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
9374 {
9375 /* reduce backoff as we got a fresh advertisement */
9376 vs->challenge_backoff =
9379 vs->challenge_backoff,
9380 2));
9383 vs->challenge_backoff));
9384 }
9385 return;
9386 }
9388 vs = GNUNET_new (struct ValidationState);
9389 vs->pid = *pid;
9390 vs->valid_until =
9392 vs->first_challenge_use = now;
9393 vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
9394 GNUNET_CRYPTO_random_block (&vs->challenge,
9395 sizeof(vs->challenge));
9396 vs->address = GNUNET_strdup (address);
9397 GNUNET_CRYPTO_hash (vs->address, strlen (vs->address), &vs->hc);
9399 "Starting address validation `%s' of peer %s using challenge %s\n",
9400 address,
9401 GNUNET_i2s (pid),
9402 GNUNET_sh2s (&vs->challenge.value));
9406 &vs->pid,
9407 vs,
9410}
9411
9412
9413static struct Queue *
9414find_queue (const struct GNUNET_PeerIdentity *pid, const char *address);
9415
9416
9417static void
9418suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address);
9419
9420
9421static void
9422hello_for_incoming_cb (void *cls,
9423 const struct GNUNET_PeerIdentity *pid,
9424 const char *uri)
9425{
9426 struct Queue *q;
9427 int pfx_len;
9428 const char *eou;
9429 char *address;
9430 (void) cls;
9431
9432 eou = strstr (uri,
9433 "://");
9434 pfx_len = eou - uri;
9435 eou += 3;
9437 "%.*s-%s",
9438 pfx_len,
9439 uri,
9440 eou);
9441
9443 "helo for client %s\n",
9444 address);
9445 q = find_queue (pid, address);
9446 if (NULL == q)
9447 {
9449 }
9450 else
9453}
9454
9455
9463static void
9464handle_hello_for_incoming (void *cls,
9465 const struct GNUNET_PEERSTORE_Record *record,
9466 const char *emsg)
9467{
9468 struct IncomingRequest *ir = cls;
9470 struct GNUNET_MessageHeader *hello;
9471 const struct GNUNET_PeerIdentity *my_identity;
9472
9473 if (NULL != emsg)
9474 {
9476 "Got failure from PEERSTORE: %s\n",
9477 emsg);
9478 return;
9479 }
9480 hello = record->value;
9483 if (0 == GNUNET_memcmp (&record->peer, my_identity))
9484 {
9486 return;
9487 }
9488 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
9491 NULL);
9492 GNUNET_HELLO_parser_free (parser);
9493}
9494
9495
9496static void
9498{
9500 "Error in PEERSTORE monitoring\n");
9501}
9502
9503
9504static void
9506{
9508 "Done with initial PEERSTORE iteration during monitoring\n");
9509}
9510
9511
9512struct SignTValidationCls
9513{
9516 struct PilsRequest *pr;
9517};
9518
9519
9520static void
9521sign_t_validation_cb (void *cls,
9522 const struct GNUNET_PeerIdentity *pid,
9523 const struct GNUNET_CRYPTO_EddsaSignature *sig)
9524{
9525 struct SignTValidationCls *sign_t_validation_cls = cls;
9526 struct CommunicatorMessageContext *cmc = sign_t_validation_cls->cmc;
9527 struct TransportValidationResponseMessage tvr = sign_t_validation_cls->tvr;
9528 struct VirtualLink *vl;
9529 struct Neighbour *n;
9530 struct IncomingRequest *ir;
9531 struct GNUNET_PeerIdentity sender;
9532
9533 sign_t_validation_cls->pr->op = NULL;
9536 sign_t_validation_cls->pr);
9537 GNUNET_free (sign_t_validation_cls->pr);
9538 tvr.signature = *sig;
9539 sender = cmc->im.sender;
9540 vl = lookup_virtual_link (&sender);
9541 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9542 {
9543 // route_control_message_without_fc (&cmc->im.sender,
9545 &tvr.header,
9547 }
9548 else
9549 {
9550 /* Use route via neighbour */
9551 n = lookup_neighbour (&sender);
9552 if (NULL != n)
9553 route_via_neighbour (n, &tvr.header,
9556 }
9557
9558 finish_cmc_handling (cmc);
9559 if (NULL != vl)
9560 return;
9561
9562 /* For us, the link is still down, but we need bi-directional
9563 connections (for flow-control and for this to be useful for
9564 CORE), so we must try to bring the link up! */
9565
9566 /* (1) Check existing queues, if any, we may be lucky! */
9567 n = lookup_neighbour (&sender);
9568 if (NULL != n)
9569 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
9570 start_address_validation (&sender, q->address);
9571 /* (2) Also try to see if we have addresses in PEERSTORE for this peer
9572 we could use */
9573 for (ir = ir_head; NULL != ir; ir = ir->next)
9574 if (0 == GNUNET_memcmp (&ir->pid, &sender))
9575 return;
9576 /* we are already trying */
9577 ir = GNUNET_new (struct IncomingRequest);
9578 ir->pid = sender;
9580
9582 GNUNET_YES,
9583 "peerstore",
9584 NULL,
9587 NULL,
9589 NULL,
9591 ir);
9592 ir_total++;
9593 /* Bound attempts we do in parallel here, might otherwise get excessive */
9596};
9597
9598
9607static void
9609 void *cls,
9610 const struct TransportValidationChallengeMessage *tvc)
9611{
9612 struct CommunicatorMessageContext *cmc = cls;
9613 struct TransportValidationResponseMessage tvr = { 0 };
9614 struct GNUNET_TIME_RelativeNBO validity_duration;
9615
9616 /* DV-routed messages are not allowed for validation challenges */
9617 if (cmc->total_hops > 0)
9618 {
9619 GNUNET_break_op (0);
9620 finish_cmc_handling (cmc);
9621 return;
9622 }
9623 validity_duration = cmc->im.expected_address_validity;
9625 "Received address validation challenge %s\n",
9626 GNUNET_sh2s (&tvc->challenge.value));
9627 /* If we have a virtual link, we use this mechanism to signal the
9628 size of the flow control window, and to allow the sender
9629 to ask for increases. If for us the virtual link is still down,
9630 we will always give a window size of zero. */
9631 tvr.header.type =
9633 tvr.header.size = htons (sizeof(tvr));
9634 tvr.reserved = htonl (0);
9635 tvr.challenge = tvc->challenge;
9636 tvr.origin_time = tvc->sender_time;
9637 tvr.validity_duration = validity_duration;
9638 {
9639 /* create signature */
9640 struct TransportValidationPS tvp = {
9642 .purpose.size = htonl (sizeof(tvp)),
9643 .validity_duration = validity_duration,
9644 .challenge = tvc->challenge
9645 };
9646 struct SignTValidationCls *sign_t_validation_cls;
9647
9648 sign_t_validation_cls = GNUNET_new (struct SignTValidationCls);
9649 sign_t_validation_cls->cmc = cmc;
9650 sign_t_validation_cls->tvr = tvr;
9651 sign_t_validation_cls->pr = GNUNET_new (struct PilsRequest);
9654 sign_t_validation_cls->pr);
9655 sign_t_validation_cls->pr->op =
9657 &tvp.purpose,
9659 sign_t_validation_cls);
9660 }
9661}
9662
9663
9668{
9673
9677 struct ValidationState *vs;
9678};
9679
9680
9690static int
9691check_known_challenge (void *cls,
9692 const struct GNUNET_PeerIdentity *pid,
9693 void *value)
9694{
9695 struct CheckKnownChallengeContext *ckac = cls;
9696 struct ValidationState *vs = value;
9697
9698 (void) pid;
9699 if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
9700 return GNUNET_OK;
9701 ckac->vs = vs;
9702 return GNUNET_NO;
9703}
9704
9705
9713static void
9714peerstore_store_validation_cb (void *cls, int success)
9715{
9716 struct ValidationState *vs = cls;
9717
9718 vs->sc = NULL;
9719 if (GNUNET_YES == success)
9720 return;
9722 "# Peerstore failed to store foreign address",
9723 1,
9724 GNUNET_NO);
9725}
9726
9727
9735static struct Queue *
9736find_queue (const struct GNUNET_PeerIdentity *pid, const char *address)
9737{
9738 struct Neighbour *n;
9739
9740 n = lookup_neighbour (pid);
9741 if (NULL == n)
9742 return NULL;
9743 for (struct Queue *pos = n->queue_head; NULL != pos;
9744 pos = pos->next_neighbour)
9745 {
9746 if (0 == strcmp (pos->address, address))
9747 return pos;
9748 }
9749 return NULL;
9750}
9751
9752
9753static void
9755
9756static void
9757revalidation_start_cb (void *cls)
9758{
9759 struct ValidationState *vs = cls;
9760 struct Queue *q;
9761 struct GNUNET_TIME_Absolute now;
9762
9763 vs->revalidation_task = NULL;
9764 q = find_queue (&vs->pid, vs->address);
9765 if (NULL == q)
9766 {
9767 now = GNUNET_TIME_absolute_get ();
9768 vs->awaiting_queue = GNUNET_YES;
9769 suggest_to_connect (&vs->pid, vs->address);
9771 }
9772 else
9774}
9775
9776
9777static enum GNUNET_GenericReturnValue
9779 void *cls,
9780 const struct GNUNET_HashCode *key,
9781 void *value)
9782{
9783 (void) cls;
9785 "Key in revalidate map %s \n",
9786 GNUNET_h2s (key));
9787 return GNUNET_YES;
9788}
9789
9790
9799static void
9801 void *cls,
9802 const struct TransportValidationResponseMessage *tvr)
9803{
9804 struct CommunicatorMessageContext *cmc = cls;
9805 struct ValidationState *vs;
9806 struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
9807 .vs = NULL};
9808 struct GNUNET_TIME_Absolute origin_time;
9809 struct Queue *q;
9810 struct Neighbour *n;
9811 struct VirtualLink *vl;
9813 GST_cfg);
9814
9815 /* check this is one of our challenges */
9817 &cmc->im.sender,
9819 &ckac);
9820 if (NULL == (vs = ckac.vs))
9821 {
9822 /* This can happen simply if we 'forgot' the challenge by now,
9823 i.e. because we received the validation response twice */
9825 "# Validations dropped, challenge unknown",
9826 1,
9827 GNUNET_NO);
9829 "Validation response %s dropped, challenge unknown\n",
9830 GNUNET_sh2s (&tvr->challenge.value));
9831 finish_cmc_handling (cmc);
9832 return;
9833 }
9834
9835 /* sanity check on origin time */
9836 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
9837 if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
9838 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
9839 {
9841 "Diff first use %" PRIu64 " and last use %" PRIu64 "\n",
9842 vs->first_challenge_use.abs_value_us - origin_time.abs_value_us,
9843 origin_time.abs_value_us - vs->last_challenge_use.abs_value_us);
9844 GNUNET_break_op (0);
9845 finish_cmc_handling (cmc);
9846 return;
9847 }
9848
9849 {
9850 /* check signature */
9851 struct TransportValidationPS tvp = {
9853 .purpose.size = htonl (sizeof(tvp)),
9854 .validity_duration = tvr->validity_duration,
9855 .challenge = tvr->challenge
9856 };
9857
9858 if (
9859 GNUNET_OK !=
9861 &tvp,
9862 &tvr->signature,
9863 &cmc->im.sender.public_key))
9864 {
9865 GNUNET_break_op (0);
9866 finish_cmc_handling (cmc);
9867 return;
9868 }
9869 }
9870
9871 /* validity is capped by our willingness to keep track of the
9872 validation entry and the maximum the other peer allows */
9875 tvr->validity_duration),
9877 vs->validated_until =
9881 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
9882 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
9883 GNUNET_CRYPTO_random_block (&vs->challenge,
9884 sizeof(vs->challenge));
9885 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
9886 vs->validated_until,
9887 GNUNET_TIME_relative_multiply (vs->validation_rtt,
9889 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, <, now))
9890 {
9892 "First challenge use is now %" PRIu64 " %s \n",
9893 vs->first_challenge_use.abs_value_us,
9894 GNUNET_sh2s (&vs->challenge.value));
9895 vs->first_challenge_use = now;
9896 }
9897 else
9899 "First challenge use is later %" PRIu64 " %s \n",
9900 vs->first_challenge_use.abs_value_us,
9901 GNUNET_sh2s (&vs->challenge.value));
9902 vs->last_challenge_use =
9903 GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
9904 update_next_challenge_time (vs, vs->first_challenge_use);
9906 "Validation response %s from %s accepted, address valid until %s\n",
9907 GNUNET_sh2s (&tvr->challenge.value),
9908 GNUNET_i2s (&cmc->im.sender),
9910 /*memcpy (&hkey,
9911 &hc,
9912 sizeof (hkey));*/
9914 "Key %s for address %s map size %u contains %u\n",
9915 GNUNET_h2s (&vs->hc),
9916 vs->address,
9919 &vs->hc));
9923 &vs->hc,
9924 vs,
9928 NULL);
9929 vs->revalidation_task =
9934 "transport",
9935 &cmc->im.sender,
9937 vs->address,
9938 strlen (vs->address) + 1,
9939 vs->valid_until,
9942 vs);
9943 finish_cmc_handling (cmc);
9944
9945 /* Finally, we now possibly have a confirmed (!) working queue,
9946 update queue status (if queue still is around) */
9947 q = find_queue (&vs->pid, vs->address);
9948 if (NULL == q)
9949 {
9951 "# Queues lost at time of successful validation",
9952 1,
9953 GNUNET_NO);
9954 return;
9955 }
9956 q->validated_until = vs->validated_until;
9957 q->pd.aged_rtt = vs->validation_rtt;
9958 n = q->neighbour;
9959 vl = lookup_virtual_link (&vs->pid);
9960 if (NULL == vl)
9961 {
9962 vl = GNUNET_new (struct VirtualLink);
9964 "Creating new virtual link %p to %s using direct neighbour!\n",
9965 vl,
9966 GNUNET_i2s (&vs->pid));
9967 vl->burst_addr = NULL;
9968 vl->confirmed = GNUNET_YES;
9969 vl->message_uuid_ctr =
9970 GNUNET_CRYPTO_random_u64 (UINT64_MAX);
9971 vl->target = n->pid;
9977 links,
9978 &vl->target,
9979 vl,
9981 vl->n = n;
9982 n->vl = vl;
9983 q->idle = GNUNET_YES;
9984 vl->visibility_task =
9985 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
9987 /* We lacked a confirmed connection to the target
9988 before, so tell CORE about it (finally!) */
9991 }
9992 else
9993 {
9994 /* Link was already up, remember n is also now available and we are done */
9995 if (NULL == vl->n)
9996 {
9997 vl->n = n;
9998 n->vl = vl;
9999 if (GNUNET_YES == vl->confirmed)
10001 "Virtual link to %s could now also use direct neighbour!\n",
10002 GNUNET_i2s (&vs->pid));
10003 }
10004 else
10005 {
10006 GNUNET_assert (n == vl->n);
10007 }
10008 if (GNUNET_NO == vl->confirmed)
10009 {
10010 vl->confirmed = GNUNET_YES;
10011 q->idle = GNUNET_YES;
10012 vl->visibility_task =
10013 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
10015 /* We lacked a confirmed connection to the target
10016 before, so tell CORE about it (finally!) */
10019 }
10020 }
10021}
10022
10023
10029static void
10030handle_incoming_msg (void *cls,
10031 const struct GNUNET_TRANSPORT_IncomingMessage *im)
10032{
10033 struct TransportClient *tc = cls;
10034 struct CommunicatorMessageContext *cmc =
10036
10037 cmc->tc = tc;
10038 cmc->im = *im;
10040 "Received message with size %u and flow control id %" PRIu64
10041 " via communicator from peer %s\n",
10042 ntohs (im->header.size),
10043 im->fc_id,
10044 GNUNET_i2s (&im->sender));
10045 cmc->im.neighbour_sender = cmc->im.sender;
10046 cmc->mh = (const struct GNUNET_MessageHeader *) &im[1];
10048}
10049
10050
10059static int
10060check_flow_control (void *cls, const struct TransportFlowControlMessage *fc)
10061{
10062 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10063 (void) cls;
10064
10066 "Flow control header size %u size of addresses %u number of addresses %u size of message struct %lu second struct %lu\n",
10067 ntohs (fc->header.size),
10068 ntohl (fc->size_of_addresses),
10069 ntohl (fc->number_of_addresses),
10070 sizeof(struct TransportFlowControlMessage),
10071 sizeof (struct TransportGlobalNattedAddress));
10072
10073 if (0 == number_of_addresses || ntohs (fc->header.size) == sizeof(struct
10075 + ntohl (fc->number_of_addresses) * sizeof (struct
10077 + ntohl (fc->size_of_addresses))
10078 return GNUNET_OK;
10079 else
10080 {
10081 GNUNET_break_op (0);
10082 return GNUNET_SYSERR;
10083 }
10084}
10085
10086
10087static struct GNUNET_TIME_Relative
10088calculate_rtt (struct DistanceVector *dv)
10089{
10091 unsigned int n_hops = 0;
10092
10094 "calculate_rtt\n");
10095 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
10096 pos = pos->next_dv)
10097 {
10099 "calculate_rtt %lu\n",
10100 (unsigned long) pos->pd.aged_rtt.rel_value_us);
10101 n_hops++;
10103 aged_rtt, pos
10104 ->distance
10105 + 2), ret);
10106 }
10107
10108 GNUNET_assert (0 != n_hops);
10109
10110 return ret;
10111}
10112
10113
10114static void
10116 const struct GNUNET_PeerIdentity *pid,
10117 const char *uri)
10118{
10119 struct VirtualLink *vl = cls;
10120 const char *slash;
10121 char *address_uri;
10122 char *prefix;
10123 char *uri_without_port;
10124
10125 slash = strrchr (uri, '/');
10126 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
10127 GNUNET_assert (NULL != slash);
10128 slash++;
10129 GNUNET_asprintf (&address_uri,
10130 "%s-%s",
10131 prefix,
10132 slash);
10133
10134 uri_without_port = get_address_without_port (address_uri);
10136 "iterate_address_start_burst %s %s %s %s\n",
10137 uri_without_port,
10138 uri,
10139 address_uri,
10140 slash);
10141 if (0 == strcmp (uri_without_port, slash))
10142 {
10143 vl->burst_addr = GNUNET_strndup (uri_without_port, strlen (uri_without_port)
10144 );
10145 }
10146 else
10147 vl->burst_addr = NULL;
10148
10150 GNUNET_free (uri_without_port);
10151}
10152
10153
10154static void
10155check_for_burst_address (void *cls,
10156 const struct GNUNET_PEERSTORE_Record *record,
10157 const char *emsg)
10158{
10159 struct GNUNET_StartBurstCls *sb_cls = cls;
10160 struct VirtualLink *vl = sb_cls->vl;
10161 struct GNUNET_MessageHeader *hello;
10163
10164 if (NULL != emsg)
10165 {
10167 "Got failure from PEERSTORE: %s\n",
10168 emsg);
10169 return;
10170 }
10171 if (NULL == record)
10172 {
10174 "Hello iteration end for %s\n",
10175 GNUNET_i2s (&vl->target));
10176 vl->ic = NULL;
10177 GNUNET_free (sb_cls);
10178 return;
10179 }
10180
10182 "check_for_burst_address\n");
10183 hello = record->value;
10184 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
10187 vl);
10188 GNUNET_HELLO_parser_free (parser);
10189
10191 GNUNET_free (sb_cls);
10192}
10193
10194
10195static void
10196burst_timeout (void *cls)
10197{
10199}
10200
10201
10202static void
10203start_burst (void *cls)
10204{
10205 struct GNUNET_StartBurstCls *sb_cls = cls;
10206 struct VirtualLink *vl = sb_cls->vl;
10207 struct GNUNET_TRANSPORT_StartBurst *sb;
10208 struct GNUNET_MQ_Envelope *env;
10209 char *uri_without_port = vl->burst_addr;
10210
10211 burst_task = NULL;
10212 /*char buf[strlen (uri_without_port) + 1];
10213
10214 GNUNET_memcpy (buf, uri_without_port, strlen (uri_without_port));
10215 buf[strlen (uri_without_port)] = '\0';*/
10216 env =
10218 strlen (uri_without_port) + 1,
10220 sb->rtt = GNUNET_TIME_relative_hton (sb_cls->rtt);
10221 sb->pid = vl->target;
10222 memcpy (&sb[1], uri_without_port, strlen (uri_without_port) + 1);
10223 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
10224 {
10226 "iterate_address_start_burst client tc prefix %s\n",
10227 tc->details.communicator.address_prefix);
10228 if (CT_COMMUNICATOR != tc->type)
10229 continue;
10230 if (GNUNET_YES == tc->details.communicator.can_burst)
10231 {
10233 "iterate_address_start_burst %s call %lu %u rtt %lu\n",
10234 uri_without_port,
10235 strlen (uri_without_port),
10236 ntohs (sb->header.size),
10237 (unsigned long) sb_cls->rtt.rel_value_us);
10238 GNUNET_MQ_send (tc->mq, env);
10242 60),
10244 NULL);
10245 // TODO We need some algo to choose from available communicators. Can we run two bursts at once? Atm we only implemented udp burst.
10246 break;
10247 }
10248 }
10249 GNUNET_free (env);
10250 GNUNET_free (sb_cls);
10251}
10252
10253
10254static void
10255queue_burst (void *cls)
10256{
10257 struct GNUNET_StartBurstCls *sb_cls = cls;
10258 struct VirtualLink *vl = sb_cls->vl;
10259
10260 if (GNUNET_YES != use_burst)
10261 return;
10263 "burst_task %p ready %s burst addr %s (%p)\n",
10264 burst_task,
10265 sb_cls->sync_ready ? "yes" : "no",
10266 vl->burst_addr,
10267 vl->burst_addr);
10268 if (NULL != burst_task && GNUNET_NO == sb_cls->sync_ready)
10269 {
10271 burst_task = NULL;
10273 return;
10274 }
10275 if (GNUNET_NO == burst_running && NULL != vl->burst_addr && NULL == burst_task
10276 )
10277 {
10279 &start_burst,
10280 sb_cls);
10281 }
10282 else if (NULL == vl->burst_addr)
10283 {
10285 "peerstore",
10286 &vl->target,
10289 sb_cls);
10290 }
10291}
10292
10293
10302static void
10303handle_flow_control (void *cls, const struct TransportFlowControlMessage *fc)
10304{
10305 struct CommunicatorMessageContext *cmc = cls;
10306 struct VirtualLink *vl;
10308 uint32_t seq;
10309 struct GNUNET_TIME_Absolute st;
10310 uint64_t os;
10311 uint64_t wnd;
10312 uint32_t random;
10313
10315 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
10316 vl = lookup_virtual_link (&cmc->im.sender);
10317 if (NULL == vl)
10318 {
10319 vl = GNUNET_new (struct VirtualLink);
10321 "No virtual link for %p FC creating new unconfirmed virtual link to %s!\n",
10322 vl,
10323 GNUNET_i2s (&cmc->im.sender));
10324 vl->burst_addr = NULL;
10325 vl->confirmed = GNUNET_NO;
10326 vl->message_uuid_ctr =
10327 GNUNET_CRYPTO_random_u64 (UINT64_MAX);
10328 vl->target = cmc->im.sender;
10334 links,
10335 &vl->target,
10336 vl,
10338 }
10339 if (NULL != vl->n)
10340 {
10341 for (struct Queue *q = vl->n->queue_head; NULL != q; q = q->next_neighbour)
10342 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
10343 }
10344
10346 "remaining %lu timeout for neighbour %p\n",
10347 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout).
10348 rel_value_us,
10349 vl->n);
10350 if (NULL == vl->n ||
10351 0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
10352 {
10353 struct GNUNET_TIME_Relative rtt;
10354 struct GNUNET_BurstSync burst_sync;
10355 struct GNUNET_StartBurstCls *bcls;
10356
10357 bcls = GNUNET_new (struct GNUNET_StartBurstCls);
10358 bcls->vl = vl;
10359 vl->sb_cls = bcls;
10360 if (NULL != vl->dv)
10361 rtt = calculate_rtt (vl->dv);
10362 else
10364 burst_sync.rtt_average = fc->rtt;
10365 bcls->rtt = GNUNET_TIME_relative_ntoh (burst_sync.rtt_average);
10366 burst_sync.sync_ready = fc->sync_ready;
10367
10369 &burst_sync,
10370 &queue_burst,
10371 bcls);
10372 }
10373 if (0 != ntohl (fc->number_of_addresses))
10374 {
10375 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10376 const char *tgnas;
10377 unsigned int off = 0;
10378
10379 tgnas = (const char *) &fc[1];
10380
10381 for (int i = 1; i <= number_of_addresses; i++)
10382 {
10383 struct TransportGlobalNattedAddress *tgna;
10384 char *addr;
10385 unsigned int address_length;
10386
10387 tgna = (struct TransportGlobalNattedAddress*) &tgnas[off];
10388 addr = (char *) &tgna[1];
10389 address_length = ntohl (tgna->address_length);
10390 off += sizeof(struct TransportGlobalNattedAddress) + address_length;
10391
10393 "received address %s length %u\n",
10394 addr,
10395 ntohl (tgna->address_length));
10396
10397 GNUNET_NAT_add_global_address (nh, addr, ntohl (tgna->address_length));
10398 }
10399 }
10401 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
10402 {
10404 "FC dropped: Message out of order\n");
10405 /* out of order, drop */
10407 "# FC dropped: message out of order",
10408 1,
10409 GNUNET_NO);
10410 finish_cmc_handling (cmc);
10411 return;
10412 }
10413 seq = ntohl (fc->seq);
10414 if (seq < vl->last_fc_seq)
10415 {
10416 /* Wrap-around/reset of other peer; start all counters from zero */
10418 }
10419 vl->last_fc_seq = seq;
10420 vl->last_fc_timestamp = st;
10422 os = GNUNET_ntohll (fc->outbound_sent);
10424 (int64_t) (os - vl->incoming_fc_window_size_used);
10426 "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
10427 GNUNET_i2s (&vl->target),
10428 (unsigned int) seq,
10429 (unsigned long long) vl->outbound_fc_window_size,
10430 (long long) vl->incoming_fc_window_size_loss);
10432 random = GNUNET_CRYPTO_random_u32 (UINT32_MAX);
10433 if ((GNUNET_YES == vl->confirmed) && ((wnd < vl->incoming_fc_window_size
10437 != wnd) ||
10438 (0 == random
10440 {
10442 "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",
10443 (unsigned long long) wnd,
10444 (unsigned long long) vl->incoming_fc_window_size,
10445 (unsigned long long) vl->last_outbound_window_size_received,
10448 }
10449 if ((wnd == vl->incoming_fc_window_size
10453 (NULL != vl->fc_retransmit_task))
10454 {
10456 "Stopping FC retransmission to %s: peer is current at window %llu\n",
10457 GNUNET_i2s (&vl->target),
10458 (unsigned long long) wnd);
10460 vl->fc_retransmit_task = NULL;
10461 vl->fc_retransmit_count = 0;
10462 }
10464 /* FC window likely increased, check transmission possibilities! */
10466 finish_cmc_handling (cmc);
10467}
10468
10469
10477static void
10479{
10481 { GNUNET_MQ_hd_var_size (fragment_box,
10484 cmc),
10485 GNUNET_MQ_hd_var_size (reliability_box,
10488 cmc),
10489 GNUNET_MQ_hd_var_size (reliability_ack,
10492 cmc),
10493 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
10496 cmc),
10497 GNUNET_MQ_hd_var_size (dv_learn,
10500 cmc),
10501 GNUNET_MQ_hd_var_size (dv_box,
10503 struct TransportDVBoxMessage,
10504 cmc),
10505 GNUNET_MQ_hd_var_size (flow_control,
10508 cmc),
10510 validation_challenge,
10513 cmc),
10515 validation_response,
10518 cmc),
10520 int ret;
10521 const struct GNUNET_MessageHeader *msg = cmc->mh;
10522
10524 "Handling message of type %u with %u bytes\n",
10525 (unsigned int) ntohs (msg->type),
10526 (unsigned int) ntohs (msg->size));
10528 if (GNUNET_SYSERR == ret)
10529 {
10530 GNUNET_break (0);
10532 GNUNET_free (cmc);
10533 return;
10534 }
10535 if (GNUNET_NO == ret)
10536 {
10537 /* unencapsulated 'raw' message */
10538 handle_raw_message (cmc, msg);
10539 }
10540}
10541
10542
10549static int
10550check_add_queue_message (void *cls,
10551 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
10552{
10553 struct TransportClient *tc = cls;
10554
10555 if (CT_COMMUNICATOR != tc->type)
10556 {
10557 GNUNET_break (0);
10558 return GNUNET_SYSERR;
10559 }
10561 return GNUNET_OK;
10562}
10563
10564
10570static void
10572{
10573 if (pm->msg_uuid_set)
10574 return;
10575 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
10576 pm->msg_uuid_set = GNUNET_YES;
10577}
10578
10579
10588static struct PendingAcknowledgement *
10590 struct DistanceVectorHop *dvh,
10591 struct PendingMessage *pm)
10592{
10593 struct PendingAcknowledgement *pa;
10594
10595 pa = GNUNET_new (struct PendingAcknowledgement);
10596 pa->queue = queue;
10597 pa->dvh = dvh;
10598 pa->pm = pm;
10599 do
10600 {
10602 sizeof(pa->ack_uuid));
10603 }
10606 &pa->ack_uuid.value,
10607 pa,
10609 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
10610 GNUNET_CONTAINER_MDLL_insert (pm, pm->pa_head, pm->pa_tail, pa);
10611 if (NULL != dvh)
10614 pa->message_size = pm->bytes_msg;
10616 "Waiting for ACKnowledgment `%s' for <%" PRIu64 ">\n",
10618 pm->logging_uuid);
10619 return pa;
10620}
10621
10622
10634static struct PendingMessage *
10636 struct DistanceVectorHop *dvh,
10637 struct PendingMessage *pm)
10638{
10639 struct PendingAcknowledgement *pa;
10640 struct PendingMessage *ff;
10641 uint16_t mtu;
10642 uint16_t msize;
10643
10644 mtu = (UINT16_MAX == queue->mtu)
10645 ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
10646 : queue->mtu;
10648 "Fragmenting message <%" PRIu64
10649 "> with size %u to %s for MTU %u\n",
10650 pm->logging_uuid,
10651 pm->bytes_msg,
10652 GNUNET_i2s (&pm->vl->target),
10653 (unsigned int) mtu);
10656 "Fragmenting message %" PRIu64 " <%" PRIu64
10657 "> with size %u to %s for MTU %u\n",
10658 pm->msg_uuid.uuid,
10659 pm->logging_uuid,
10660 pm->bytes_msg,
10661 GNUNET_i2s (&pm->vl->target),
10662 (unsigned int) mtu);
10663
10664 /* This invariant is established in #handle_add_queue_message() */
10665 GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
10666
10667 /* select fragment for transmission, descending the tree if it has
10668 been expanded until we are at a leaf or at a fragment that is small
10669 enough
10670 */
10671 ff = pm;
10672 msize = ff->bytes_msg;
10673
10674 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
10675 (ff->frag_off == msize) && (NULL != ff->head_frag))
10676 {
10677 ff = ff->head_frag; /* descent into fragmented fragments */
10678 msize = ff->bytes_msg - sizeof(struct TransportFragmentBoxMessage);
10679 }
10680
10681 if (((ff->bytes_msg > mtu) || (pm == ff)) && (ff->frag_off < msize))
10682 {
10683 /* Did not yet calculate all fragments, calculate next fragment */
10684 struct PendingMessage *frag;
10685 struct TransportFragmentBoxMessage tfb;
10686 const char *orig;
10687 char *msg;
10688 uint16_t fragmax;
10689 uint16_t fragsize;
10690 uint16_t msize_ff;
10691 uint16_t xoff = 0;
10692 pm->frag_count++;
10693
10694 orig = (const char *) &ff[1];
10695 msize_ff = ff->bytes_msg;
10696 if (pm != ff)
10697 {
10698 const struct TransportFragmentBoxMessage *tfbo;
10699
10700 tfbo = (const struct TransportFragmentBoxMessage *) orig;
10701 orig += sizeof(struct TransportFragmentBoxMessage);
10702 msize_ff -= sizeof(struct TransportFragmentBoxMessage);
10703 xoff = ntohs (tfbo->frag_off);
10704 }
10705 fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
10706 fragsize = GNUNET_MIN (msize_ff - ff->frag_off, fragmax);
10707 frag =
10708 GNUNET_malloc (sizeof(struct PendingMessage)
10709 + sizeof(struct TransportFragmentBoxMessage) + fragsize);
10711 "3 created pm %p from pm %p storing vl %p from pm %p\n",
10712 frag,
10713 ff,
10714 pm->vl,
10715 pm);
10717 frag->vl = pm->vl;
10718 frag->frag_parent = ff;
10719 frag->timeout = pm->timeout;
10720 frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
10721 frag->pmt = PMT_FRAGMENT_BOX;
10722 msg = (char *) &frag[1];
10723 tfb.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT);
10724 tfb.header.size =
10725 htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
10726 pa = prepare_pending_acknowledgement (queue, dvh, frag);
10727 tfb.ack_uuid = pa->ack_uuid;
10728 tfb.msg_uuid = pm->msg_uuid;
10729 tfb.frag_off = htons (ff->frag_off + xoff);
10730 tfb.msg_size = htons (pm->bytes_msg);
10731 memcpy (msg, &tfb, sizeof(tfb));
10732 memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
10734 ff->tail_frag, frag);
10735 ff->frag_off += fragsize;
10736 ff = frag;
10737 }
10738
10739 /* Move head to the tail and return it */
10743 ff);
10747 ff);
10748
10749 return ff;
10750}
10751
10752
10765static struct PendingMessage *
10767 struct DistanceVectorHop *dvh,
10768 struct PendingMessage *pm)
10769{
10771 struct PendingAcknowledgement *pa;
10772 struct PendingMessage *bpm;
10773 char *msg;
10774
10775 if ((PMT_CORE != pm->pmt) && (PMT_DV_BOX != pm->pmt))
10776 return pm; /* already fragmented or reliability boxed, or control message:
10777 do nothing */
10778 if (NULL != pm->bpm)
10779 return pm->bpm; /* already computed earlier: do nothing */
10780 // TODO I guess we do not need this assertion. We might have a DLL with
10781 // fragments, because the MTU changed, and we do not need to fragment anymore.
10782 // But we should keep the fragments until message was completed, because
10783 // the MTU might change again.
10784 // GNUNET_assert (NULL == pm->head_frag);
10785 if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
10786 {
10787 /* failed hard */
10788 GNUNET_break (0);
10790 return NULL;
10791 }
10792
10794
10795 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
10796 + pm->bytes_msg);
10798 "4 created pm %p storing vl %p from pm %p\n",
10799 bpm,
10800 pm->vl,
10801 pm);
10803 bpm->vl = pm->vl;
10804 bpm->frag_parent = pm;
10805 // Why was this needed?
10806 // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
10807 bpm->timeout = pm->timeout;
10809 bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
10811 rbox.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX);
10812 rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
10813 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
10814
10815 rbox.ack_uuid = pa->ack_uuid;
10816 msg = (char *) &bpm[1];
10817 memcpy (msg, &rbox, sizeof(rbox));
10818 memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
10819 pm->bpm = bpm;
10821 "Preparing reliability box for message <%" PRIu64
10822 "> of size %d (%d) to %s on queue %s\n",
10823 pm->logging_uuid,
10824 pm->bytes_msg,
10825 ntohs (((const struct GNUNET_MessageHeader *) &pm[1])->size),
10826 GNUNET_i2s (&pm->vl->target),
10827 queue->address);
10828 return bpm;
10829}
10830
10831
10832static void
10835{
10836 struct VirtualLink *vl = pm->vl;
10837 struct PendingMessage *pos;
10838
10839 /* re-insert sort in neighbour list */
10843 pm);
10844 pos = vl->pending_msg_tail;
10845 while ((NULL != pos) &&
10847 pos = pos->prev_vl;
10851 pos,
10852 pm);
10853}
10854
10855
10856static unsigned int
10858{
10859 struct PendingMessage *pos;
10861
10862 pos = pm->head_frag;
10863 while (NULL != pos)
10864 {
10865 if (pos->frags_in_flight_round == pm->frags_in_flight_round ||
10866 GNUNET_NO == check_next_attempt_tree (pos, root))
10868 else
10869 {
10871 break;
10872 }
10873 pos = pos->next_frag;
10874 }
10875
10876 return frags_in_flight;
10877}
10878
10879
10880static void
10882{
10883 struct PendingMessage *pos;
10884
10885 pos = pm->head_frag;
10886 while (NULL != pos)
10887 {
10888 pos->frags_in_flight_round = pm->frags_in_flight_round;
10890 pos = pos->next_frag;
10891 }
10892}
10893
10894
10903static void
10906{
10907 if (NULL == pm->frag_parent)
10908 {
10911 "Next attempt for message <%" PRIu64 "> set to %" PRIu64 "\n",
10912 pm->logging_uuid,
10915 }
10916 else if ((PMT_RELIABILITY_BOX == pm->pmt) || (PMT_DV_BOX == pm->pmt))// || (PMT_FRAGMENT_BOX == pm->pmt))
10917 {
10918 struct PendingMessage *root = pm->frag_parent;
10919
10920 while (NULL != root->frag_parent)
10921 root = root->frag_parent;
10923 "Next attempt for root message <%" PRIu64 "> set to %s\n",
10924 root->logging_uuid,
10926 root->next_attempt = next_attempt;
10928 }
10929 else
10930 {
10931 struct PendingMessage *root = pm->frag_parent;
10932
10933 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
10934 root = root->frag_parent;
10935
10937 "frag_count next attempt %u\n",
10938 root->frag_count);
10939
10940 if (GNUNET_NO == root->frags_in_flight)
10941 {
10942 root->next_attempt = next_attempt;
10944 root->frags_in_flight_round++;
10946 "Next attempt for fragmented message <%" PRIu64 "> (<%" PRIu64
10947 ">)set to %" PRIu64 "\n",
10948 pm->logging_uuid,
10949 root->logging_uuid,
10951 }
10952
10953 pm->next_attempt = root->next_attempt;
10954 pm->frags_in_flight_round = root->frags_in_flight_round;
10956
10957 if (root->bytes_msg == root->frag_off)
10958 root->frags_in_flight = check_next_attempt_tree (root, root);
10959 else
10961
10962 if (GNUNET_NO == root->frags_in_flight)
10963 {
10965 "We have no fragments in flight for message %" PRIu64
10966 ", reorder root! Next attempt is %" PRIu64 "\n",
10967 root->logging_uuid,
10969 if (PMT_DV_BOX == root->pmt)
10970 root = root->frag_parent;
10971 reorder_root_pm (root, root->next_attempt);
10972 // root->next_attempt = GNUNET_TIME_UNIT_ZERO_ABS;
10973 }
10974 else
10975 {
10976 double factor = ((double) root->frag_count - 1)
10977 / (double) root->frag_count;
10978 struct GNUNET_TIME_Relative s1;
10979 struct GNUNET_TIME_Relative s2;
10980 struct GNUNET_TIME_Relative plus_mean =
10983 next_attempt);
10984
10986 "frag_count %u after factor\n",
10987 root->frag_count);
10989 factor);
10990 s2 = GNUNET_TIME_relative_divide (plus,
10991 root->frag_count);
10992 plus_mean = GNUNET_TIME_relative_add (s1, s2);
10995 "We have fragments in flight for message %" PRIu64
10996 ", do not reorder root! Actual next attempt %" PRIu64 "\n",
10997 root->logging_uuid,
10999 }
11000 }
11001}
11002
11003
11008{
11012 struct PendingMessage *best;
11013
11017 struct DistanceVectorHop *dvh;
11018
11022 size_t real_overhead;
11023
11027 unsigned int consideration_counter;
11028
11032 int frag;
11033
11037 int relb;
11038
11042 int to_early;
11043
11047 unsigned int frags_in_flight;
11048
11053};
11054
11055
11067static void
11069 struct Queue *queue,
11070 struct VirtualLink *vl,
11071 struct DistanceVectorHop *dvh,
11072 size_t overhead)
11073{
11074 struct GNUNET_TIME_Absolute now;
11075
11076 now = GNUNET_TIME_absolute_get ();
11077 sc->to_early = GNUNET_NO;
11078 sc->frags_in_flight = GNUNET_NO;
11079 for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
11080 pos = pos->next_vl)
11081 {
11082 size_t real_overhead = overhead;
11083 int frag;
11084 int relb;
11085
11086 if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
11087 {
11089 "DV messages must not be DV-routed to next hop!\n");
11090 continue; /* DV messages must not be DV-routed to next hop! */
11091 }
11092 if (pos->next_attempt.abs_value_us > now.abs_value_us)
11093 {
11094 if (GNUNET_YES == pos->frags_in_flight)
11095 {
11096 sc->frags_in_flight = GNUNET_YES;
11098 "Fragments in flight for message %" PRIu64 "\n",
11099 pos->logging_uuid);
11100 }
11101 else
11102 {
11104 "Maybe too early, because message are sorted by next_attempt, if there are no fragments in flight.Checked message %"
11105 PRIu64 "\n",
11106 pos->logging_uuid);
11107 sc->to_early = GNUNET_YES;
11108 sc->to_early_retry_delay = GNUNET_TIME_absolute_get_remaining (
11109 pos->next_attempt);
11110 continue;
11111 }
11112 // break; /* too early for all messages, they are sorted by next_attempt */
11113 }
11114 if (NULL != pos->qe)
11115 {
11117 "not eligible\n");
11118 continue; /* not eligible */
11119 }
11120 sc->consideration_counter++;
11121 /* determine if we have to fragment, if so add fragmentation
11122 overhead! */
11124 "check %" PRIu64 " for sc->best\n",
11125 pos->logging_uuid);
11126 frag = GNUNET_NO;
11127 if (((0 != queue->mtu) &&
11128 (pos->bytes_msg + real_overhead > queue->mtu)) ||
11129 (pos->bytes_msg > UINT16_MAX - sizeof(struct
11131 ||
11132 (NULL != pos->head_frag /* fragments already exist, should
11133 respect that even if MTU is UINT16_MAX for
11134 this queue */))
11135 {
11137 "fragment msg with size %u, realoverhead is %lu\n",
11138 pos->bytes_msg,
11139 real_overhead);
11140 frag = GNUNET_YES;
11141 if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
11142 {
11143 /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
11144 header without the ACK UUID when using a *reliable* channel! */
11145 }
11146 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11147 }
11148 /* determine if we have to reliability-box, if so add reliability box
11149 overhead */
11150 relb = GNUNET_NO;
11151 if ((GNUNET_NO == frag) &&
11152 (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
11153 (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
11154 {
11155 real_overhead += sizeof(struct TransportReliabilityBoxMessage);
11156
11157 if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu))
11158 {
11159 frag = GNUNET_YES;
11160 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11161 }
11162 else
11163 {
11164 relb = GNUNET_YES;
11165 }
11167 "Create reliability box of msg with size %u, realoverhead is %lu %u %u %u\n",
11168 pos->bytes_msg,
11169 real_overhead,
11170 queue->mtu,
11171 frag,
11172 relb);
11173 }
11174
11175 /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
11176 message would beat it! */
11177 if (GNUNET_NO == sc->frags_in_flight && NULL != sc->best)
11178 {
11179 /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
11180 OPTIMIZE-ME: This is a heuristic, which so far has NOT been
11181 experimentally validated. There may be some huge potential for
11182 improvement here. Also, we right now only compare how well the
11183 given message fits _this_ queue, and do not consider how well other
11184 queues might suit the message. Taking other queues into consideration
11185 may further improve the result, but could also be expensive
11186 in terms of CPU time. */
11187 long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
11188 long long pm_score = frag * 40 + relb * 20 + real_overhead;
11189 long long time_delta =
11190 (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
11191 / 1000LL;
11192
11193 /* "time_delta" considers which message has been 'ready' for transmission
11194 for longer, if a message has a preference for low latency, increase
11195 the weight of the time_delta by 10x if it is favorable for that message */
11196 if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11197 (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
11198 time_delta *= 10; /* increase weight (always, both are low latency) */
11199 else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11200 (time_delta > 0))
11201 time_delta *= 10; /* increase weight, favors 'pos', which is low latency */
11202 else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11203 (time_delta < 0))
11204 time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */
11205 if (0 != queue->mtu)
11206 {
11207 /* Grant bonus if we are below MTU, larger bonus the closer we will
11208 be to the MTU */
11209 if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
11210 sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
11211 if (queue->mtu > real_overhead + pos->bytes_msg)
11212 pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
11213 }
11214 if (sc_score + time_delta > pm_score)
11215 {
11217 "sc_score of %" PRIu64 " larger, keep sc->best %" PRIu64
11218 "\n",
11219 pos->logging_uuid,
11220 sc->best->logging_uuid);
11221 continue; /* sc_score larger, keep sc->best */
11222 }
11223 }
11224 sc->best = pos;
11225 sc->dvh = dvh;
11226 sc->frag = frag;
11227 sc->relb = relb;
11228 sc->real_overhead = real_overhead;
11229 }
11230}
11231
11232
11243static void
11244extract_box_cb (void *cls,
11245 struct Neighbour *next_hop,
11246 const struct GNUNET_MessageHeader *hdr,
11248{
11249 struct PendingMessageScoreContext *sc = cls;
11250 struct PendingMessage *pm = sc->best;
11251 struct PendingMessage *bpm;
11252 uint16_t bsize = ntohs (hdr->size);
11253
11254 GNUNET_assert (NULL == pm->bpm);
11255 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
11257 "5 created pm %p storing vl %p from pm %p\n",
11258 bpm,
11259 pm->vl,
11260 pm);
11262 bpm->pmt = PMT_DV_BOX;
11263 bpm->vl = pm->vl;
11264 bpm->timeout = pm->timeout;
11265 bpm->bytes_msg = bsize;
11266 bpm->frag_parent = pm;
11269 "Creating DV Box %" PRIu64 " for original message %" PRIu64
11270 " (next hop is %s)\n",
11272 pm->logging_uuid,
11273 GNUNET_i2s (&next_hop->pid));
11274 memcpy (&bpm[1], hdr, bsize);
11275 pm->bpm = bpm;
11276}
11277
11278
11294static void
11295transmit_on_queue (void *cls)
11296{
11297 struct Queue *queue = cls;
11298 struct Neighbour *n = queue->neighbour;
11300 struct PendingMessage *pm;
11301
11302 queue->transmit_task = NULL;
11303 if (NULL == n->vl)
11304 {
11306 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
11307 GNUNET_i2s (&n->pid),
11308 queue->address);
11309 queue->idle = GNUNET_YES;
11310 return;
11311 }
11312 memset (&sc, 0, sizeof(sc));
11313 select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
11314 if (NULL == sc.best)
11315 {
11316 /* Also look at DVH that have the n as first hop! */
11317 for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
11318 dvh = dvh->next_neighbour)
11319 {
11321 queue,
11322 dvh->dv->vl,
11323 dvh,
11324 sizeof(struct GNUNET_PeerIdentity)
11325 * (1 + dvh->distance)
11326 + sizeof(struct TransportDVBoxMessage)
11327 + sizeof(struct TransportDVBoxPayloadP));
11328 }
11329 }
11330 if (NULL == sc.best)
11331 {
11332 /* no message pending, nothing to do here! */
11334 "No pending messages, queue `%s' to %s now idle\n",
11335 queue->address,
11336 GNUNET_i2s (&n->pid));
11337 if (GNUNET_YES == sc.to_early)
11338 schedule_transmit_on_queue (sc.to_early_retry_delay,
11339 queue,
11341 queue->idle = GNUNET_YES;
11342 return;
11343 }
11344 /* There is a message pending, we are certainly not idle */
11345 queue->idle = GNUNET_NO;
11346
11347 /* Given selection in `sc`, do transmission */
11348 pm = sc.best;
11350 "Selected message <%" PRIu64 ">\n",
11351 pm->logging_uuid);
11352 if (NULL != sc.dvh)
11353 {
11355 "Is this %u a DV box?\n",
11356 pm->pmt);
11357 GNUNET_assert (PMT_DV_BOX != pm->pmt);
11358 if ((NULL != sc.best->bpm) && (sc.best->bpm->used_dvh != sc.dvh))
11359 {
11361 "Discard old box, because we have a new DV path.\n");
11362 free_pending_message (sc.best->bpm);
11363 sc.best->bpm = NULL;
11364 }
11365
11366 if (NULL == sc.best->bpm)
11367 {
11369 "encapsulate_for_dv 2\n");
11370 encapsulate_for_dv (sc.dvh->dv,
11371 1,
11372 &sc.dvh,
11373 (const struct GNUNET_MessageHeader *) &sc.best[1],
11375 &sc,
11376 RMO_NONE,
11377 GNUNET_NO);
11378 GNUNET_assert (NULL != sc.best->bpm);
11380 "%lu %lu %lu %lu %u\n",
11381 sizeof(struct GNUNET_PeerIdentity),
11382 sizeof(struct TransportDVBoxMessage),
11383 sizeof(struct TransportDVBoxPayloadP),
11384 sizeof(struct TransportFragmentBoxMessage),
11385 ((const struct GNUNET_MessageHeader *) &sc.best[1])->size);
11386 sc.best->bpm->used_dvh = sc.dvh;
11387 }
11388 pm = sc.best->bpm;
11389 }
11390 if (GNUNET_YES == sc.frag)
11391 {
11392 pm = fragment_message (queue, sc.dvh, pm);
11393 if (NULL == pm)
11394 {
11396 "Fragmentation failed queue %s to %s for <%" PRIu64
11397 ">, trying again\n",
11398 queue->address,
11399 GNUNET_i2s (&n->pid),
11400 sc.best->logging_uuid);
11402 queue,
11404 return;
11405 }
11406 }
11407 else if (GNUNET_YES == sc.relb)
11408 {
11410 if (NULL == pm)
11411 {
11412 /* Reliability boxing failed, try next message... */
11413 GNUNET_log (
11415 "Reliability boxing failed queue %s to %s for <%" PRIu64
11416 ">, trying again\n",
11417 queue->address,
11418 GNUNET_i2s (&n->pid),
11419 sc.best->logging_uuid);
11421 queue,
11423 return;
11424 }
11425 }
11426
11427 /* Pass 'pm' for transission to the communicator */
11428 GNUNET_log (
11430 "Passing message <%" PRIu64
11431 "> to queue %s for peer %s (considered %u others)\n",
11432 pm->logging_uuid,
11433 queue->address,
11434 GNUNET_i2s (&n->pid),
11435 sc.consideration_counter);
11436
11437 /* Flow control: increment amount of traffic sent; if we are routing
11438 via DV (and thus the ultimate target of the pending message is for
11439 a different virtual link than the one of the queue), then we need
11440 to use up not only the window of the direct link but also the
11441 flow control window for the DV link! */
11442 pm->vl->outbound_fc_window_size_used += pm->bytes_msg;
11443
11444 if (pm->vl != queue->neighbour->vl)
11445 {
11446 /* If the virtual link of the queue differs, this better be distance
11447 vector routing! */
11448 GNUNET_assert (NULL != sc.dvh);
11449 /* If we do distance vector routing, we better not do this for a
11450 message that was itself DV-routed */
11451 GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
11452 /* We use the size of the unboxed message here, to avoid counting
11453 the DV-Box header which is eaten up on the way by intermediaries */
11454 queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
11455 }
11456 else
11457 {
11458 GNUNET_assert (NULL == sc.dvh);
11459 }
11460
11461 queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
11462
11463 /* Check if this transmission somehow conclusively finished handing 'pm'
11464 even without any explicit ACKs */
11465 if ((PMT_CORE == pm->pmt) ||
11466 (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
11467 {
11469 }
11470 else
11471 {
11472 struct GNUNET_TIME_Relative wait_duration;
11473 unsigned int wait_multiplier;
11474
11475 if (PMT_FRAGMENT_BOX == pm->pmt)
11476 {
11477 struct PendingMessage *root;
11478
11479 root = pm->frag_parent;
11480 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11481 root = root->frag_parent;
11482
11483 wait_multiplier = (unsigned int) ceil ((double) root->bytes_msg
11484 / ((double) root->frag_off
11485 / (double) root->frag_count))
11486 * 4;
11487 }
11488 else
11489 {
11490 // No fragments, we use 4 RTT before retransmitting.
11491 wait_multiplier = 4;
11492 }
11493
11494 // Depending on how much pending message the VirtualLink is queueing, we wait longer.
11495 // wait_multiplier = wait_multiplier * pm->vl->pending_msg_num;
11496
11498 "Wait multiplier %u\n",
11499 wait_multiplier);
11500
11501 /* Message not finished, waiting for acknowledgement.
11502 Update time by which we might retransmit 's' based on queue
11503 characteristics (i.e. RTT); it takes one RTT for the message to
11504 arrive and the ACK to come back in the best case; but the other
11505 side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
11506 retransmitting.
11507
11508 OPTIMIZE: Note that in the future this heuristic should likely
11509 be improved further (measure RTT stability, consider message
11510 urgency and size when delaying ACKs, etc.) */
11511
11512 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
11513 queue->pd.aged_rtt.rel_value_us)
11514 wait_duration = queue->pd.aged_rtt;
11515 else
11516 {
11517 wait_duration = DEFAULT_ACK_WAIT_DURATION;
11518 wait_multiplier = 4;
11519 }
11520 {
11523 wait_duration, wait_multiplier));
11525 wait_duration, wait_multiplier);
11527 "Waiting %s for ACK until %s\n",
11532 GNUNET_TIME_relative_multiply (wait_duration,
11533 wait_multiplier))
11534 );
11535 }
11536 }
11537 /* finally, re-schedule queue transmission task itself */
11539 queue,
11541}
11542
11543
11550static void
11551handle_del_queue_message (void *cls,
11552 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
11553{
11554 struct TransportClient *tc = cls;
11555
11556 if (CT_COMMUNICATOR != tc->type)
11557 {
11558 GNUNET_break (0);
11560 return;
11561 }
11562 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11563 queue = queue->next_client)
11564 {
11565 struct Neighbour *neighbour = queue->neighbour;
11566
11567 if ((ntohl (dqm->qid) != queue->qid) ||
11568 (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
11569 continue;
11571 "Dropped queue %s to peer %s\n",
11572 queue->address,
11573 GNUNET_i2s (&neighbour->pid));
11574 free_queue (queue);
11576 return;
11577 }
11578 GNUNET_break (0);
11580}
11581
11582
11583static void
11585 struct TransportClient *tc)
11586{
11587 struct PendingMessage *pm;
11588
11589 GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
11590 qe->queue->queue_tail,
11591 qe);
11592 qe->queue->queue_length--;
11593 tc->details.communicator.total_queue_length--;
11595 "Received ACK on queue %s (QID %u) to peer %s (new length: %u/%u)\n",
11596 qe->queue->address,
11597 qe->queue->qid,
11598 GNUNET_i2s (&qe->queue->neighbour->pid),
11599 qe->queue->queue_length,
11600 tc->details.communicator.total_queue_length);
11601
11602 /* if applicable, resume transmissions that waited on ACK */
11604 tc->details.communicator.total_queue_length)
11605 {
11606 /* Communicator dropped below threshold, resume all queues
11607 incident with this client! */
11609 GST_stats,
11610 "# Transmission throttled due to communicator queue limit",
11611 -1,
11612 GNUNET_NO);
11613 for (struct Queue *queue = tc->details.communicator.queue_head;
11614 NULL != queue;
11615 queue = queue->next_client)
11616 {
11618 queue,
11620 }
11621 }
11622 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
11623 {
11624 /* queue dropped below threshold; only resume this one queue */
11626 "# Transmission throttled due to queue queue limit",
11627 -1,
11628 GNUNET_NO);
11630 qe->queue,
11632 }
11633 else if (1 == qe->queue->q_capacity)
11634 {
11635 // TODO I guess this will never happen, because the communicator triggers this by updating its queue length itself.
11637 "Transmission rescheduled due to communicator message queue with qid %u has capacity %"
11638 PRIu64 ".\n",
11639 qe->queue->qid,
11640 qe->queue->q_capacity);
11641 /* message queue has capacity; only resume this one queue */
11642 /* queue dropped below threshold; only resume this one queue */
11644 "# Transmission throttled due to message queue capacity",
11645 -1,
11646 GNUNET_NO);
11648 qe->queue,
11650 }
11651
11652 if (NULL != (pm = qe->pm))
11653 {
11654 struct VirtualLink *vl;
11655
11656 // GNUNET_assert (qe == pm->qe);
11657 pm->qe = NULL;
11658 /* If waiting for this communicator may have blocked transmission
11659 of pm on other queues for this neighbour, force schedule
11660 transmit on queue for queues of the neighbour */
11661 if (NULL == pm->frag_parent)
11662 {
11663 vl = pm->vl;
11664 if ((NULL != vl) &&
11665 (NULL != vl->pending_msg_head) &&
11666 (vl->pending_msg_head == pm))
11668 }
11669 }
11670 GNUNET_free (qe);
11671}
11672
11673
11680static void
11681handle_send_message_ack (void *cls,
11682 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
11683{
11684 struct TransportClient *tc = cls;
11685 struct QueueEntry *qe;
11686
11687 if (CT_COMMUNICATOR != tc->type)
11688 {
11689 GNUNET_break (0);
11691 return;
11692 }
11693
11694 /* find our queue entry matching the ACK */
11695 qe = NULL;
11697 "Looking for queue for PID %s\n",
11698 GNUNET_i2s (&sma->receiver));
11699 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11700 queue = queue->next_client)
11701 {
11702 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
11703 continue;
11705 "Found PID %s\n",
11706 GNUNET_i2s (&queue->neighbour->pid));
11707
11708
11709 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
11710 qep = qep->next)
11711 {
11712 if (qep->mid != GNUNET_ntohll (sma->mid) || queue->qid != ntohl (
11713 sma->qid))
11714 continue;
11716 "QueueEntry MID: %" PRIu64 " on queue QID: %u, Ack MID: %"
11717 PRIu64 " Ack QID %u\n",
11718 qep->mid,
11719 queue->qid,
11720 GNUNET_ntohll (sma->mid),
11721 ntohl (sma->qid));
11722 qe = qep;
11723 if ((NULL != qe->pm) && (qe->pm->qe != qe))
11725 "For pending message %" PRIu64 " we had retransmissions.\n",
11726 qe->pm->logging_uuid);
11727 break;
11728 }
11729 }
11730 if (NULL == qe)
11731 {
11733 "No QueueEntry found for Ack MID %" PRIu64 " QID: %u\n",
11734 GNUNET_ntohll (sma->mid),
11735 ntohl (sma->qid));
11736 // TODO I guess this can happen, if the Ack from the peer comes before the Ack from the queue.
11737 // Update: Maybe QueueEntry was accidentally freed during freeing PendingMessage.
11738 /* this should never happen */
11739 // GNUNET_break (0);
11740 // GNUNET_SERVICE_client_drop (tc->client);
11742 return;
11743 }
11746}
11747
11748
11754static void
11755handle_burst_finished (void *cls,
11756 const struct GNUNET_TRANSPORT_BurstFinished *bf)
11757{
11759}
11760
11761
11771static int
11772notify_client_queues (void *cls,
11773 const struct GNUNET_PeerIdentity *pid,
11774 void *value)
11775{
11776 struct TransportClient *tc = cls;
11777 struct Neighbour *neighbour = value;
11778
11779 GNUNET_assert (CT_MONITOR == tc->type);
11780 for (struct Queue *q = neighbour->queue_head; NULL != q;
11781 q = q->next_neighbour)
11782 {
11783 struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
11784 .cs = q->cs,
11785 .num_msg_pending = q->num_msg_pending,
11786 .num_bytes_pending = q->num_bytes_pending };
11787
11788 notify_monitor (tc, pid, q->address, q->nt, &me);
11789 }
11790 return GNUNET_OK;
11791}
11792
11793
11800static void
11801handle_monitor_start (void *cls,
11803{
11804 struct TransportClient *tc = cls;
11805
11806 if (CT_NONE != tc->type)
11807 {
11808 GNUNET_break (0);
11810 return;
11811 }
11812 tc->type = CT_MONITOR;
11813 tc->details.monitor.peer = start->peer;
11814 tc->details.monitor.one_shot = ntohl (start->one_shot);
11818}
11819
11820
11828static struct TransportClient *
11829lookup_communicator (const char *prefix)
11830{
11831 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
11832 {
11833 if (CT_COMMUNICATOR != tc->type)
11834 continue;
11835 if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
11836 return tc;
11837 }
11838 GNUNET_log (
11840 "Someone suggested use of communicator for `%s', but we do not have such a communicator!\n",
11841 prefix);
11842 return NULL;
11843}
11844
11845
11853static void
11854suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address)
11855{
11856 static uint32_t idgen = 0;
11857 struct TransportClient *tc;
11858 char *prefix;
11859 struct GNUNET_TRANSPORT_CreateQueue *cqm;
11860 struct GNUNET_MQ_Envelope *env;
11861 size_t alen;
11862
11864 if (NULL == prefix)
11865 {
11866 GNUNET_break (0); /* We got an invalid address!? */
11867 return;
11868 }
11870 if (NULL == tc)
11871 {
11873 "# Suggestions ignored due to missing communicator",
11874 1,
11875 GNUNET_NO);
11877 "Cannot connect to %s at `%s', no matching communicator present\n",
11878 GNUNET_i2s (pid),
11879 address);
11881 return;
11882 }
11883 /* forward suggestion for queue creation to communicator */
11885 "Request #%u for `%s' communicator to create queue to `%s' at `%s'\n",
11886 (unsigned int) idgen,
11887 prefix,
11888 GNUNET_i2s (pid),
11889 address);
11891 alen = strlen (address) + 1;
11892 env =
11894 cqm->request_id = htonl (idgen++);
11895 cqm->receiver = *pid;
11896 memcpy (&cqm[1], address, alen);
11897 GNUNET_MQ_send (tc->mq, env);
11898}
11899
11900
11908static void
11910{
11912 struct GNUNET_TIME_Absolute monotonic_time;
11913
11914 if (NULL != vs->revalidation_task)
11915 {
11916 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
11917 vs->revalidation_task = NULL;
11918 }
11919 /*memcpy (&hkey,
11920 &hc,
11921 sizeof (hkey));*/
11923 "Remove key %s for address %s map size %u contains %u\n",
11924 GNUNET_h2s (&vs->hc),
11925 vs->address,
11928 &vs->hc));
11930
11932 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
11933 vs->last_challenge_use.abs_value_us)
11934 {
11935 vs->first_challenge_use = monotonic_time;
11936 }
11937 vs->last_challenge_use = monotonic_time;
11938 tvc.header.type =
11940 tvc.header.size = htons (sizeof(tvc));
11941 tvc.reserved = htonl (0);
11942 tvc.challenge = vs->challenge;
11943 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
11945 "Sending address validation challenge %s to %s\n",
11947 GNUNET_i2s (&q->neighbour->pid));
11948 queue_send_msg (q, NULL, &tvc, sizeof(tvc));
11949}
11950
11951
11957static void
11958validation_start_cb (void *cls)
11959{
11960 struct ValidationState *vs;
11961 struct Queue *q;
11963 GST_cfg);
11964
11965 (void) cls;
11966 validation_task = NULL;
11968 /* drop validations past their expiration */
11969 while (
11970 (NULL != vs) &&
11972 {
11974 "Validation response %s cleaned up\n",
11975 GNUNET_sh2s (&vs->challenge.value));
11978 }
11979 if (NULL == vs)
11980 {
11982 "Address validation task not scheduled anymore, nothing to do\n");
11983 return; /* woopsie, no more addresses known, should only
11984 happen if we're really a lonely peer */
11985 }
11986 q = find_queue (&vs->pid, vs->address);
11987 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
11988 {
11990 "To early to start next address validation for challenge %s\n",
11991 GNUNET_sh2s (&vs->challenge.value));
11992 return;
11993 }
11994 if (NULL == q)
11995 {
11996 vs->awaiting_queue = GNUNET_YES;
11997 suggest_to_connect (&vs->pid, vs->address);
11998 }
11999 else
12001 /* Finally, reschedule next attempt */
12002 vs->challenge_backoff =
12003 GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
12006 "Address validation task will run again in %s\n",
12007 GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
12008 GNUNET_YES));
12011 vs->challenge_backoff));
12012}
12013
12014
12019{
12023 struct Queue *q;
12024
12028 unsigned int quality_count;
12029
12033 unsigned int num_queues;
12034
12039 unsigned int k;
12040};
12041
12042
12054static int
12055check_connection_quality (void *cls,
12056 const struct GNUNET_PeerIdentity *pid,
12057 void *value)
12058{
12059 struct QueueQualityContext *ctx = cls;
12060 struct Neighbour *n = value;
12061 int do_inc;
12062
12063 (void) pid;
12064 do_inc = GNUNET_NO;
12065 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
12066 {
12067 ctx->num_queues++;
12068 if (0 == ctx->k--)
12069 ctx->q = q;
12070 /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
12071 statistics and consider those as well here? */
12072 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
12073 do_inc = GNUNET_YES;
12074 }
12075 if (GNUNET_YES == do_inc)
12076 ctx->quality_count++;
12077 return GNUNET_OK;
12078}
12079
12080
12092static void
12093start_dv_learn (void *cls);
12094
12095
12096struct SignDvInitCls
12097{
12099 struct LearnLaunchEntry *lle;
12100 struct QueueQualityContext qqc;
12101 struct PilsRequest *pr;
12102};
12103
12104
12105static void
12106sign_dv_init_cb (void *cls,
12107 const struct GNUNET_PeerIdentity *pid,
12108 const struct GNUNET_CRYPTO_EddsaSignature *sig)
12109{
12110 const struct GNUNET_PeerIdentity *my_identity;
12111 struct SignDvInitCls *sign_dv_init_cls = cls;
12112 struct TransportDVLearnMessage dvl = sign_dv_init_cls->dvl;
12113 struct LearnLaunchEntry *lle = sign_dv_init_cls->lle;
12114 struct QueueQualityContext qqc = sign_dv_init_cls->qqc;
12115
12118
12119 sign_dv_init_cls->pr->op = NULL;
12122 sign_dv_init_cls->pr);
12123 GNUNET_free (sign_dv_init_cls->pr);
12124
12125 dvl.init_sig = *sig;
12126 dvl.initiator = *my_identity;
12127 dvl.challenge = lle->challenge;
12128
12129 qqc.quality_count = 0;
12131 qqc.num_queues = 0;
12132 qqc.q = NULL;
12135 &qqc);
12136 GNUNET_assert (NULL != qqc.q);
12137
12138 /* Do this as close to transmission time as possible! */
12140
12141 queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
12142 /* reschedule this job, randomizing the time it runs (but no
12143 actual backoff!) */
12144 if (NULL != dvlearn_task)
12149 NULL);
12150}
12151
12152
12164static void
12165start_dv_learn (void *cls)
12166{
12167 struct LearnLaunchEntry *lle;
12168 struct QueueQualityContext qqc;
12169 struct TransportDVLearnMessage dvl;
12170 const struct GNUNET_PeerIdentity *my_identity;
12171
12172 (void) cls;
12173 dvlearn_task = NULL;
12175 return; /* lost all connectivity, cannot do learning */
12176 qqc.quality_count = 0;
12177 qqc.num_queues = 0;
12181 &qqc);
12183 {
12184 struct GNUNET_TIME_Relative delay;
12185 unsigned int factor;
12186
12187 /* scale our retries by how far we are above the threshold */
12191 "At connection quality %u, will launch DV learn in %s\n",
12192 qqc.quality_count,
12195 return;
12196 }
12197 /* remove old entries in #dvlearn_map if it has grown too big */
12198 while (MAX_DV_LEARN_PENDING <=
12200 {
12201 lle = lle_tail;
12204 &lle->challenge.value,
12205 lle));
12207 GNUNET_free (lle);
12208 }
12209 /* setup data structure for learning */
12210 lle = GNUNET_new (struct LearnLaunchEntry);
12212 sizeof(lle->challenge));
12214 "Starting launch DV learn with challenge %s\n",
12215 GNUNET_sh2s (&lle->challenge.value));
12220 &lle->challenge.value,
12221 lle,
12226 dvl.header.size = htons (sizeof(dvl));
12227 dvl.num_hops = htons (0);
12228 dvl.bidirectional = htons (0);
12230 dvl.monotonic_time =
12232 // We will set the below again later
12233 memset (&dvl.init_sig, 0, sizeof dvl.init_sig);
12234 dvl.challenge = lle->challenge;
12235 dvl.initiator = *my_identity;
12236 {
12237 struct DvInitPS dvip = {
12238 .purpose.purpose = htonl (
12240 .purpose.size = htonl (sizeof(dvip)),
12241 .monotonic_time = dvl.monotonic_time,
12242 .challenge = lle->challenge
12243 };
12244 struct SignDvInitCls *sign_dv_init_cls;
12245
12246 sign_dv_init_cls = GNUNET_new (struct SignDvInitCls);
12247 sign_dv_init_cls->dvl = dvl;
12248 sign_dv_init_cls->lle = lle;
12249 sign_dv_init_cls->qqc = qqc;
12250 sign_dv_init_cls->pr = GNUNET_new (struct PilsRequest);
12253 sign_dv_init_cls->pr);
12254 sign_dv_init_cls->pr->op =
12256 &dvip.purpose,
12258 sign_dv_init_cls);
12259 }
12260}
12261
12262
12270static char *
12272{
12273 const char *colon;
12274 char *colon_rest;
12275 size_t colon_rest_length;
12276 char *address_without_port;
12277
12278 colon = strchr (address,':');
12279 colon_rest = GNUNET_strndup (address, colon - address);
12280 colon_rest_length = strlen (colon_rest);
12281 address_without_port = GNUNET_strndup (&colon_rest[4], colon_rest_length - 4);
12282 GNUNET_free (colon_rest);
12283
12284 return address_without_port;
12285}
12286
12287
12297static int
12299 const struct GNUNET_PeerIdentity *pid,
12300 void *value)
12301{
12302 struct Queue *q = cls;
12303 struct ValidationState *vs = value;
12304 char *address_without_port_vs;
12305 char *address_without_port_q;
12306 int success = GNUNET_YES;
12307
12308 // TODO Check if this is really necessary.
12309 address_without_port_vs = get_address_without_port (vs->address);
12310 address_without_port_q = get_address_without_port (q->address);
12311
12313 "Check validation request pending for `%s' at `%s'/`%s' (vs)/(q)\n",
12314 GNUNET_i2s (pid),
12315 address_without_port_vs,
12316 address_without_port_q);
12317 (void) pid;
12318 if ((GNUNET_YES == vs->awaiting_queue) &&
12319 (0 == strcmp (address_without_port_vs, address_without_port_q)))
12320 {
12321
12322 vs->awaiting_queue = GNUNET_NO;
12324 success = GNUNET_NO;
12325 }
12326
12327 GNUNET_free (address_without_port_vs);
12328 GNUNET_free (address_without_port_q);
12329 return success;
12330}
12331
12332
12341static void
12342neighbour_dv_monotime_cb (void *cls,
12343 const struct GNUNET_PEERSTORE_Record *record,
12344 const char *emsg)
12345{
12346 struct Neighbour *n = cls;
12347 struct GNUNET_TIME_AbsoluteNBO *mtbe;
12348
12349 (void) emsg;
12350 if (NULL == record)
12351 {
12352 /* we're done with #neighbour_dv_monotime_cb() invocations,
12353 continue normal processing */
12354 n->get = NULL;
12356 return;
12357 }
12358 if (0 == record->value_size)
12359 {
12361 GNUNET_break (0);
12362 return;
12363 }
12364 mtbe = record->value;
12369}
12370
12371
12372static void
12374 const struct GNUNET_PeerIdentity *pid,
12375 const char *uri)
12376{
12377 struct Queue *queue = cls;
12378 struct sockaddr_in v4;
12379 const char *slash;
12380 char *address_uri;
12381 char *prefix;
12382 char *uri_without_port;
12383 char *address_uri_without_port;
12384
12385 slash = strrchr (uri, '/');
12386 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
12387 GNUNET_assert (NULL != slash);
12388 slash++;
12389 GNUNET_asprintf (&address_uri,
12390 "%s-%s",
12391 prefix,
12392 slash);
12393
12395 "1 not global natted_address %u %s %s %s\n",
12396 queue->is_global_natted,
12397 uri,
12398 queue->address,
12399 slash);
12400
12401 uri_without_port = get_address_without_port (address_uri);
12402 if (1 != inet_pton (AF_INET, uri_without_port, &v4.sin_addr))
12403 {
12405 GNUNET_free (address_uri);
12406 GNUNET_free (uri_without_port);
12407 return;
12408 }
12409
12411 "2 not global natted_address %u %s %s\n",
12412 queue->is_global_natted,
12413 uri,
12414 queue->address);
12415
12416 if (GNUNET_NO == queue->is_global_natted)
12417 {
12419 GNUNET_free (address_uri);
12420 GNUNET_free (uri_without_port);
12421 return;
12422 }
12423
12425 "3 not global natted_address %u %s %s\n",
12426 queue->is_global_natted,
12427 uri,
12428 queue->address);
12429
12430 if (0 == strcmp (uri_without_port, address_uri))
12431 {
12433 GNUNET_free (address_uri);
12434 GNUNET_free (uri_without_port);
12435 return;
12436 }
12437
12439 "4 not global natted_address %u %s %s\n",
12440 queue->is_global_natted,
12441 uri,
12442 queue->address);
12443
12444 address_uri_without_port = get_address_without_port (queue->address);
12445 if (0 == strcmp (uri_without_port, address_uri_without_port))
12446 {
12447 queue->is_global_natted = GNUNET_NO;
12448 }
12449
12451 "not global natted_address %u %s %s %s %s %s %u\n",
12452 queue->is_global_natted,
12453 uri,
12454 queue->address,
12455 uri_without_port,
12456 address_uri_without_port,
12457 prefix,
12458 GNUNET_NO);
12460 GNUNET_free (address_uri);
12461 GNUNET_free (address_uri_without_port);
12462 GNUNET_free (uri_without_port);
12463}
12464
12465
12467{
12471 char *addr;
12472
12477};
12478
12479
12480static enum GNUNET_GenericReturnValue
12481contains_address (void *cls,
12482 const struct GNUNET_PeerIdentity *pid,
12483 void *value)
12484{
12485 struct TransportGlobalNattedAddressClosure *tgna_cls = cls;
12486 struct TransportGlobalNattedAddress *tgna = value;
12487 char *addr = (char *) &tgna[1];
12488
12490 "Checking tgna %p with addr %s and length %u compare length %lu\n",
12491 tgna,
12492 addr,
12493 ntohl (tgna->address_length),
12494 strlen (tgna_cls->addr));
12495 if (strlen (tgna_cls->addr) == ntohl (tgna->address_length)
12496 && 0 == strncmp (addr, tgna_cls->addr, ntohl (tgna->address_length)))
12497 {
12498 tgna_cls->tgna = tgna;
12499 return GNUNET_NO;
12500 }
12501 return GNUNET_YES;
12502}
12503
12504
12505static void
12507{
12509 "Error in PEERSTORE monitoring for checking global natted\n");
12510}
12511
12512
12513static void
12515{
12517 "Done with initial PEERSTORE iteration during monitoring for checking global natted\n");
12518}
12519
12520
12521static void
12522check_for_global_natted (void *cls,
12523 const struct GNUNET_PEERSTORE_Record *record,
12524 const char *emsg)
12525{
12526 struct Queue *queue = cls;
12527 struct Neighbour *neighbour = queue->neighbour;
12529 struct GNUNET_MessageHeader *hello;
12531 size_t address_len_without_port;
12532
12533 if (NULL != emsg)
12534 {
12536 "Got failure from PEERSTORE: %s\n",
12537 emsg);
12538 return;
12539 }
12540 if (0 == record->value_size)
12541 {
12543 GNUNET_break (0);
12544 return;
12545 }
12546 queue->is_global_natted = GNUNET_YES;
12547 hello = record->value;
12548 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
12550 "before not global natted %u\n",
12551 queue->is_global_natted);
12554 queue);
12556 "after not global natted %u\n",
12557 queue->is_global_natted);
12558 GNUNET_HELLO_parser_free (parser);
12559
12560 tgna_cls.addr = get_address_without_port (queue->address);
12561 address_len_without_port = strlen (tgna_cls.addr);
12562 /*{
12563 char buf[address_len_without_port + 1];
12564
12565 GNUNET_memcpy (&buf, addr, address_len_without_port);
12566 buf[address_len_without_port] = '\0';
12567 GNUNET_free (addr);
12568 GNUNET_memcpy (tgna_cls.addr, buf, address_len_without_port + 1);
12569 }*/
12570 tgna_cls.tgna = NULL;
12572 &neighbour->pid,
12574 &tgna_cls);
12575 if (NULL != tgna_cls.tgna)
12577 " tgna_cls.tgna tgna %p %lu %u %u\n",
12578 tgna_cls.tgna,
12579 neighbour->size_of_global_addresses,
12580 ntohl (tgna_cls.tgna->address_length),
12581 neighbour->number_of_addresses);
12582 if (NULL == tgna_cls.tgna && GNUNET_YES == queue->is_global_natted)
12583 {
12584 struct TransportGlobalNattedAddress *tgna;
12585
12586 tgna = GNUNET_malloc (sizeof (struct TransportGlobalNattedAddress)
12587 + address_len_without_port);
12588 tgna->address_length = htonl (address_len_without_port);
12589 GNUNET_memcpy (&tgna[1], tgna_cls.addr, address_len_without_port);
12591 &neighbour->pid,
12592 tgna,
12594 neighbour->number_of_addresses++;
12595 neighbour->size_of_global_addresses += address_len_without_port + 1;
12597 "Created tgna %p with address %s and length %lu\n",
12598 tgna,
12599 tgna_cls.addr,
12600 address_len_without_port + 1);
12601 }
12602 else if (NULL != tgna_cls.tgna && GNUNET_NO == queue->is_global_natted)
12603 {
12605 &neighbour->pid,
12606 tgna_cls.tgna);
12607 GNUNET_assert (neighbour->size_of_global_addresses >= ntohl (tgna_cls.tgna->
12609 );
12610 neighbour->size_of_global_addresses -= ntohl (tgna_cls.tgna->address_length)
12611 ;
12612 GNUNET_assert (0 < neighbour->number_of_addresses);
12613 neighbour->number_of_addresses--;
12615 "removed tgna %p\n",
12616 tgna_cls.tgna);
12617 GNUNET_free (tgna_cls.tgna);
12618 }
12620 GNUNET_free (tgna_cls.addr);
12621}
12622
12623
12630static void
12631handle_add_queue_message (void *cls,
12632 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
12633{
12634 struct TransportClient *tc = cls;
12635 struct Queue *queue;
12636 struct Neighbour *neighbour;
12637 const char *addr;
12638 uint16_t addr_len;
12639
12640 if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
12641 {
12642 /* MTU so small as to be useless for transmissions,
12643 required for #fragment_message()! */
12644 GNUNET_break_op (0);
12646 return;
12647 }
12648 /* This may simply be a queue update */
12649 for (queue = tc->details.communicator.queue_head;
12650 NULL != queue;
12651 queue = queue->next_client)
12652 {
12653 if (queue->qid != ntohl (aqm->qid))
12654 continue;
12655 break;
12656 }
12657
12658 if (NULL != queue)
12659 {
12660 neighbour = queue->neighbour;
12661 }
12662 else
12663 {
12664 struct GNUNET_TIME_Absolute validated_until = GNUNET_TIME_UNIT_ZERO_ABS;
12665
12666 neighbour = lookup_neighbour (&aqm->receiver);
12667 if (NULL == neighbour)
12668 {
12669 neighbour = GNUNET_new (struct Neighbour);
12671 GNUNET_YES);
12672 neighbour->pid = aqm->receiver;
12675 neighbours,
12676 &neighbour->pid,
12677 neighbour,
12679 neighbour->get =
12681 "transport",
12682 &neighbour->pid,
12685 neighbour);
12686 }
12687 addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
12688 addr = (const char *) &aqm[1];
12690 "New queue %s to %s available with QID %u and q_len %" PRIu64
12691 " and mtu %u\n",
12692 addr,
12693 GNUNET_i2s (&aqm->receiver),
12694 ntohl (aqm->qid),
12695 GNUNET_ntohll (aqm->q_len),
12696 ntohl (aqm->mtu));
12697 queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
12698 queue->tc = tc;
12699 for (struct Queue *q = neighbour->queue_head; NULL != q; q = q->
12700 next_neighbour)
12701 validated_until = GNUNET_TIME_absolute_max (validated_until, q->
12702 validated_until);
12703 if (0 == GNUNET_TIME_absolute_get_remaining (validated_until).rel_value_us)
12704 {
12706 "New queue with QID %u inherit validated until\n",
12707 ntohl (aqm->qid));
12708 queue->validated_until = validated_until;
12709 }
12710 queue->address = (const char *) &queue[1];
12711 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
12712 queue->qid = ntohl (aqm->qid);
12713 queue->neighbour = neighbour;
12715 queue->unlimited_length = GNUNET_YES;
12716 queue->q_capacity = GNUNET_ntohll (aqm->q_len);
12717 memcpy (&queue[1], addr, addr_len);
12718 /* notify monitors about new queue */
12719 {
12720 struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
12721
12722 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
12723 }
12725 neighbour->queue_head,
12726 neighbour->queue_tail,
12727 queue);
12729 tc->details.communicator.queue_head,
12730 tc->details.communicator.queue_tail,
12731 queue);
12732
12733 }
12734 queue->mtu = ntohl (aqm->mtu);
12735 queue->nt = ntohl (aqm->nt);
12736 queue->cs = ntohl (aqm->cs);
12737 queue->idle = GNUNET_YES;
12738
12739 {
12740 struct sockaddr_in v4;
12741 char *addr_without = get_address_without_port (queue->address);
12742 if (1 == inet_pton (AF_INET, addr_without, &v4.sin_addr))
12743 {
12745 "start not global natted\n");
12747 GNUNET_YES,
12748 "peerstore",
12749 &neighbour->pid,
12751 &
12753 NULL,
12754 &
12756 NULL,
12758 queue);
12759 }
12760 GNUNET_free (addr_without);
12761 }
12762 /* check if valdiations are waiting for the queue */
12764 &aqm->receiver))
12765 {
12768 &aqm->
12769 receiver,
12770 &
12772 queue))
12773 start_address_validation (&aqm->receiver, queue->address);
12774 }
12775 else
12776 start_address_validation (&aqm->receiver, queue->address);
12777 /* look for traffic for this queue */
12778 // TODO Check whether this makes any sense at all.
12779 /*schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
12780 queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);*/
12781 /* might be our first queue, try launching DV learning */
12782 if (NULL == dvlearn_task)
12785}
12786
12787
12794static void
12796 const struct
12798{
12799 struct TransportClient *tc = cls;
12800 struct Queue *target_queue = NULL;
12801
12803 "Received queue update message for %u with q_len %llu and mtu %u\n",
12804 ntohl (msg->qid),
12805 (unsigned long long) GNUNET_ntohll (msg->q_len),
12806 ntohl (msg->mtu));
12807 for (target_queue = tc->details.communicator.queue_head;
12808 NULL != target_queue;
12809 target_queue = target_queue->next_client)
12810 {
12811 if (ntohl (msg->qid) == target_queue->qid)
12812 break;
12813 }
12814 if (NULL == target_queue)
12815 {
12817 "Queue to update no longer exists! Discarding update.\n");
12818 return;
12819 }
12820
12821 target_queue->nt = msg->nt;
12822 target_queue->mtu = ntohl (msg->mtu);
12823 target_queue->cs = msg->cs;
12824 target_queue->priority = ntohl (msg->priority);
12825 /* The update message indicates how many messages
12826 * the queue should be able to handle.
12827 */
12829 target_queue->unlimited_length = GNUNET_YES;
12830 else
12831 target_queue->unlimited_length = GNUNET_NO;
12832 target_queue->q_capacity += GNUNET_ntohll (msg->q_len);
12833 if (0 < target_queue->q_capacity)
12835 target_queue,
12838}
12839
12840
12848static void
12849handle_queue_create_ok (void *cls,
12850 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
12851{
12852 struct TransportClient *tc = cls;
12853
12854 if (CT_COMMUNICATOR != tc->type)
12855 {
12856 GNUNET_break (0);
12858 return;
12859 }
12861 "# Suggestions succeeded at communicator",
12862 1,
12863 GNUNET_NO);
12865 "Request #%u for communicator to create queue succeeded\n",
12866 (unsigned int) ntohs (cqr->request_id));
12868}
12869
12870
12879static void
12881 void *cls,
12882 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
12883{
12884 struct TransportClient *tc = cls;
12885
12886 if (CT_COMMUNICATOR != tc->type)
12887 {
12888 GNUNET_break (0);
12890 return;
12891 }
12893 "Request #%u for communicator to create queue failed\n",
12894 (unsigned int) ntohl (cqr->request_id));
12896 "# Suggestions failed in queue creation at communicator",
12897 1,
12898 GNUNET_NO);
12900}
12901
12902
12910static void
12911handle_suggest_cancel (void *cls, const struct ExpressPreferenceMessage *msg)
12912{
12913 struct TransportClient *tc = cls;
12914 struct PeerRequest *pr;
12915
12916 if (CT_APPLICATION != tc->type)
12917 {
12918 GNUNET_break (0);
12920 return;
12921 }
12922 pr = GNUNET_CONTAINER_multipeermap_get (tc->details.application.requests,
12923 &msg->peer);
12924 if (NULL == pr)
12925 {
12926 GNUNET_break (0);
12928 return;
12929 }
12930 (void) stop_peer_request (tc, &pr->pid, pr);
12932}
12933
12934
12935static void
12936hello_for_client_cb (void *cls,
12937 const struct GNUNET_PeerIdentity *pid,
12938 const char *uri)
12939{
12940 struct Queue *q;
12941 int pfx_len;
12942 const char *eou;
12943 char *address;
12944 (void) cls;
12945
12946 eou = strstr (uri,
12947 "://");
12948 pfx_len = eou - uri;
12949 eou += 3;
12951 "%.*s-%s",
12952 pfx_len,
12953 uri,
12954 eou);
12955
12957 "hello for client %s\n",
12958 address);
12959
12960 q = find_queue (pid, address);
12961 if (NULL == q)
12962 {
12964 }
12965 else
12968}
12969
12970
12978static void
12979handle_hello_for_client (void *cls,
12980 const struct GNUNET_PEERSTORE_Record *record,
12981 const char *emsg)
12982{
12983 const struct GNUNET_PeerIdentity *my_identity;
12984 struct PeerRequest *pr = cls;
12986 struct GNUNET_MessageHeader *hello;
12987
12988 if (NULL != emsg)
12989 {
12991 "Got failure from PEERSTORE: %s\n",
12992 emsg);
12993 return;
12994 }
12996 if (NULL == my_identity)
12997 {
12999 "No identity given yet!\n");
13000 return;
13001 }
13002 hello = record->value;
13003 if (0 == GNUNET_memcmp (&record->peer, my_identity))
13004 {
13006 return;
13007 }
13008 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
13009 if (NULL == parser)
13010 {
13012 "HELLO cannot be parsed!\n");
13013 return;
13014 }
13016 "HELLO for `%s' could be parsed, iterating addresses...!\n",
13020 NULL);
13021 GNUNET_HELLO_parser_free (parser);
13022}
13023
13024
13025static void
13026hello_for_client_error_cb (void *cls)
13027{
13029 "Error in PEERSTORE monitoring\n");
13030}
13031
13032
13033static void
13034hello_for_client_sync_cb (void *cls)
13035{
13037 "Done with initial PEERSTORE iteration during monitoring\n");
13038}
13039
13040
13048static void
13049handle_suggest (void *cls, const struct ExpressPreferenceMessage *msg)
13050{
13051 struct TransportClient *tc = cls;
13052 const struct GNUNET_PeerIdentity *my_identity;
13053 struct PeerRequest *pr;
13054
13055 if (CT_NONE == tc->type)
13056 {
13057 tc->type = CT_APPLICATION;
13058 tc->details.application.requests =
13060 }
13061 if (CT_APPLICATION != tc->type)
13062 {
13063 GNUNET_break (0);
13065 return;
13066 }
13068 if (NULL == my_identity)
13069 {
13071 "Still waiting for own identity!\n");
13073 return;
13074 }
13076 "Client suggested we talk to %s with preference %d at rate %u\n",
13077 GNUNET_i2s (&msg->peer),
13078 (int) ntohl (msg->pk),
13079 (int) ntohl (msg->bw.value__));
13080 if (0 == GNUNET_memcmp (my_identity, &msg->peer))
13081 {
13083 "Client suggested connection to ourselves, ignoring...\n");
13085 return;
13086 }
13087 pr = GNUNET_new (struct PeerRequest);
13088 pr->tc = tc;
13089 pr->pid = msg->peer;
13090 pr->bw = msg->bw;
13091 pr->pk = ntohl (msg->pk);
13093 tc->details.application.requests,
13094 &pr->pid,
13095 pr,
13097 {
13098 GNUNET_break (0);
13099 GNUNET_free (pr);
13101 return;
13102 }
13103 pr->nc =
13105 GNUNET_YES,
13106 "peerstore",
13107 NULL,
13110 NULL,
13112 NULL,
13114 pr);
13116}
13117
13118
13127static int
13129 const struct RequestHelloValidationMessage *m)
13130{
13131 (void) cls;
13133 return GNUNET_OK;
13134}
13135
13136
13144static void
13146 const struct RequestHelloValidationMessage *m)
13147{
13148 struct TransportClient *tc = cls;
13149 struct Queue *q;
13150
13151 q = find_queue (&m->peer, (const char *) &m[1]);
13152 if (NULL == q)
13153 {
13154 suggest_to_connect (&m->peer, (const char *) &m[1]);
13155 }
13156 else
13157 start_address_validation (&m->peer, (const char *) &m[1]);
13159}
13160
13161
13170static int
13171free_neighbour_cb (void *cls,
13172 const struct GNUNET_PeerIdentity *pid,
13173 void *value)
13174{
13175 struct Neighbour *neighbour = value;
13176
13177 (void) cls;
13178 (void) pid;
13179 GNUNET_break (0); // should this ever happen?
13180 free_neighbour (neighbour, GNUNET_YES);
13181
13182 return GNUNET_OK;
13183}
13184
13185
13194static int
13195free_dv_routes_cb (void *cls,
13196 const struct GNUNET_PeerIdentity *pid,
13197 void *value)
13198{
13199 struct DistanceVector *dv = value;
13200
13201 (void) cls;
13202 (void) pid;
13203 free_dv_route (dv);
13204
13205 return GNUNET_OK;
13206}
13207
13208
13217static int
13218free_validation_state_cb (void *cls,
13219 const struct GNUNET_PeerIdentity *pid,
13220 void *value)
13221{
13222 struct ValidationState *vs = value;
13223
13224 (void) cls;
13225 (void) pid;
13227 return GNUNET_OK;
13228}
13229
13230
13239static int
13240free_pending_ack_cb (void *cls, const struct GNUNET_Uuid *key, void *value)
13241{
13242 struct PendingAcknowledgement *pa = value;
13243
13244 (void) cls;
13245 (void) key;
13247 return GNUNET_OK;
13248}
13249
13250
13259static int
13260free_ack_cummulator_cb (void *cls,
13261 const struct GNUNET_PeerIdentity *pid,
13262 void *value)
13263{
13264 struct AcknowledgementCummulator *ac = value;
13265
13266 (void) cls;
13267 (void) pid;
13269 GNUNET_free (ac);
13270 return GNUNET_OK;
13271}
13272
13273
13280static void
13281do_shutdown (void *cls)
13282{
13283 struct LearnLaunchEntry *lle;
13284 struct PilsRequest *pr;
13285 (void) cls;
13286
13288 "shutdown logic\n");
13291 &free_neighbour_cb, NULL);
13292 if (NULL != validation_task)
13293 {
13295 validation_task = NULL;
13296 }
13297 if (NULL != dvlearn_task)
13298 {
13300 dvlearn_task = NULL;
13301 }
13302 if (NULL != burst_task)
13303 {
13305 burst_task = NULL;
13306 }
13307 if (NULL != burst_timeout_task)
13308 {
13310 burst_timeout_task = NULL;
13311 }
13314 dvlearn_map = NULL;
13317 dv_routes = NULL;
13318 if (NULL != GST_stats)
13319 {
13321 GST_stats = NULL;
13322 }
13323 if (NULL != GST_my_hello)
13324 {
13326 GST_my_hello = NULL;
13327 }
13330 NULL);
13332 ack_cummulators = NULL;
13335 NULL);
13337 pending_acks = NULL;
13340 neighbours = NULL;
13343 links = NULL;
13346 NULL);
13348 backtalkers = NULL;
13351 NULL);
13353 validation_map = NULL;
13355 validation_heap = NULL;
13357 revalidation_map = NULL;
13358 while (NULL != ir_head)
13360 GNUNET_assert (0 == ir_total);
13361 while (NULL != (lle = lle_head))
13362 {
13364 GNUNET_free (lle);
13365 }
13366 while (NULL != (pr = pils_requests_head))
13367 {
13370 pr);
13371 if (NULL != pr->op)
13372 GNUNET_PILS_cancel (pr->op);
13373 GNUNET_free (pr);
13374 }
13375 if (NULL != pils_feed_task)
13376 {
13378 pils_feed_task = NULL;
13379 }
13380 if (NULL != pils)
13381 {
13383 pils = NULL;
13384 }
13385 if (NULL != peerstore)
13386 {
13388 "Disconnecting from PEERSTORE service\n");
13390 peerstore = NULL;
13391 }
13393}
13394
13395
13396static const char*
13398{
13399 switch (type)
13400 {
13401 case CT_CORE:
13402 return "CORE";
13403 case CT_MONITOR:
13404 return "MONITOR";
13405 case CT_COMMUNICATOR:
13406 return "COMMUNICATOR";
13407 case CT_APPLICATION:
13408 return "APPLICATION";
13409 default:
13410 return "UNKNOWN";
13411 }
13412}
13413
13414
13415static void
13416shutdown_task (void *cls)
13417{
13419
13421 "Shutdown task executed\n");
13422 if (NULL != clients_head)
13423 {
13424 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
13425 {
13427 "Client still connected: %s\n",
13428 get_client_type_name (tc->type));
13429 }
13430 }
13431 else
13432 do_shutdown (cls);
13433
13434}
13435
13436
13438{
13440};
13441
13442static void
13443update_hello_from_pid_change_cb (void *cls, int success)
13444{
13445 struct UpdateHelloFromPidCtx *pc = cls;
13446
13447 if (GNUNET_OK != success)
13448 {
13450 "Failed to store our new hello with peerstore\n");
13451 }
13452 GNUNET_free (pc);
13454 "Stored our new hello with peerstore\n");
13455}
13456
13457
13458void
13459print_address_list (void *cls,
13460 const struct GNUNET_PeerIdentity *pid,
13461 const char *uri)
13462{
13464 "%s\n", uri);
13465}
13466
13467
13477static void
13478pils_pid_change_cb (void *cls,
13479 const struct GNUNET_HELLO_Parser *parser,
13480 const struct GNUNET_HashCode *hash)
13481{
13482 const struct GNUNET_PeerIdentity *my_identity;
13483 struct GNUNET_MQ_Envelope *env;
13484 const struct GNUNET_MessageHeader *msg;
13485 struct UpdateHelloFromPidCtx *sc;
13486 struct GNUNET_HELLO_Builder *nbuilder;
13487 struct GNUNET_PeerIdentity npid;
13488
13491
13492 if (NULL == GST_my_hello)
13495 "My current identity is `%s'\n",
13507 nbuilder = GNUNET_HELLO_builder_from_parser (parser,
13508 &npid);
13509 if (GNUNET_NO ==
13511 {
13513 "New PID from PILS is derived from address list inconsistent with ours. Ignoring...\n");
13515 "Proposed address list:\n");
13518 "Current address list:\n");
13520 GNUNET_HELLO_builder_free (nbuilder);
13521 return;
13522 }
13524 GST_my_hello = nbuilder;
13526 "My new identity is `%s'\n",
13532 msg,
13534 sc);
13535 GNUNET_free (env);
13536}
13537
13538
13546static void
13547run (void *cls,
13548 const struct GNUNET_CONFIGURATION_Handle *c,
13550{
13551 (void) cls;
13552 (void) service;
13553 /* setup globals */
13556 GST_cfg = c;
13564 GNUNET_YES);
13569 // TODO check for all uses of GST_my_hello that it is not used uninitialized
13571 "transport",
13572 "USE_BURST_NAT");
13573 if (GNUNET_SYSERR == use_burst)
13575 "Could not configure burst nat use. Default to no.\n");
13581 "transport",
13582 0,
13583 0,
13584 NULL,
13585 0,
13586 NULL,
13587 NULL,
13588 NULL);
13589 if (NULL == peerstore)
13590 {
13591 GNUNET_break (0);
13593 return;
13594 }
13597 NULL); // FIXME we need to wait for
13598 // our first peer id before
13599 // we can start the service
13600 // completely - PILS in turn
13601 // waits for the first
13602 // addresses from the
13603 // communicators in order to
13604 // be able to generate a
13605 // peer id
13606 if (NULL == pils)
13607 {
13608 GNUNET_break (0);
13610 return;
13611 }
13612}
13613
13614
13620 "transport",
13622 &run,
13625 NULL,
13626 /* communication with applications */
13627 GNUNET_MQ_hd_fixed_size (suggest,
13630 NULL),
13631 GNUNET_MQ_hd_fixed_size (suggest_cancel,
13634 NULL),
13635 GNUNET_MQ_hd_var_size (request_hello_validation,
13638 NULL),
13639 /* communication with core */
13640 GNUNET_MQ_hd_fixed_size (client_start,
13642 struct StartMessage,
13643 NULL),
13644 GNUNET_MQ_hd_var_size (client_send,
13646 struct OutboundMessage,
13647 NULL),
13648 GNUNET_MQ_hd_fixed_size (client_recv_ok,
13650 struct RecvOkMessage,
13651 NULL),
13652 /* communication with communicators */
13653 GNUNET_MQ_hd_var_size (communicator_available,
13656 NULL),
13657 GNUNET_MQ_hd_var_size (communicator_backchannel,
13660 NULL),
13661 GNUNET_MQ_hd_var_size (add_address,
13664 NULL),
13665 GNUNET_MQ_hd_fixed_size (del_address,
13668 NULL),
13669 GNUNET_MQ_hd_var_size (incoming_msg,
13672 NULL),
13673 GNUNET_MQ_hd_fixed_size (queue_create_ok,
13676 NULL),
13677 GNUNET_MQ_hd_fixed_size (queue_create_fail,
13680 NULL),
13681 GNUNET_MQ_hd_var_size (add_queue_message,
13684 NULL),
13685 GNUNET_MQ_hd_fixed_size (update_queue_message,
13688 NULL),
13689 GNUNET_MQ_hd_fixed_size (del_queue_message,
13692 NULL),
13693 GNUNET_MQ_hd_fixed_size (send_message_ack,
13696 NULL),
13697 GNUNET_MQ_hd_fixed_size (burst_finished,
13700 NULL),
13701 /* communication with monitors */
13702 GNUNET_MQ_hd_fixed_size (monitor_start,
13705 NULL),
13707
13708
13709/* 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.
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
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 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 struct GNUNET_PeerIdentity my_identity
Identity of this peer.
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 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 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 const char * get_client_type_name(enum ClientType type)
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 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 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 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 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:465
void GNUNET_PILS_disconnect(struct GNUNET_PILS_Handle *handle)
Disconnect from the PILS service.
Definition pils_api.c:488
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:703
void GNUNET_PILS_cancel(struct GNUNET_PILS_Operation *op)
Cancel request.
Definition pils_api.c:623
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:528
const struct GNUNET_PeerIdentity * GNUNET_PILS_get_identity(const struct GNUNET_PILS_Handle *handle)
Return the current peer identity of a given handle.
Definition pils_api.c:727
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:568
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:669
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(uint64_t max)
Generate a random unsigned 64-bit value.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_aead_decrypt(size_t ct_len, const unsigned char ct[ct_len], size_t aad_len, const unsigned char aad[aad_len], const struct GNUNET_CRYPTO_AeadSecretKey *key, const struct GNUNET_CRYPTO_AeadNonce *nonce, const struct GNUNET_CRYPTO_AeadMac *mac, void *pt)
Decrypt the given data using XChaCha20-Poly1305.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_aead_encrypt(size_t pt_len, const unsigned char pt[pt_len], size_t aad_len, const unsigned char aad[aad_len], const struct GNUNET_CRYPTO_AeadSecretKey *key, const struct GNUNET_CRYPTO_AeadNonce *nonce, void *ct, struct GNUNET_CRYPTO_AeadMac *mac)
Encrypt the given data using XChaCha20-Poly1305.
void GNUNET_CRYPTO_random_block(void *buffer, size_t length)
Fill block with a random values.
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.
uint32_t GNUNET_CRYPTO_random_u32(uint32_t i)
Produce a random value.
#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:40
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:380
void GNUNET_HELLO_builder_free(struct GNUNET_HELLO_Builder *builder)
Release resources of a builder.
Definition hello-uri.c:398
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_new()
Allocate builder.
Definition hello-uri.c:344
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:992
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:361
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:1011
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:939
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:1366
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:968
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:354
#define GNUNET_HELLO_ADDRESS_EXPIRATION
For how long are HELLO signatures valid?
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_msg(const struct GNUNET_MessageHeader *msg, const struct GNUNET_PeerIdentity *pid)
Parse msg.
Definition hello-uri.c:416
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:660
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:1098
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:1178
#define GNUNET_is_zero(a)
Check that memory in a is all zeros.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
#define GNUNET_MAX(a, b)
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
GNUNET_SCHEDULER_Priority
Valid task priorities.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
#define GNUNET_MIN(a, b)
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
#define GNUNET_PACKED
gcc-ism to get packed structs.
@ GNUNET_SCHEDULER_PRIORITY_BACKGROUND
Run as background job (higher than idle, lower than default).
@ GNUNET_SCHEDULER_PRIORITY_DEFAULT
Run with the default priority (normal P2P operations).
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
const char * GNUNET_uuid2s(const struct GNUNET_Uuid *uuid)
Convert a UUID to a string (for printing debug messages).
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
const char * GNUNET_sh2s(const struct GNUNET_ShortHashCode *shc)
Convert a short hash value to a string (for printing debug messages).
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
const char * GNUNET_i2s2(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_EXTRA_LOGGING
define GNUNET_EXTRA_LOGGING if using this header outside the GNUnet source tree where gnunet_config....
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition mq.c:305
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_check_zero_termination(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
#define GNUNET_MQ_check_boxed_message(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
GNUNET_MQ_PriorityPreferences
Per envelope preferences and priorities.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
enum GNUNET_GenericReturnValue GNUNET_MQ_handle_message(const struct GNUNET_MQ_MessageHandler *handlers, const struct GNUNET_MessageHeader *mh)
Call the message message handler that was registered for the type of the given message in the given h...
Definition mq.c:205
void GNUNET_MQ_notify_sent(struct GNUNET_MQ_Envelope *ev, GNUNET_SCHEDULER_TaskCallback cb, void *cb_cls)
Call a callback once the envelope has been sent, that is, sending it can not be canceled anymore.
Definition mq.c:655
const struct GNUNET_MessageHeader * GNUNET_MQ_env_get_msg(const struct GNUNET_MQ_Envelope *env)
Obtain message contained in envelope.
Definition mq.c:896
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
@ GNUNET_MQ_PRIO_BACKGROUND
Lowest priority, i.e.
@ GNUNET_MQ_PREF_UNRELIABLE
Flag to indicate that unreliable delivery is acceptable.
@ GNUNET_MQ_PREF_LOW_LATENCY
Flag to indicate that low latency is important.
void GNUNET_is_burst_ready(struct GNUNET_TIME_Relative rtt_average, struct GNUNET_BurstSync *burst_sync, GNUNET_SCHEDULER_TaskCallback task, struct GNUNET_StartBurstCls *task_cls)
Checks if we are ready and starts burst when we and the other peer is ready.
Definition nat.c:89
struct GNUNET_NAT_Handle * GNUNET_NAT_register(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on...
Definition nat_api.c:366
void GNUNET_NAT_unregister(struct GNUNET_NAT_Handle *nh)
Stop port redirection and public IP address detection for the given handle.
Definition nat_api.c:703
void GNUNET_NAT_add_global_address(struct GNUNET_NAT_Handle *nh, char *addr, unsigned int address_length)
Add global address to the list of addresses and notify clients.
Definition nat_api.c:460
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
void GNUNET_PEERSTORE_monitor_stop(struct GNUNET_PEERSTORE_Monitor *zm)
Stop monitoring.
struct GNUNET_PEERSTORE_IterateContext * GNUNET_PEERSTORE_iteration_start(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_PEERSTORE_Processor callback, void *callback_cls)
Iterate over peerstore entries.
void GNUNET_PEERSTORE_iteration_next(struct GNUNET_PEERSTORE_IterateContext *ic, uint64_t limit)
Continue an iteration.
void GNUNET_PEERSTORE_store_cancel(struct GNUNET_PEERSTORE_StoreContext *sc)
Cancel a store request.
#define GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME
Key used to store sender's monotonic time from backchannel messages.
void GNUNET_PEERSTORE_disconnect(struct GNUNET_PEERSTORE_Handle *h)
Disconnect from the PEERSTORE service.
#define GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY
Key used for storing addresses in URL format in the peerstore.
struct GNUNET_PEERSTORE_Monitor * GNUNET_PEERSTORE_monitor_start(const struct GNUNET_CONFIGURATION_Handle *cfg, int iterate_first, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_SCHEDULER_TaskCallback sync_cb, void *sync_cb_cls, GNUNET_PEERSTORE_Processor callback, void *callback_cls)
Request watching a given key The monitoring can be filtered to contain only records matching peer and...
#define GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME
Key used to store sender's monotonic time from DV learn messages.
struct GNUNET_PEERSTORE_Handle * GNUNET_PEERSTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the PEERSTORE service.
void GNUNET_PEERSTORE_monitor_next(struct GNUNET_PEERSTORE_Monitor *zm, uint64_t limit)
Calls the monitor processor specified in GNUNET_PEERSTORE_monitor_start for the next record(s).
struct GNUNET_PEERSTORE_StoreContext * GNUNET_PEERSTORE_store(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, const void *value, size_t size, struct GNUNET_TIME_Absolute expiry, enum GNUNET_PEERSTORE_StoreOption options, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Store a new entry in the PEERSTORE.
#define GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY
Key used for storing HELLOs in the peerstore.
void GNUNET_PEERSTORE_iteration_stop(struct GNUNET_PEERSTORE_IterateContext *ic)
Cancel an iteration.
#define GNUNET_PEERSTORE_HELLO_KEY
Key used for storing HELLO in the peerstore.
struct GNUNET_PEERSTORE_StoreHelloContext * GNUNET_PEERSTORE_hello_add(struct GNUNET_PEERSTORE_Handle *h, const struct GNUNET_MessageHeader *msg, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Add hello to peerstore.
@ GNUNET_PEERSTORE_STOREOPTION_MULTIPLE
Possibly store multiple values under given key.
@ GNUNET_PEERSTORE_STOREOPTION_REPLACE
Delete any previous values for the given key before storing the given value.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE
P2P message: transport requests confirmation that an address works.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK
transport acknowledges processing an incoming message
#define GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT
Message from TRANSPORT notifying about a client that connected to us.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN
inform transport that a queue was torn down
#define GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION
Type of the 'struct RequestHelloValidationMessage' send by clients to TRANSPORT to trigger validation...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_START
Message from the core saying that the transport server should start giving it messages.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA
Message sent to indicate to a monitor about events.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR
Message sent to indicate to the transport which address prefix is supported by a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RECV_OK
Message telling transport to limit its receive rate.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT
Type of a fragment of a CORE message created by transport to adjust message length to a queue's MTU.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL
Response from communicator: address bogus, will not try to create queue.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX
Source-routed transport message based DV information gathered.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX
Wrapper around non-fragmented CORE message used to measure RTT and ensure reliability.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST_CANCEL
Type of the 'struct ExpressPreferenceMessage' send by clients to TRANSPORT to abandon bandwidth prefe...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RECV
Message from TRANSPORT notifying about a message that was received.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION
Message type used between transport services when they internally forward communicator backchannel me...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE
transport tells communicator it wants a queue
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN
Message sent for topology discovery at transport level.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_BURST_FINISHED
Burst message we send to another peer for hole punching.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL
Tell transport that it should assist with exchanging a message between communicators.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT
Message from TRANSPORT notifying about a client that disconnected from us.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG
inform transport about an incoming message
#define GNUNET_MESSAGE_TYPE_TRANSPORT_START_BURST
Burst message we send to another peer for hole punching.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK
Response from communicator: will try to create queue.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING
Transport signalling incoming backchannel message to a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK
communicator tells transports that message was sent
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS
inform transport to add an address of this peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START
Message sent to indicate to the transport that a monitor wants to observe certain events.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS
inform transport to delete an address of this peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE
P2P message: transport proves that an address worked.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL
Transport signalling incoming backchannel message to a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG
transport tells communicator it wants to transmit
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND
Request to TRANSPORT to transmit a message.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK
Confirmation from TRANSPORT that message for transmission has been queued (and that the next message ...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK
Confirmation for a GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP
inform transport that a queue was setup to talk to some peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST
Type of the 'struct ExpressPreferenceMessage' send by clients to TRANSPORT to establish bandwidth pre...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_UPDATE
inform transport that a queue was updated
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition scheduler.c: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:2528
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition service.c:2463
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition service.c:2434
@ 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:1629
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:610
#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:671
#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
static 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.
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 session keys
type for session 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:185
Context for parsing HELLOs.
Definition hello-uri.c:233
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_CRYPTO_AeadNonce iv
We use an IV here as the ephemeral_key is reused for EPHEMERAL_VALIDITY time to avoid re-signing it a...
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_CRYPTO_AeadMac mac
HMAC over the ciphertext of the encrypted, variable-size body that follows.
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 200 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 207 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 213 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 221 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 228 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 235 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 242 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 248 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 254 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 261 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 267 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 275 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 282 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 288 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 293 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 299 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 308 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 316 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 324 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 331 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 336 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 343 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 5077 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 1033 of file gnunet-service-transport.c.

1034{
1038 CT_NONE = 0,
1039
1043 CT_CORE = 1,
1044
1048 CT_MONITOR = 2,
1049
1053 CT_COMMUNICATOR = 3,
1054
1058 CT_APPLICATION = 4
1059};

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

1067{
1071 RMO_NONE = 0,
1072
1076 RMO_DV_ALLOWED = 1,
1077
1082
1087
1093 RMO_REDUNDANT = 4
1094};

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

2217{
2221 PMT_CORE = 0,
2222
2226 PMT_FRAGMENT_BOX = 1,
2227
2232
2236 PMT_DV_BOX = 3
2237};

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

3124{
3125 struct GNUNET_TIME_Absolute now;
3126
3127 now = GNUNET_TIME_absolute_get ();
3128 return now.abs_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us / 15;
3129}

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

3139{
3141 GNUNET_assert (ir_total > 0);
3142 ir_total--;
3143 if (NULL != ir->nc)
3145 ir->nc = NULL;
3146 GNUNET_free (ir);
3147}

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

3157{
3158 struct Queue *q = pa->queue;
3159 struct PendingMessage *pm = pa->pm;
3160 struct DistanceVectorHop *dvh = pa->dvh;
3161
3163 "free_pending_acknowledgement\n");
3164 if (NULL != q)
3165 {
3166 GNUNET_CONTAINER_MDLL_remove (queue, q->pa_head, q->pa_tail, pa);
3167 pa->queue = NULL;
3168 }
3169 if (NULL != pm)
3170 {
3172 "remove pa from message\n");
3174 "remove pa from message %" PRIu64 "\n",
3175 pm->logging_uuid);
3177 "remove pa from message %u\n",
3178 pm->pmt);
3180 "remove pa from message %s\n",
3182 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3183 pa->pm = NULL;
3184 }
3185 if (NULL != dvh)
3186 {
3187 GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
3188 pa->queue = NULL;
3189 }
3192 &pa->ack_uuid.value,
3193 pa));
3194 GNUNET_free (pa);
3195}

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

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

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

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

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

3327{
3328 struct VirtualLink *vl = rc->virtual_link;
3329
3333 rc->msg_uuid.uuid,
3334 rc));
3335 GNUNET_free (rc);
3336}

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

3346{
3347 struct VirtualLink *vl = cls;
3348 struct ReassemblyContext *rc;
3349
3350 vl->reassembly_timeout_task = NULL;
3351 while (NULL != (rc = GNUNET_CONTAINER_heap_peek (vl->reassembly_heap)))
3352 {
3354 .rel_value_us)
3355 {
3357 continue;
3358 }
3363 vl);
3364 return;
3365 }
3366}

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

3379{
3380 struct ReassemblyContext *rc = value;
3381
3382 (void) cls;
3383 (void) key;
3385 return GNUNET_OK;
3386}

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

3396{
3397 struct PendingMessage *pm;
3398 struct CoreSentContext *csc;
3399
3401 "free virtual link %p\n",
3402 vl);
3403
3404 if (NULL != vl->reassembly_map)
3405 {
3408 NULL);
3410 vl->reassembly_map = NULL;
3412 vl->reassembly_heap = NULL;
3413 }
3414 if (NULL != vl->reassembly_timeout_task)
3415 {
3418 }
3419 while (NULL != (pm = vl->pending_msg_head))
3423 if (NULL != vl->visibility_task)
3424 {
3426 vl->visibility_task = NULL;
3427 }
3428 if (NULL != vl->fc_retransmit_task)
3429 {
3431 vl->fc_retransmit_task = NULL;
3432 }
3433 while (NULL != (csc = vl->csc_head))
3434 {
3436 GNUNET_assert (vl == csc->vl);
3437 csc->vl = NULL;
3438 }
3439 GNUNET_break (NULL == vl->n);
3440 GNUNET_break (NULL == vl->dv);
3441 GNUNET_free (vl);
3442}

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

3452{
3453 if (NULL != vs->revalidation_task)
3454 {
3455 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
3456 vs->revalidation_task = NULL;
3457 }
3458 /*memcpy (&hkey,
3459 &hc,
3460 sizeof (hkey));*/
3462 "Remove key %s for address %s map size %u contains %u during freeing state\n",
3463 GNUNET_h2s (&vs->hc),
3464 vs->address,
3467 &vs->hc));
3470 GNUNET_YES ==
3473 vs->hn = NULL;
3474 if (NULL != vs->sc)
3475 {
3477 "store cancel\n");
3479 vs->sc = NULL;
3480 }
3481 GNUNET_free (vs->address);
3482 GNUNET_free (vs);
3483}

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

3494{
3496}

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

3507{
3509}

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

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

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

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

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

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

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

3615{
3616 struct DistanceVectorHop *dvh;
3617 struct VirtualLink *vl;
3618
3619 while (NULL != (dvh = dv->dv_head))
3621
3623 GNUNET_YES ==
3625 if (NULL != (vl = dv->vl))
3626 {
3627 GNUNET_assert (dv == vl->dv);
3628 vl->dv = NULL;
3629 if (NULL == vl->n)
3630 {
3632 free_virtual_link (vl);
3633 }
3634 else
3635 {
3638 }
3639 dv->vl = NULL;
3640 }
3641
3642 if (NULL != dv->timeout_task)
3643 {
3645 dv->timeout_task = NULL;
3646 }
3647 GNUNET_free (dv->km);
3648 GNUNET_free (dv);
3649}

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

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

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

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

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

3735{
3736 struct TransportClient *tc;
3737
3738 (void) cls;
3739 tc = GNUNET_new (struct TransportClient);
3740 tc->client = client;
3741 tc->mq = mq;
3744 "Client %p of type %u connected\n",
3745 tc,
3746 tc->type);
3747 return tc;
3748}

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

3755{
3756 struct TransportGlobalNattedAddress *tgna = value;
3757 (void) cls;
3758
3759 GNUNET_free (tgna);
3760
3761 return GNUNET_OK;
3762}

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

3774{
3775 struct DistanceVectorHop *dvh;
3776 struct VirtualLink *vl;
3777
3778 GNUNET_assert (NULL == neighbour->queue_head);
3781 &neighbour->pid,
3782 neighbour));
3784 "Freeing neighbour\n");
3787 NULL);
3789 while (NULL != (dvh = neighbour->dv_head))
3790 {
3791 struct DistanceVector *dv = dvh->dv;
3792
3794 if (NULL == dv->dv_head)
3795 free_dv_route (dv);
3796 }
3797 if (NULL != neighbour->get)
3798 {
3800 neighbour->get = NULL;
3801 }
3802 if (NULL != neighbour->sc)
3803 {
3805 "store cancel\n");
3806 GNUNET_PEERSTORE_store_cancel (neighbour->sc);
3807 neighbour->sc = NULL;
3808 }
3809 if (NULL != (vl = neighbour->vl))
3810 {
3811 GNUNET_assert (neighbour == vl->n);
3812 vl->n = NULL;
3813 if ((GNUNET_YES == drop_link) || (NULL == vl->dv))
3814 {
3817 }
3818 else
3819 {
3822 }
3823 neighbour->vl = NULL;
3824 }
3825 GNUNET_free (neighbour);
3826}

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

3838{
3839 struct GNUNET_MQ_Envelope *env;
3840 struct ConnectInfoMessage *cim;
3841
3842 GNUNET_assert (CT_CORE == tc->type);
3844 cim->id = *pid;
3845 GNUNET_MQ_send (tc->mq, env);
3846}

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

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

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

11297{
11298 struct Queue *queue = cls;
11299 struct Neighbour *n = queue->neighbour;
11301 struct PendingMessage *pm;
11302
11303 queue->transmit_task = NULL;
11304 if (NULL == n->vl)
11305 {
11307 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
11308 GNUNET_i2s (&n->pid),
11309 queue->address);
11310 queue->idle = GNUNET_YES;
11311 return;
11312 }
11313 memset (&sc, 0, sizeof(sc));
11314 select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
11315 if (NULL == sc.best)
11316 {
11317 /* Also look at DVH that have the n as first hop! */
11318 for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
11319 dvh = dvh->next_neighbour)
11320 {
11322 queue,
11323 dvh->dv->vl,
11324 dvh,
11325 sizeof(struct GNUNET_PeerIdentity)
11326 * (1 + dvh->distance)
11327 + sizeof(struct TransportDVBoxMessage)
11328 + sizeof(struct TransportDVBoxPayloadP));
11329 }
11330 }
11331 if (NULL == sc.best)
11332 {
11333 /* no message pending, nothing to do here! */
11335 "No pending messages, queue `%s' to %s now idle\n",
11336 queue->address,
11337 GNUNET_i2s (&n->pid));
11338 if (GNUNET_YES == sc.to_early)
11339 schedule_transmit_on_queue (sc.to_early_retry_delay,
11340 queue,
11342 queue->idle = GNUNET_YES;
11343 return;
11344 }
11345 /* There is a message pending, we are certainly not idle */
11346 queue->idle = GNUNET_NO;
11347
11348 /* Given selection in `sc`, do transmission */
11349 pm = sc.best;
11351 "Selected message <%" PRIu64 ">\n",
11352 pm->logging_uuid);
11353 if (NULL != sc.dvh)
11354 {
11356 "Is this %u a DV box?\n",
11357 pm->pmt);
11358 GNUNET_assert (PMT_DV_BOX != pm->pmt);
11359 if ((NULL != sc.best->bpm) && (sc.best->bpm->used_dvh != sc.dvh))
11360 {
11362 "Discard old box, because we have a new DV path.\n");
11363 free_pending_message (sc.best->bpm);
11364 sc.best->bpm = NULL;
11365 }
11366
11367 if (NULL == sc.best->bpm)
11368 {
11370 "encapsulate_for_dv 2\n");
11371 encapsulate_for_dv (sc.dvh->dv,
11372 1,
11373 &sc.dvh,
11374 (const struct GNUNET_MessageHeader *) &sc.best[1],
11376 &sc,
11377 RMO_NONE,
11378 GNUNET_NO);
11379 GNUNET_assert (NULL != sc.best->bpm);
11381 "%lu %lu %lu %lu %u\n",
11382 sizeof(struct GNUNET_PeerIdentity),
11383 sizeof(struct TransportDVBoxMessage),
11384 sizeof(struct TransportDVBoxPayloadP),
11385 sizeof(struct TransportFragmentBoxMessage),
11386 ((const struct GNUNET_MessageHeader *) &sc.best[1])->size);
11387 sc.best->bpm->used_dvh = sc.dvh;
11388 }
11389 pm = sc.best->bpm;
11390 }
11391 if (GNUNET_YES == sc.frag)
11392 {
11393 pm = fragment_message (queue, sc.dvh, pm);
11394 if (NULL == pm)
11395 {
11397 "Fragmentation failed queue %s to %s for <%" PRIu64
11398 ">, trying again\n",
11399 queue->address,
11400 GNUNET_i2s (&n->pid),
11401 sc.best->logging_uuid);
11403 queue,
11405 return;
11406 }
11407 }
11408 else if (GNUNET_YES == sc.relb)
11409 {
11411 if (NULL == pm)
11412 {
11413 /* Reliability boxing failed, try next message... */
11414 GNUNET_log (
11416 "Reliability boxing failed queue %s to %s for <%" PRIu64
11417 ">, trying again\n",
11418 queue->address,
11419 GNUNET_i2s (&n->pid),
11420 sc.best->logging_uuid);
11422 queue,
11424 return;
11425 }
11426 }
11427
11428 /* Pass 'pm' for transission to the communicator */
11429 GNUNET_log (
11431 "Passing message <%" PRIu64
11432 "> to queue %s for peer %s (considered %u others)\n",
11433 pm->logging_uuid,
11434 queue->address,
11435 GNUNET_i2s (&n->pid),
11436 sc.consideration_counter);
11437
11438 /* Flow control: increment amount of traffic sent; if we are routing
11439 via DV (and thus the ultimate target of the pending message is for
11440 a different virtual link than the one of the queue), then we need
11441 to use up not only the window of the direct link but also the
11442 flow control window for the DV link! */
11443 pm->vl->outbound_fc_window_size_used += pm->bytes_msg;
11444
11445 if (pm->vl != queue->neighbour->vl)
11446 {
11447 /* If the virtual link of the queue differs, this better be distance
11448 vector routing! */
11449 GNUNET_assert (NULL != sc.dvh);
11450 /* If we do distance vector routing, we better not do this for a
11451 message that was itself DV-routed */
11452 GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
11453 /* We use the size of the unboxed message here, to avoid counting
11454 the DV-Box header which is eaten up on the way by intermediaries */
11455 queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
11456 }
11457 else
11458 {
11459 GNUNET_assert (NULL == sc.dvh);
11460 }
11461
11462 queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
11463
11464 /* Check if this transmission somehow conclusively finished handing 'pm'
11465 even without any explicit ACKs */
11466 if ((PMT_CORE == pm->pmt) ||
11467 (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
11468 {
11470 }
11471 else
11472 {
11473 struct GNUNET_TIME_Relative wait_duration;
11474 unsigned int wait_multiplier;
11475
11476 if (PMT_FRAGMENT_BOX == pm->pmt)
11477 {
11478 struct PendingMessage *root;
11479
11480 root = pm->frag_parent;
11481 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11482 root = root->frag_parent;
11483
11484 wait_multiplier = (unsigned int) ceil ((double) root->bytes_msg
11485 / ((double) root->frag_off
11486 / (double) root->frag_count))
11487 * 4;
11488 }
11489 else
11490 {
11491 // No fragments, we use 4 RTT before retransmitting.
11492 wait_multiplier = 4;
11493 }
11494
11495 // Depending on how much pending message the VirtualLink is queueing, we wait longer.
11496 // wait_multiplier = wait_multiplier * pm->vl->pending_msg_num;
11497
11499 "Wait multiplier %u\n",
11500 wait_multiplier);
11501
11502 /* Message not finished, waiting for acknowledgement.
11503 Update time by which we might retransmit 's' based on queue
11504 characteristics (i.e. RTT); it takes one RTT for the message to
11505 arrive and the ACK to come back in the best case; but the other
11506 side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
11507 retransmitting.
11508
11509 OPTIMIZE: Note that in the future this heuristic should likely
11510 be improved further (measure RTT stability, consider message
11511 urgency and size when delaying ACKs, etc.) */
11512
11513 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
11514 queue->pd.aged_rtt.rel_value_us)
11515 wait_duration = queue->pd.aged_rtt;
11516 else
11517 {
11518 wait_duration = DEFAULT_ACK_WAIT_DURATION;
11519 wait_multiplier = 4;
11520 }
11521 {
11524 wait_duration, wait_multiplier));
11526 wait_duration, wait_multiplier);
11528 "Waiting %s for ACK until %s\n",
11533 GNUNET_TIME_relative_multiply (wait_duration,
11534 wait_multiplier))
11535 );
11536 }
11537 }
11538 /* finally, re-schedule queue transmission task itself */
11540 queue,
11542}

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

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

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

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

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

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

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

4138{
4139 struct TransportClient *tc = ale->tc;
4140
4141 GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
4142 tc->details.communicator.addr_tail,
4143 ale);
4144 if (NULL != ale->sc)
4145 {
4147 "store cancel\n");
4149 ale->sc = NULL;
4150 }
4151 if (NULL != ale->st)
4152 {
4154 ale->st = NULL;
4155 }
4156 if (NULL != ale->signed_address)
4158 GNUNET_free (ale);
4159}

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

4174{
4175 struct TransportClient *tc = cls;
4176 struct PeerRequest *pr = value;
4177
4178 if (NULL != pr->nc)
4180 pr->nc = NULL;
4182 GNUNET_YES ==
4183 GNUNET_CONTAINER_multipeermap_remove (tc->details.application.requests,
4184 pid,
4185 pr));
4186 GNUNET_free (pr);
4187
4188 return GNUNET_OK;
4189}

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

13283{
13284 struct LearnLaunchEntry *lle;
13285 struct PilsRequest *pr;
13286 (void) cls;
13287
13289 "shutdown logic\n");
13292 &free_neighbour_cb, NULL);
13293 if (NULL != validation_task)
13294 {
13296 validation_task = NULL;
13297 }
13298 if (NULL != dvlearn_task)
13299 {
13301 dvlearn_task = NULL;
13302 }
13303 if (NULL != burst_task)
13304 {
13306 burst_task = NULL;
13307 }
13308 if (NULL != burst_timeout_task)
13309 {
13311 burst_timeout_task = NULL;
13312 }
13315 dvlearn_map = NULL;
13318 dv_routes = NULL;
13319 if (NULL != GST_stats)
13320 {
13322 GST_stats = NULL;
13323 }
13324 if (NULL != GST_my_hello)
13325 {
13327 GST_my_hello = NULL;
13328 }
13331 NULL);
13333 ack_cummulators = NULL;
13336 NULL);
13338 pending_acks = NULL;
13341 neighbours = NULL;
13344 links = NULL;
13347 NULL);
13349 backtalkers = NULL;
13352 NULL);
13354 validation_map = NULL;
13356 validation_heap = NULL;
13358 revalidation_map = NULL;
13359 while (NULL != ir_head)
13361 GNUNET_assert (0 == ir_total);
13362 while (NULL != (lle = lle_head))
13363 {
13365 GNUNET_free (lle);
13366 }
13367 while (NULL != (pr = pils_requests_head))
13368 {
13371 pr);
13372 if (NULL != pr->op)
13373 GNUNET_PILS_cancel (pr->op);
13374 GNUNET_free (pr);
13375 }
13376 if (NULL != pils_feed_task)
13377 {
13379 pils_feed_task = NULL;
13380 }
13381 if (NULL != pils)
13382 {
13384 pils = NULL;
13385 }
13386 if (NULL != peerstore)
13387 {
13389 "Disconnecting from PEERSTORE service\n");
13391 peerstore = NULL;
13392 }
13394}

References ack_cummulators, backtalkers, burst_running, burst_task, burst_timeout_task, 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_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 4204 of file gnunet-service-transport.c.

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

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_INFO, 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 4296 of file gnunet-service-transport.c.

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

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

4328{
4329 struct VirtualLink *vl = value;
4330 struct CommunicatorMessageContext *cmc;
4331
4332 /* resume communicators */
4333 while (NULL != (cmc = vl->cmc_tail))
4334 {
4336 if (GNUNET_NO == cmc->continue_send)
4338 }
4339 return GNUNET_OK;
4340}

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

4353{
4354 // const struct GNUNET_PeerIdentity *my_identity;
4355 struct TransportClient *tc = cls;
4356 // uint32_t options;
4357 //
4358 // my_identity = GNUNET_PILS_get_identity (pils);
4359 // GNUNET_assert (my_identity);
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, 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] =
4507 GNUNET_CRYPTO_random_u64 (num_dv);
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_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 const struct GNUNET_PeerIdentity *my_identity;
4670 struct TransportClient *tc = cls;
4671 uint16_t size;
4672
4673 size = ntohs (cam->header.size) - sizeof(*cam);
4674 if (0 == size)
4675 {
4677 "Receive-only communicator connected\n");
4678 return; /* receive-only communicator */
4679 }
4680 tc->details.communicator.address_prefix =
4681 GNUNET_strdup ((const char *) &cam[1]);
4682 tc->details.communicator.cc = ntohl (cam->cc);
4683 tc->details.communicator.can_burst = ntohl (cam->can_burst);
4685 if (NULL != my_identity)
4686 {
4688 "Communicator for peer %s with prefix '%s' connected %s\n",
4690 tc->details.communicator.address_prefix,
4691 tc->details.communicator.can_burst ? "can burst" :
4692 "can not burst");
4693 }
4694 else
4695 {
4697 "Communicator for local peer with prefix '%s' connected %s\n",
4698 tc->details.communicator.address_prefix,
4699 tc->details.communicator.can_burst ? "can burst" :
4700 "can not burst");
4701 }
4703}

References GNUNET_TRANSPORT_CommunicatorAvailableMessage::can_burst, GNUNET_TRANSPORT_CommunicatorAvailableMessage::cc, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_PILS_get_identity(), GNUNET_SERVICE_client_continue(), GNUNET_strdup, GNUNET_TRANSPORT_CommunicatorAvailableMessage::header, my_identity, pils, 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 4714 of file gnunet-service-transport.c.

4717{
4718 const struct GNUNET_MessageHeader *inbox;
4719 const char *is;
4720 uint16_t msize;
4721 uint16_t isize;
4722
4723 (void) cls;
4724 msize = ntohs (cb->header.size) - sizeof(*cb);
4725 inbox = (const struct GNUNET_MessageHeader *) &cb[1];
4726 isize = ntohs (inbox->size);
4727 if (isize >= msize)
4728 {
4729 GNUNET_break (0);
4730 return GNUNET_SYSERR;
4731 }
4732 is = (const char *) inbox;
4733 is += isize;
4734 msize -= isize;
4735 GNUNET_assert (0 < msize);
4736 if ('\0' != is[msize - 1])
4737 {
4738 GNUNET_break (0);
4739 return GNUNET_SYSERR;
4740 }
4741 return GNUNET_OK;
4742}

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

4756{
4757 struct SignDvCls *sign_dv_cls = cls;
4758 struct DistanceVector *dv = sign_dv_cls->dv;
4759 struct PilsRequest *pr = sign_dv_cls->req;
4760
4761 pr->op = NULL;
4764 pr);
4765 GNUNET_free (pr);
4766
4767 dv->sender_sig = *sig;
4768}

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

4778{
4779 struct EphemeralConfirmationPS ec;
4780 struct SignDvCls *sign_dv_cls;
4781
4785 ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL);
4786 ec.target = dv->target;
4787 ec.ephemeral_key = dv->ephemeral_key;
4788 ec.sender_monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
4789 ec.purpose.size = htonl (sizeof(ec));
4790 sign_dv_cls = GNUNET_new (struct SignDvCls);
4791 sign_dv_cls->req = GNUNET_new (struct PilsRequest);
4792 sign_dv_cls->dv = dv;
4795 sign_dv_cls->req);
4797 &ec.purpose,
4798 sign_dv_cb,
4799 sign_dv_cls);
4800}

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

11587{
11588 struct PendingMessage *pm;
11589
11590 GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
11591 qe->queue->queue_tail,
11592 qe);
11593 qe->queue->queue_length--;
11594 tc->details.communicator.total_queue_length--;
11596 "Received ACK on queue %s (QID %u) to peer %s (new length: %u/%u)\n",
11597 qe->queue->address,
11598 qe->queue->qid,
11599 GNUNET_i2s (&qe->queue->neighbour->pid),
11600 qe->queue->queue_length,
11601 tc->details.communicator.total_queue_length);
11602
11603 /* if applicable, resume transmissions that waited on ACK */
11605 tc->details.communicator.total_queue_length)
11606 {
11607 /* Communicator dropped below threshold, resume all queues
11608 incident with this client! */
11610 GST_stats,
11611 "# Transmission throttled due to communicator queue limit",
11612 -1,
11613 GNUNET_NO);
11614 for (struct Queue *queue = tc->details.communicator.queue_head;
11615 NULL != queue;
11616 queue = queue->next_client)
11617 {
11619 queue,
11621 }
11622 }
11623 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
11624 {
11625 /* queue dropped below threshold; only resume this one queue */
11627 "# Transmission throttled due to queue queue limit",
11628 -1,
11629 GNUNET_NO);
11631 qe->queue,
11633 }
11634 else if (1 == qe->queue->q_capacity)
11635 {
11636 // TODO I guess this will never happen, because the communicator triggers this by updating its queue length itself.
11638 "Transmission rescheduled due to communicator message queue with qid %u has capacity %"
11639 PRIu64 ".\n",
11640 qe->queue->qid,
11641 qe->queue->q_capacity);
11642 /* message queue has capacity; only resume this one queue */
11643 /* queue dropped below threshold; only resume this one queue */
11645 "# Transmission throttled due to message queue capacity",
11646 -1,
11647 GNUNET_NO);
11649 qe->queue,
11651 }
11652
11653 if (NULL != (pm = qe->pm))
11654 {
11655 struct VirtualLink *vl;
11656
11657 // GNUNET_assert (qe == pm->qe);
11658 pm->qe = NULL;
11659 /* If waiting for this communicator may have blocked transmission
11660 of pm on other queues for this neighbour, force schedule
11661 transmit on queue for queues of the neighbour */
11662 if (NULL == pm->frag_parent)
11663 {
11664 vl = pm->vl;
11665 if ((NULL != vl) &&
11666 (NULL != vl->pending_msg_head) &&
11667 (vl->pending_msg_head == pm))
11669 }
11670 }
11671 GNUNET_free (qe);
11672}

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

4810{
4811 struct TransportClient *tc = cls;
4813
4815 "freeing timedout queue entries\n");
4816
4817 tc->details.communicator.free_queue_entry_task = NULL;
4818 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
4819 queue = queue->next_client)
4820 {
4821 struct QueueEntry *qep = queue->queue_head;
4822
4824 "checking QID %u for timedout queue entries\n",
4825 queue->qid);
4826 while (NULL != qep)
4827 {
4828 struct QueueEntry *pos = qep;
4830 pos->creation_timestamp, now);
4831 qep = qep->next;
4832
4834 "diff to now %s \n",
4837 {
4839 "Freeing timed out QueueEntry with MID %" PRIu64
4840 " and QID %u\n",
4841 pos->mid,
4842 queue->qid);
4843 free_queue_entry (pos, tc);
4844 }
4845 }
4846 }
4847}

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

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

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

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

References GNUNET_TIME_Absolute::abs_value_us, 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:

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

5105{
5106 const struct GNUNET_PeerIdentity *my_identity;
5107 struct TransportDVBoxMessage box_hdr;
5108 struct TransportDVBoxPayloadP *payload_hdr;
5109 uint16_t body_len_hbo = ntohs (hdr->size);
5110 unsigned char pt[sizeof(struct TransportDVBoxPayloadP) + body_len_hbo]
5112 unsigned char ct[sizeof(struct TransportDVBoxPayloadP) + body_len_hbo]
5114 struct GNUNET_TIME_Relative rtt;
5116
5117 payload_hdr = (struct TransportDVBoxPayloadP*) pt;
5120
5121 /* Encrypt payload */
5122 box_hdr.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX);
5123 box_hdr.total_hops = htons (0);
5124 box_hdr.without_fc = htons (without_fc);
5125 // update_ephemeral (dv);
5126 if (0 ==
5128 {
5130 &dv->ephemeral_key,
5131 (struct GNUNET_ShortHashCode*) &km);
5132 dv->km = GNUNET_new (struct GNUNET_ShortHashCode);
5133 GNUNET_memcpy (dv->km, &km, sizeof(struct GNUNET_ShortHashCode));
5134 sign_ephemeral (dv);
5135 }
5136 box_hdr.ephemeral_key = dv->ephemeral_key;
5137 payload_hdr->sender_sig = dv->sender_sig;
5138 memcpy (&payload_hdr[1], hdr, body_len_hbo);
5139 GNUNET_CRYPTO_random_block (&box_hdr.iv,
5140 sizeof(box_hdr.iv));
5141 payload_hdr->sender = *my_identity;
5143 GNUNET_CRYPTO_aead_encrypt (sizeof pt,
5144 pt,
5145 0,
5146 NULL,
5147 &km,
5148 &box_hdr.iv,
5149 ct,
5150 &box_hdr.mac);
5152 /* For each selected path, take the pre-computed header and body
5153 and add the path in the middle of the message; then send it. */
5154 for (unsigned int i = 0; i < num_dvhs; i++)
5155 {
5156 struct DistanceVectorHop *dvh = dvhs[i];
5157 unsigned int num_hops = dvh->distance + 1;
5158 char buf[sizeof(struct TransportDVBoxMessage)
5159 + sizeof(struct GNUNET_PeerIdentity) * num_hops
5160 + sizeof(struct TransportDVBoxPayloadP)
5161 + body_len_hbo] GNUNET_ALIGN;
5162 struct GNUNET_PeerIdentity *dhops;
5163
5164 box_hdr.header.size = htons (sizeof(buf));
5165 box_hdr.orig_size = htons (sizeof(buf));
5166 box_hdr.num_hops = htons (num_hops);
5167 memcpy (buf, &box_hdr, sizeof(box_hdr));
5168 dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
5169 memcpy (dhops,
5170 dvh->path,
5171 dvh->distance * sizeof(struct GNUNET_PeerIdentity));
5172 dhops[dvh->distance] = dv->target;
5173 if (GNUNET_EXTRA_LOGGING > 0)
5174 {
5175 char *path;
5176
5178 for (unsigned int j = 0; j < num_hops; j++)
5179 {
5180 char *tmp;
5181
5182 GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
5183 GNUNET_free (path);
5184 path = tmp;
5185 }
5187 "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
5188 ntohs (hdr->type),
5189 GNUNET_i2s (&dv->target),
5190 i + 1,
5191 num_dvhs,
5192 path);
5193 GNUNET_free (path);
5194 }
5195 rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
5196 memcpy (&dhops[num_hops], ct, sizeof(ct));
5197 use (use_cls,
5198 dvh->next_hop,
5199 (const struct GNUNET_MessageHeader *) buf,
5200 options);
5201 }
5202 return rtt;
5203}

References PerformanceData::aged_rtt, DistanceVectorHop::distance, TransportDVBoxMessage::ephemeral_key, GNUNET_ALIGN, GNUNET_asprintf(), GNUNET_assert, GNUNET_CRYPTO_aead_encrypt(), GNUNET_CRYPTO_eddsa_kem_encaps(), 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_PILS_get_identity(), GNUNET_strdup, GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_absolute_hton(), GNUNET_TIME_relative_min(), GNUNET_TIME_UNIT_FOREVER_REL, TransportDVBoxMessage::header, TransportDVBoxMessage::iv, TransportDVBoxMessage::mac, TransportDVBoxPayloadP::monotonic_time, my_identity, DistanceVectorHop::next_hop, TransportDVBoxMessage::num_hops, options, TransportDVBoxMessage::orig_size, DistanceVectorHop::path, DistanceVectorHop::pd, pils, 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 5216 of file gnunet-service-transport.c.

5220{
5221 (void) cls;
5222 (void) route_via_neighbour (next_hop, hdr, RMO_UNCONFIRMED_ALLOWED);
5223}

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

5242{
5243 // struct VirtualLink *vl;
5244 struct Neighbour *n;
5245 struct DistanceVector *dv;
5246 struct GNUNET_TIME_Relative rtt1;
5247 struct GNUNET_TIME_Relative rtt2;
5248 const struct GNUNET_PeerIdentity *target = &vl->target;
5249
5251 "Trying to route message of type %u to %s without fc\n",
5252 ntohs (hdr->type),
5253 GNUNET_i2s (target));
5254
5255 // TODO Do this elsewhere. vl should be given as parameter to method.
5256 // vl = lookup_virtual_link (target);
5257 GNUNET_assert (NULL != vl && GNUNET_YES == vl->confirmed);
5258 if (NULL == vl)
5260 n = vl->n;
5261 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
5262 if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
5263 {
5264 /* if confirmed is required, and we do not have anything
5265 confirmed, drop respective options */
5266 if (NULL == n)
5267 n = lookup_neighbour (target);
5268 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
5270 }
5271 if ((NULL == n) && (NULL == dv))
5272 {
5274 "Cannot route message of type %u to %s: no route\n",
5275 ntohs (hdr->type),
5276 GNUNET_i2s (target));
5278 "# Messages dropped in routing: no acceptable method",
5279 1,
5280 GNUNET_NO);
5282 }
5284 "Routing message of type %u to %s with options %X\n",
5285 ntohs (hdr->type),
5286 GNUNET_i2s (target),
5287 (unsigned int) options);
5288 /* If both dv and n are possible and we must choose:
5289 flip a coin for the choice between the two; for now 50/50 */
5290 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
5291 {
5292 if (0 == GNUNET_CRYPTO_random_u32 (2))
5293 n = NULL;
5294 else
5295 dv = NULL;
5296 }
5297 if ((NULL != n) && (NULL != dv))
5298 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
5299 enough for redundancy, so clear the flag. */
5302 if (NULL != n)
5303 {
5305 "Try to route message of type %u to %s without fc via neighbour\n",
5306 ntohs (hdr->type),
5307 GNUNET_i2s (target));
5308 rtt1 = route_via_neighbour (n, hdr, options);
5309 }
5310 if (NULL != dv)
5311 {
5312 struct DistanceVectorHop *hops[2];
5313 unsigned int res;
5314
5316 options,
5317 hops,
5318 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
5319 if (0 == res)
5320 {
5322 "Failed to route message, could not determine DV path\n");
5323 return rtt1;
5324 }
5326 "encapsulate_for_dv 1\n");
5327 rtt2 = encapsulate_for_dv (dv,
5328 res,
5329 hops,
5330 hdr,
5332 NULL,
5334 GNUNET_YES);
5335 }
5336 return GNUNET_TIME_relative_min (rtt1, rtt2);
5337}

References DistanceVectorHop::dv, dv_routes, encapsulate_for_dv(), GNUNET_assert, GNUNET_CONTAINER_multipeermap_get(), 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 5403 of file gnunet-service-transport.c.

5404{
5405 struct VirtualLink *vl = cls;
5406 struct GNUNET_TIME_Absolute monotime;
5407 struct TransportFlowControlMessage *fc;
5409 struct GNUNET_TIME_Relative rtt;
5410 struct GNUNET_TIME_Relative rtt_average;
5411 struct Neighbour *n = vl->n;
5412
5413 if (NULL != n && 0 < n->number_of_addresses)
5414 {
5415 size_t addresses_size =
5416 n->number_of_addresses * sizeof (struct TransportGlobalNattedAddress) + n
5417 ->size_of_global_addresses;
5418 char *tgnas = GNUNET_malloc (addresses_size);
5420 ctx.off = 0;
5421 ctx.tgnas = tgnas;
5422
5424 + addresses_size);
5425 fc->header.size = htons (sizeof(struct TransportFlowControlMessage)
5426 + addresses_size);
5427 fc->size_of_addresses = htonl (n->size_of_global_addresses);
5428 fc->number_of_addresses = htonl (n->number_of_addresses);
5431 &ctx);
5434 }
5435 else
5436 {
5437 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage));
5438 fc->header.size = htons (sizeof(struct TransportFlowControlMessage));
5439 }
5440
5442 /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
5443 it always! */
5444 /* For example, we should probably ONLY do this if a bit more than
5445 an RTT has passed, or if the window changed "significantly" since
5446 then. See vl->last_fc_rtt! NOTE: to do this properly, we also
5447 need an estimate for the bandwidth-delay-product for the entire
5448 VL, as that determines "significantly". We have the delay, but
5449 the bandwidth statistics need to be added for the VL!*/(void) duration;
5450
5451 if (NULL != vl->dv)
5452 rtt_average = calculate_rtt (vl->dv);
5453 else
5454 rtt_average = GNUNET_TIME_UNIT_FOREVER_REL;
5455 fc->rtt = GNUNET_TIME_relative_hton (rtt_average);
5457 "Sending FC seq %u to %s with new window %llu %lu %u\n",
5458 (unsigned int) vl->fc_seq_gen,
5459 GNUNET_i2s (&vl->target),
5460 (unsigned long long) vl->incoming_fc_window_size,
5461 (unsigned long) rtt_average.rel_value_us,
5462 vl->sync_ready);
5464 vl->last_fc_transmission = monotime;
5465 fc->sync_ready = vl->sync_ready;
5467 fc->seq = htonl (vl->fc_seq_gen++);
5468 fc->inbound_window_size = GNUNET_htonll (vl->incoming_fc_window_size
5471 fc->outbound_sent = GNUNET_htonll (vl->outbound_fc_window_size_used);
5472 fc->outbound_window_size = GNUNET_htonll (vl->outbound_fc_window_size);
5473 fc->sender_time = GNUNET_TIME_absolute_hton (monotime);
5475 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
5476 {
5479 "FC retransmission to %s failed, will retry in %s\n",
5480 GNUNET_i2s (&vl->target),
5483 }
5484 else
5485 {
5486 /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
5487 vl->last_fc_rtt = rtt;
5488 }
5489 if (NULL != vl->fc_retransmit_task)
5492 {
5494 vl->fc_retransmit_count = 0;
5495 }
5496 vl->fc_retransmit_task =
5498 vl->fc_retransmit_count++;
5499 GNUNET_free (fc);
5500}

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

5351{
5352 struct VirtualLink *vl = cls;
5353 vl->fc_retransmit_task = NULL;
5354 consider_sending_fc (cls);
5355}

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

12273{
12274 const char *colon;
12275 char *colon_rest;
12276 size_t colon_rest_length;
12277 char *address_without_port;
12278
12279 colon = strchr (address,':');
12280 colon_rest = GNUNET_strndup (address, colon - address);
12281 colon_rest_length = strlen (colon_rest);
12282 address_without_port = GNUNET_strndup (&colon_rest[4], colon_rest_length - 4);
12283 GNUNET_free (colon_rest);
12284
12285 return address_without_port;
12286}

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

5373{
5374 struct AddGlobalAddressesContext *ctx = cls;
5375 struct TransportGlobalNattedAddress *tgna = value;
5376 char *addr = (char *) &tgna[1];
5377
5379 "sending address %s length %u\n",
5380 addr,
5381 ntohl (tgna->address_length));
5382 GNUNET_memcpy (&(ctx->tgnas[ctx->off]), tgna, sizeof (struct
5384 + ntohl (tgna->address_length));
5385 ctx->off += sizeof(struct TransportGlobalNattedAddress) + ntohl (tgna->
5387
5388 return GNUNET_OK;
5389}

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

10090{
10092 unsigned int n_hops = 0;
10093
10095 "calculate_rtt\n");
10096 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
10097 pos = pos->next_dv)
10098 {
10100 "calculate_rtt %lu\n",
10101 (unsigned long) pos->pd.aged_rtt.rel_value_us);
10102 n_hops++;
10104 aged_rtt, pos
10105 ->distance
10106 + 2), ret);
10107 }
10108
10109 GNUNET_assert (0 != n_hops);
10110
10111 return ret;
10112}

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

5521{
5522 struct Neighbour *n = vl->n;
5523 struct DistanceVector *dv = vl->dv;
5524 struct GNUNET_TIME_Absolute now;
5525 struct VirtualLink *vl_next_hop;
5526 int elig;
5527
5529 "check_vl_transmission to target %s\n",
5530 GNUNET_i2s (&vl->target));
5531 /* Check that we have an eligible pending message!
5532 (cheaper than having #transmit_on_queue() find out!) */
5533 elig = GNUNET_NO;
5534 for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
5535 pm = pm->next_vl)
5536 {
5538 "check_vl_transmission loop\n");
5539 if (NULL != pm->qe)
5540 continue; /* not eligible, is in a queue! */
5541 if (pm->bytes_msg + vl->outbound_fc_window_size_used >
5543 {
5545 "Stalled message %" PRIu64
5546 " transmission on VL %s due to flow control: %llu < %llu\n",
5547 pm->logging_uuid,
5548 GNUNET_i2s (&vl->target),
5549 (unsigned long long) vl->outbound_fc_window_size,
5550 (unsigned long long) (pm->bytes_msg
5553 return; /* We have a message, but flow control says "nope" */
5554 }
5556 "Target window on VL %s not stalled. Scheduling transmission on queue\n",
5557 GNUNET_i2s (&vl->target));
5558 /* Notify queues at direct neighbours that we are interested */
5559 now = GNUNET_TIME_absolute_get ();
5560 if (NULL != n)
5561 {
5562 for (struct Queue *queue = n->queue_head; NULL != queue;
5563 queue = queue->next_neighbour)
5564 {
5565 if ((GNUNET_YES == queue->idle) &&
5566 (queue->validated_until.abs_value_us > now.abs_value_us))
5567 {
5569 "Direct neighbour %s not stalled\n",
5570 GNUNET_i2s (&n->pid));
5572 queue,
5574 elig = GNUNET_YES;
5575 }
5576 else
5578 "Neighbour Queue QID: %u (%u) busy or invalid\n",
5579 queue->qid,
5580 queue->idle);
5581 }
5582 }
5583 /* Notify queues via DV that we are interested */
5584 if (NULL != dv)
5585 {
5586 /* Do DV with lower scheduler priority, which effectively means that
5587 IF a neighbour exists and is available, we prefer it. */
5588 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5589 pos = pos->next_dv)
5590 {
5591 struct Neighbour *nh_iter = pos->next_hop;
5592
5593
5594 if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
5595 continue; /* skip this one: path not validated */
5596 else
5597 {
5598 vl_next_hop = lookup_virtual_link (&nh_iter->pid);
5599 GNUNET_assert (NULL != vl_next_hop);
5600 if (pm->bytes_msg + vl_next_hop->outbound_fc_window_size_used >
5601 vl_next_hop->outbound_fc_window_size)
5602 {
5604 "Stalled message %" PRIu64
5605 " transmission on next hop %s due to flow control: %llu < %llu\n",
5606 pm->logging_uuid,
5607 GNUNET_i2s (&vl_next_hop->target),
5608 (unsigned long
5609 long) vl_next_hop->outbound_fc_window_size,
5610 (unsigned long long) (pm->bytes_msg
5611 + vl_next_hop->
5612 outbound_fc_window_size_used));
5613 consider_sending_fc (vl_next_hop);
5614 continue; /* We have a message, but flow control says "nope" for the first hop of this path */
5615 }
5616 for (struct Queue *queue = nh_iter->queue_head; NULL != queue;
5617 queue = queue->next_neighbour)
5618 if ((GNUNET_YES == queue->idle) &&
5619 (queue->validated_until.abs_value_us > now.abs_value_us))
5620 {
5622 "Next hop neighbour %s not stalled\n",
5623 GNUNET_i2s (&nh_iter->pid));
5625 queue,
5627 elig = GNUNET_YES;
5628 }
5629 else
5631 "DV Queue QID: %u (%u) busy or invalid\n",
5632 queue->qid,
5633 queue->idle);
5634 }
5635 }
5636 }
5637 if (GNUNET_YES == elig)
5639 "Eligible message %" PRIu64 " of size %u to %s: %llu/%llu\n",
5640 pm->logging_uuid,
5641 pm->bytes_msg,
5642 GNUNET_i2s (&vl->target),
5643 (unsigned long long) vl->outbound_fc_window_size,
5644 (unsigned long long) (pm->bytes_msg
5646 break;
5647 }
5648}

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

5659{
5660 struct TransportClient *tc = cls;
5661 struct PendingMessage *pm;
5662 const struct GNUNET_MessageHeader *obmm;
5663 uint32_t bytes_msg;
5664 struct VirtualLink *vl;
5666
5667 GNUNET_assert (CT_CORE == tc->type);
5668 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
5669 bytes_msg = ntohs (obmm->size);
5670 pp = ntohl (obm->priority);
5671 vl = lookup_virtual_link (&obm->peer);
5672 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
5673 {
5675 "Don't have %s as a neighbour (anymore).\n",
5676 GNUNET_i2s (&obm->peer));
5677 /* Failure: don't have this peer as a neighbour (anymore).
5678 Might have gone down asynchronously, so this is NOT
5679 a protocol violation by CORE. Still count the event,
5680 as this should be rare. */
5683 "# messages dropped (neighbour unknown)",
5684 1,
5685 GNUNET_NO);
5686 return;
5687 }
5688
5689 pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
5691 "1 created pm %p storing vl %p\n",
5692 pm,
5693 vl);
5694 pm->logging_uuid = logging_uuid_gen++;
5695 pm->prefs = pp;
5696 pm->client = tc;
5697 pm->vl = vl;
5698 pm->bytes_msg = bytes_msg;
5699 memcpy (&pm[1], obmm, bytes_msg);
5701 "Sending message of type %u with %u bytes as <%" PRIu64
5702 "> to %s\n",
5703 ntohs (obmm->type),
5704 bytes_msg,
5705 pm->logging_uuid,
5706 GNUNET_i2s (&obm->peer));
5708 tc->details.core.pending_msg_head,
5709 tc->details.core.pending_msg_tail,
5710 pm);
5712 vl->pending_msg_head,
5713 vl->pending_msg_tail,
5714 pm);
5717}

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

5733{
5734 struct Neighbour *n;
5735 struct VirtualLink *vl;
5736 struct TransportClient *tc = cls;
5737 const struct GNUNET_MessageHeader *inbox =
5738 (const struct GNUNET_MessageHeader *) &cb[1];
5739 uint16_t isize = ntohs (inbox->size);
5740 const char *is = ((const char *) &cb[1]) + isize;
5741 size_t slen = strlen (is) + 1;
5742 char
5743 mbuf[slen + isize
5744 + sizeof(struct
5748
5749 /* 0-termination of 'is' was checked already in
5750 #check_communicator_backchannel() */
5752 "Preparing backchannel transmission to %s:%s of type %u and size %u\n",
5753 GNUNET_i2s (&cb->pid),
5754 is,
5755 ntohs (inbox->type),
5756 ntohs (inbox->size));
5757 /* encapsulate and encrypt message */
5758 be->header.type =
5760 be->header.size = htons (sizeof(mbuf));
5761 memcpy (&be[1], inbox, isize);
5762 memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
5763 + isize],
5764 is,
5765 strlen (is) + 1);
5766 // route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
5767 vl = lookup_virtual_link (&cb->pid);
5768 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
5769 {
5771 }
5772 else
5773 {
5774 /* Use route via neighbour */
5775 n = lookup_neighbour (&cb->pid);
5776 if (NULL != n)
5778 n,
5779 &be->header,
5780 RMO_NONE);
5781 }
5783}

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

5796{
5797 struct TransportClient *tc = cls;
5798
5799 if (CT_COMMUNICATOR != tc->type)
5800 {
5801 GNUNET_break (0);
5802 return GNUNET_SYSERR;
5803 }
5805 return GNUNET_OK;
5806}

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

6062{
6063 struct AddressListEntry *ale = cls;
6064 const char *dash;
6065 char *address_uri;
6066 char *prefix;
6067 unsigned int add_success;
6068
6069 if (NULL == GNUNET_PILS_get_identity (pils))
6070 {
6072 &store_pi,
6073 ale);
6074 return;
6075 }
6077 dash = strchr (ale->address, '-');
6078 GNUNET_assert (NULL != dash);
6079 dash++;
6080 GNUNET_asprintf (&address_uri,
6081 "%s://%s",
6082 prefix,
6083 dash);
6085 ale->st = NULL;
6087 "Storing our address `%s' in peerstore until %s!\n",
6088 ale->address,
6091 address_uri);
6092 if (GNUNET_OK != add_success)
6093 {
6095 "Storing our address `%s' %s\n",
6096 address_uri,
6097 GNUNET_NO == add_success ? "not done" : "failed");
6098 GNUNET_free (address_uri);
6099 return;
6100 }
6101 else
6102 {
6103
6105 "Storing our address `%s'\n",
6106 address_uri);
6107 }
6108 // FIXME hello_mono_time used here?? What about expiration in ale?
6109 pils_sign_address (ale,
6111 // TODO keep track of op and potentially cancel/clean
6112 GNUNET_free (address_uri);
6113}

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_PILS_get_identity(), GNUNET_SCHEDULER_add_delayed(), GNUNET_STRINGS_absolute_time_to_string(), GNUNET_TIME_UNIT_MILLISECONDS, GST_my_hello, hello_mono_time, pils, 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 5843 of file gnunet-service-transport.c.

5844{
5845 struct PilsAddressSignContext *pc = cls;
5846
5847 GNUNET_assert (NULL == pc->req);
5848 if (GNUNET_OK != success)
5849 {
5851 "Failed to store our address `%s' with peerstore\n",
5852 pc->ale->address);
5853 if (NULL == pc->ale->st)
5854 {
5856 &store_pi,
5857 pc->ale);
5858 }
5859 }
5860 GNUNET_free (pc);
5861}

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

5871{
5872 struct PilsAddressSignContext *pc = cls;
5873 struct GNUNET_MQ_Envelope *env;
5874 const struct GNUNET_MessageHeader *msg;
5875
5876 pc->req->op = NULL;
5879 pc->req);
5880 GNUNET_free (pc->req);
5881 pc->req = NULL;
5884 pid,
5885 sig,
5886 pc->et);
5889 "store_pi 1\n");
5891 msg,
5892 shc_cont,
5893 pc);
5894 GNUNET_free (env);
5895}

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

5906{
5907 struct PilsAddressSignContext *pc = cls;
5908
5909 pc->ale->sc = NULL;
5910 if (GNUNET_YES != success)
5912 "Failed to store our own address `%s' in peerstore!\n",
5913 pc->ale->address);
5914 else
5916 "Successfully stored our own address `%s' in peerstore!\n",
5917 pc->ale->address);
5918 /* refresh period is 1/4 of expiration time, that should be plenty
5919 without being excessive. */
5920 if (NULL == pc->ale->st)
5921 {
5922 pc->ale->st =
5924 GNUNET_TIME_relative_divide (pc->ale->expiration,
5925 4ULL),
5926 &store_pi,
5927 pc->ale);
5928 }
5929
5930 /* Now we have to update our HELLO! */
5932 pc->req = GNUNET_new (struct PilsRequest);
5935 pc->req);
5936 pc->req->op = GNUNET_PILS_sign_hello (pils,
5938 pc->et,
5940 pc);
5941}

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

5949{
5950 struct PilsAddressSignContext *pc = cls;
5951 char *sig_str;
5952 void *result;
5953 size_t result_size;
5954
5955 pc->req->op = NULL;
5958 pc->req);
5959 GNUNET_free (pc->req);
5960 sig_str = NULL;
5961 (void) GNUNET_STRINGS_base64_encode (sig, sizeof(*sig), &sig_str);
5962 result_size =
5963 1 + GNUNET_asprintf (
5964 (char **) &result,
5965 "%s;%llu;%u;%s",
5966 sig_str,
5967 (unsigned long long) pc->et.abs_value_us,
5968 (unsigned int) pc->ale->nt,
5969 pc->ale->address);
5970 GNUNET_free (sig_str);
5971
5973 "Build our HELLO URI `%s'\n",
5974 (char*) result);
5975
5976 pc->ale->signed_address = result;
5977 pc->ale->signed_address_len = result_size;
5979
5980 expiration = GNUNET_TIME_relative_to_absolute (pc->ale->expiration);
5982 "transport",
5983 pid,
5985 result,
5986 result_size,
5987 expiration,
5990 pc);
5991}

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(), pc, peerstore, peerstore_store_own_cb(), pid, 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 6030 of file gnunet-service-transport.c.

6033{
6034 struct SignedAddress sa;
6035 struct PilsAddressSignContext *pc;
6036
6037 sa.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS);
6038 sa.purpose.size = htonl (sizeof(sa));
6039 sa.mono_time = GNUNET_TIME_absolute_hton (mono_time);
6040 GNUNET_CRYPTO_hash (ale->address, strlen (ale->address), &sa.addr_hash);
6042 pc->ale = ale;
6043 pc->et = mono_time;
6044 pc->req = GNUNET_new (struct PilsRequest);
6046 &sa.purpose,
6048 pc);
6051 pc->req);
6052}

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

6123{
6124 struct AddressListEntry *ale;
6125 char *address_without_port;
6126
6127 ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
6128 ale->tc = tc;
6129 ale->address = (const char *) &ale[1];
6130 ale->expiration = expiration;
6131 ale->aid = aid;
6132 ale->nt = nt;
6133 memcpy (&ale[1], address, slen);
6134 address_without_port = get_address_without_port (ale->address);
6136 "Is this %s a local address (%s)\n",
6137 address_without_port,
6138 ale->address);
6139 if (0 != strcmp ("127.0.0.1", address_without_port))
6140 {
6141 if (NULL != ale->st)
6142 {
6144 }
6145 ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
6146 }
6147 GNUNET_free (address_without_port);
6148
6149 return ale;
6150}

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

6155{
6156
6158 "Feeding addresses to PILS\n");
6159 pils_feed_task = NULL;
6160
6162 GST_my_hello);
6163}

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

6175{
6176 struct TransportClient *tc = cls;
6177 struct AddressListEntry *ale;
6178 size_t slen;
6179 char *address;
6180
6181 /* 0-termination of &aam[1] was checked in #check_add_address */
6183 "Communicator added address `%s'!\n",
6184 (const char *) &aam[1]);
6185 slen = ntohs (aam->header.size) - sizeof(*aam);
6186 address = GNUNET_malloc (slen);
6187 memcpy (address, &aam[1], slen);
6188 ale = create_address_entry (tc,
6190 ntohl (aam->nt),
6191 address,
6192 aam->aid,
6193 slen);
6194 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
6195 tc->details.communicator.addr_tail,
6196 ale);
6197 {
6198 for (struct AddressListEntry *iter = tc->details.communicator.addr_head;
6199 (NULL != iter && NULL != iter->next);
6200 iter = iter->next)
6201 {
6202 char *address_uri;
6203 const char *dash = strchr (ale->address, '-');
6205 GNUNET_assert (NULL != dash);
6206 dash++;
6207 GNUNET_asprintf (&address_uri,
6208 "%s://%s",
6209 prefix,
6210 dash);
6213 GNUNET_free (address_uri);
6214 }
6215 if (NULL != pils_feed_task)
6219 NULL);
6220 }
6223}

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

6235{
6236 struct TransportClient *tc = cls;
6237 struct AddressListEntry *alen;
6238
6239 if (CT_COMMUNICATOR != tc->type)
6240 {
6241 GNUNET_break (0);
6243 return;
6244 }
6245 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
6246 NULL != ale;
6247 ale = alen)
6248 {
6249 alen = ale->next;
6250 if (dam->aid != ale->aid)
6251 continue;
6252 GNUNET_assert (ale->tc == tc);
6254 "Communicator deleted address `%s'!\n",
6255 ale->address);
6257 ale->address);
6258 if (NULL != pils_feed_task)
6262 NULL);
6265 return;
6266 }
6268 "Communicator removed address we did not even have.\n");
6270 // GNUNET_SERVICE_client_drop (tc->client);
6271}

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

10480{
10482 { GNUNET_MQ_hd_var_size (fragment_box,
10485 cmc),
10486 GNUNET_MQ_hd_var_size (reliability_box,
10489 cmc),
10490 GNUNET_MQ_hd_var_size (reliability_ack,
10493 cmc),
10494 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
10497 cmc),
10498 GNUNET_MQ_hd_var_size (dv_learn,
10501 cmc),
10502 GNUNET_MQ_hd_var_size (dv_box,
10504 struct TransportDVBoxMessage,
10505 cmc),
10506 GNUNET_MQ_hd_var_size (flow_control,
10509 cmc),
10511 validation_challenge,
10514 cmc),
10516 validation_response,
10519 cmc),
10521 int ret;
10522 const struct GNUNET_MessageHeader *msg = cmc->mh;
10523
10525 "Handling message of type %u with %u bytes\n",
10526 (unsigned int) ntohs (msg->type),
10527 (unsigned int) ntohs (msg->size));
10529 if (GNUNET_SYSERR == ret)
10530 {
10531 GNUNET_break (0);
10533 GNUNET_free (cmc);
10534 return;
10535 }
10536 if (GNUNET_NO == ret)
10537 {
10538 /* unencapsulated 'raw' message */
10539 handle_raw_message (cmc, msg);
10540 }
10541}

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

6294{
6295 struct CoreSentContext *ctx = cls;
6296 struct VirtualLink *vl = ctx->vl;
6297
6298 if (NULL == vl)
6299 {
6300 /* lost the link in the meantime, ignore */
6301 GNUNET_free (ctx);
6302 return;
6303 }
6306 vl->incoming_fc_window_size_ram -= ctx->size;
6307 vl->incoming_fc_window_size_used += ctx->isize;
6309 GNUNET_free (ctx);
6310}

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

6318{
6319 uint16_t size = ntohs (mh->size);
6320 int have_core;
6321
6322 if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
6323 {
6325 "# CORE messages dropped (FC arithmetic overflow)",
6326 1,
6327 GNUNET_NO);
6329 "CORE messages of type %u with %u bytes dropped (FC arithmetic overflow)\n",
6330 (unsigned int) ntohs (mh->type),
6331 (unsigned int) ntohs (mh->size));
6332 if (GNUNET_YES == free_cmc)
6334 return;
6335 }
6337 {
6339 "# CORE messages dropped (FC window overflow)",
6340 1,
6341 GNUNET_NO);
6343 "CORE messages of type %u with %u bytes dropped (FC window overflow)\n",
6344 (unsigned int) ntohs (mh->type),
6345 (unsigned int) ntohs (mh->size));
6346 if (GNUNET_YES == free_cmc)
6348 return;
6349 }
6350
6351 /* Forward to all CORE clients */
6352 have_core = GNUNET_NO;
6353 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
6354 {
6355 struct GNUNET_MQ_Envelope *env;
6356 struct InboundMessage *im;
6357 struct CoreSentContext *ctx;
6358
6359 if (CT_CORE != tc->type)
6360 continue;
6363 ctx = GNUNET_new (struct CoreSentContext);
6364 ctx->vl = vl;
6365 ctx->size = size;
6366 ctx->isize = (GNUNET_NO == have_core) ? size : 0;
6367 have_core = GNUNET_YES;
6370 im->peer = cmc->im.sender;
6371 memcpy (&im[1], mh, size);
6372 GNUNET_MQ_send (tc->mq, env);
6374 }
6375 if (GNUNET_NO == have_core)
6376 {
6378 "Dropped message to CORE: no CORE client connected!\n");
6379 /* Nevertheless, count window as used, as it is from the
6380 perspective of the other peer! */
6382 /* TODO-M1 */
6384 "Dropped message of type %u with %u bytes to CORE: no CORE client connected!\n",
6385 (unsigned int) ntohs (mh->type),
6386 (unsigned int) ntohs (mh->size));
6387 if (GNUNET_YES == free_cmc)
6389 return;
6390 }
6392 "Delivered message from %s of type %u to CORE recv window %d\n",
6393 GNUNET_i2s (&cmc->im.sender),
6394 ntohs (mh->type),
6396 if (vl->core_recv_window > 0)
6397 {
6398 if (GNUNET_YES == free_cmc)
6400 return;
6401 }
6402 /* Wait with calling #finish_cmc_handling(cmc) until the message
6403 was processed by CORE MQs (for CORE flow control)! */
6404 if (GNUNET_YES == free_cmc)
6406}

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

6419{
6420 struct CommunicatorMessageContext *cmc = cls;
6421 // struct CommunicatorMessageContext *cmc_copy =
6422 // GNUNET_new (struct CommunicatorMessageContext);
6423 struct GNUNET_MessageHeader *mh_copy;
6424 struct RingBufferEntry *rbe;
6425 struct VirtualLink *vl;
6426 uint16_t size = ntohs (mh->size);
6427
6429 "Handling raw message of type %u with %u bytes\n",
6430 (unsigned int) ntohs (mh->type),
6431 (unsigned int) ntohs (mh->size));
6432
6433 if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
6434 (size < sizeof(struct GNUNET_MessageHeader)))
6435 {
6436 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6437
6438 GNUNET_break (0);
6439 finish_cmc_handling (cmc);
6441 return;
6442 }
6443 vl = lookup_virtual_link (&cmc->im.sender);
6444 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6445 {
6446 /* FIXME: sender is giving us messages for CORE but we don't have
6447 the link up yet! I *suspect* this can happen right now (i.e.
6448 sender has verified us, but we didn't verify sender), but if
6449 we pass this on, CORE would be confused (link down, messages
6450 arrive). We should investigate more if this happens often,
6451 or in a persistent manner, and possibly do "something" about
6452 it. Thus logging as error for now. */
6453
6454 mh_copy = GNUNET_malloc (size);
6455 rbe = GNUNET_new (struct RingBufferEntry);
6456 rbe->cmc = cmc;
6457 /*cmc_copy->tc = cmc->tc;
6458 cmc_copy->im = cmc->im;*/
6459 GNUNET_memcpy (mh_copy, mh, size);
6460
6461 rbe->mh = mh_copy;
6462
6464 {
6465 struct RingBufferEntry *rbe_old = ring_buffer[ring_buffer_head];
6466 GNUNET_free (rbe_old->cmc);
6467 GNUNET_free (rbe_old->mh);
6468 GNUNET_free (rbe_old);
6469 }
6470 ring_buffer[ring_buffer_head] = rbe;// cmc_copy;
6471 // cmc_copy->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6472 cmc->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6474 "Storing message for %s and type %u (%u) in ring buffer head %u is full %u\n",
6475 GNUNET_i2s (&cmc->im.sender),
6476 (unsigned int) ntohs (mh->type),
6477 (unsigned int) ntohs (mh_copy->type),
6481 {
6482 ring_buffer_head = 0;
6484 }
6485 else
6487
6489 "%u items stored in ring buffer\n",
6492
6493 /*GNUNET_break_op (0);
6494 GNUNET_STATISTICS_update (GST_stats,
6495 "# CORE messages dropped (virtual link still down)",
6496 1,
6497 GNUNET_NO);
6498
6499 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6500 "CORE messages of type %u with %u bytes dropped (virtual link still down)\n",
6501 (unsigned int) ntohs (mh->type),
6502 (unsigned int) ntohs (mh->size));
6503 finish_cmc_handling (cmc);*/
6506 // GNUNET_free (cmc);
6507 return;
6508 }
6510}

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

6522{
6523 uint16_t size = ntohs (fb->header.size);
6524 uint16_t bsize = size - sizeof(*fb);
6525
6526 (void) cls;
6527 if (0 == bsize)
6528 {
6529 GNUNET_break_op (0);
6530 return GNUNET_SYSERR;
6531 }
6532 if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
6533 {
6534 GNUNET_break_op (0);
6535 return GNUNET_SYSERR;
6536 }
6537 if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
6538 {
6539 GNUNET_break_op (0);
6540 return GNUNET_SYSERR;
6541 }
6542 return GNUNET_YES;
6543}

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

6553{
6554 struct AcknowledgementCummulator *ac = cls;
6555
6556 ac->task = NULL;
6557 GNUNET_assert (0 == ac->num_acks);
6559 GNUNET_YES ==
6561 GNUNET_free (ac);
6562}

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

6572{
6573 struct Neighbour *n;
6574 struct VirtualLink *vl;
6575 struct AcknowledgementCummulator *ac = cls;
6576 char buf[sizeof(struct TransportReliabilityAckMessage)
6577 + ac->num_acks
6579 struct TransportReliabilityAckMessage *ack =
6580 (struct TransportReliabilityAckMessage *) buf;
6582
6583 ac->task = NULL;
6585 "Sending ACK with %u components to %s\n",
6586 ac->num_acks,
6587 GNUNET_i2s (&ac->target));
6588 GNUNET_assert (0 < ac->num_acks);
6590 ack->header.size =
6591 htons (sizeof(*ack)
6592 + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP));
6593 ack->ack_counter = htonl (ac->ack_counter += ac->num_acks);
6594 ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
6595 for (unsigned int i = 0; i < ac->num_acks; i++)
6596 {
6597 ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
6600 }
6601 /*route_control_message_without_fc (
6602 &ac->target,
6603 &ack->header,
6604 RMO_DV_ALLOWED);*/
6605 vl = lookup_virtual_link (&ac->target);
6606 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
6607 {
6609 vl,
6610 &ack->header,
6612 }
6613 else
6614 {
6615 /* Use route via neighbour */
6616 n = lookup_neighbour (&ac->target);
6617 if (NULL != n)
6619 n,
6620 &ack->header,
6621 RMO_NONE);
6622 }
6623 ac->num_acks = 0;
6626 ac);
6627}

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

6642{
6643 struct AcknowledgementCummulator *ac;
6644
6646 "Scheduling ACK %s for transmission to %s\n",
6647 GNUNET_uuid2s (&ack_uuid->value),
6648 GNUNET_i2s (pid));
6650 if (NULL == ac)
6651 {
6653 ac->target = *pid;
6654 ac->min_transmission_time = max_delay;
6658 &ac->target,
6659 ac,
6661 }
6662 else
6663 {
6664 if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
6665 {
6666 /* must run immediately, ack buffer full! */
6668 }
6672 }
6675 ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
6676 ac->num_acks++;
6679 ac);
6680}

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

6711{
6712 struct FindByMessageUuidContext *fc = cls;
6713 struct ReassemblyContext *rc = value;
6714
6715 (void) key;
6716 if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
6717 {
6718 fc->rc = rc;
6719 return GNUNET_NO;
6720 }
6721 return GNUNET_YES;
6722}

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

6734{
6735 struct CommunicatorMessageContext *cmc = cls;
6736 struct VirtualLink *vl;
6737 struct ReassemblyContext *rc;
6738 const struct GNUNET_MessageHeader *msg;
6739 uint16_t msize;
6740 uint16_t fsize;
6741 uint16_t frag_off;
6742 char *target;
6743 struct GNUNET_TIME_Relative cdelay;
6744 struct FindByMessageUuidContext fc;
6745
6746 vl = lookup_virtual_link (&cmc->im.sender);
6747 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6748 {
6749 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6750
6752 "No virtual link for %s to handle fragment\n",
6753 GNUNET_i2s (&cmc->im.sender));
6754 GNUNET_break (0);
6755 finish_cmc_handling (cmc);
6757 return;
6758 }
6759 if (NULL == vl->reassembly_map)
6760 {
6762 vl->reassembly_heap =
6767 vl);
6768 }
6769 msize = ntohs (fb->msg_size);
6770 fc.message_uuid = fb->msg_uuid;
6771 fc.rc = NULL;
6773 fb->msg_uuid.uuid,
6775 &fc);
6776 fsize = ntohs (fb->header.size) - sizeof(*fb);
6777 if (NULL == (rc = fc.rc))
6778 {
6779 rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */
6780 + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
6781 rc->msg_uuid = fb->msg_uuid;
6782 rc->virtual_link = vl;
6783 rc->msg_size = msize;
6784 rc->reassembly_timeout =
6788 rc,
6792 vl->reassembly_map,
6793 rc->msg_uuid.uuid,
6794 rc,
6796 target = (char *) &rc[1];
6797 rc->bitfield = (uint8_t *) (target + rc->msg_size);
6798 if (fsize != rc->msg_size)
6799 rc->msg_missing = rc->msg_size;
6800 else
6801 rc->msg_missing = 0;
6803 "Received fragment with size %u at offset %u/%u %u bytes missing from %s for NEW message %"
6804 PRIu64 "\n",
6805 fsize,
6806 ntohs (fb->frag_off),
6807 msize,
6808 rc->msg_missing,
6809 GNUNET_i2s (&cmc->im.sender),
6810 fb->msg_uuid.uuid);
6811 }
6812 else
6813 {
6814 target = (char *) &rc[1];
6816 "Received fragment at offset %u/%u from %s for message %u\n",
6817 ntohs (fb->frag_off),
6818 msize,
6819 GNUNET_i2s (&cmc->im.sender),
6820 (unsigned int) fb->msg_uuid.uuid);
6821 }
6822 if (msize != rc->msg_size)
6823 {
6824 GNUNET_break (0);
6825 finish_cmc_handling (cmc);
6826 return;
6827 }
6828
6829 /* reassemble */
6830 if (0 == fsize)
6831 {
6832 GNUNET_break (0);
6833 finish_cmc_handling (cmc);
6834 return;
6835 }
6836 frag_off = ntohs (fb->frag_off);
6837 if (frag_off + fsize > msize)
6838 {
6839 /* Fragment (plus fragment size) exceeds message size! */
6840 GNUNET_break_op (0);
6841 finish_cmc_handling (cmc);
6842 return;
6843 }
6844 memcpy (&target[frag_off], &fb[1], fsize);
6845 /* update bitfield and msg_missing */
6846 for (unsigned int i = frag_off; i < frag_off + fsize; i++)
6847 {
6848 if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
6849 {
6850 rc->bitfield[i / 8] |= (1 << (i % 8));
6851 rc->msg_missing--;
6852 }
6853 }
6854
6855 /* Compute cumulative ACK */
6857 cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
6858 if (0 == rc->msg_missing)
6859 cdelay = GNUNET_TIME_UNIT_ZERO;
6860 cummulative_ack (&cmc->im.sender,
6861 &fb->ack_uuid,
6864 /* is reassembly complete? */
6865 if (0 != rc->msg_missing)
6866 {
6867 finish_cmc_handling (cmc);
6868 return;
6869 }
6870 /* reassembly is complete, verify result */
6871 msg = (const struct GNUNET_MessageHeader *) &rc[1];
6872 if (ntohs (msg->size) != rc->msg_size)
6873 {
6874 GNUNET_break (0);
6876 finish_cmc_handling (cmc);
6877 return;
6878 }
6879 /* successful reassembly */
6881 "Fragment reassembly complete for message %u\n",
6882 (unsigned int) fb->msg_uuid.uuid);
6883 /* FIXME: check that the resulting msg is NOT a
6884 DV Box or Reliability Box, as that is NOT allowed! */
6885 cmc->mh = msg;
6887 /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
6888 en-route and we forget that we finished this reassembly immediately!
6889 -> keep around until timeout?
6890 -> shorten timeout based on ACK? */
6892}

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

6905{
6906 const struct GNUNET_MessageHeader *box = (const struct
6907 GNUNET_MessageHeader *) &rb[1];
6908 (void) cls;
6909
6911 "check_send_msg with size %u: inner msg type %u and size %u (%lu %lu)\n",
6912 ntohs (rb->header.size),
6913 ntohs (box->type),
6914 ntohs (box->size),
6915 sizeof (struct TransportReliabilityBoxMessage),
6916 sizeof (struct GNUNET_MessageHeader));
6918 return GNUNET_YES;
6919}

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

6932{
6933 struct CommunicatorMessageContext *cmc = cls;
6934 const struct GNUNET_MessageHeader *inbox =
6935 (const struct GNUNET_MessageHeader *) &rb[1];
6936 struct GNUNET_TIME_Relative rtt;
6937
6939 "Received reliability box from %s with UUID %s of type %u\n",
6940 GNUNET_i2s (&cmc->im.sender),
6942 (unsigned int) ntohs (inbox->type));
6943 rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
6944 do not really have an RTT for the
6945 * incoming* queue (should we have
6946 the sender add it to the rb message?) */
6948 &cmc->im.sender,
6949 &rb->ack_uuid,
6950 (0 == ntohl (rb->ack_countdown))
6953 GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
6954 /* continue with inner message */
6955 /* FIXME: check that inbox is NOT a DV Box, fragment or another
6956 reliability box (not allowed!) */
6957 cmc->mh = inbox;
6959}

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

6972{
6973 unsigned int sage;
6974
6975 if (age == pd->last_age)
6976 return; /* nothing to do */
6977 sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
6978 for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
6979 {
6980 struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
6981
6982 the->bytes_sent = 0;
6983 the->bytes_received = 0;
6984 }
6985 pd->last_age = age;
6986}

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

7001{
7002 uint64_t nval = rtt.rel_value_us;
7003 uint64_t oval = pd->aged_rtt.rel_value_us;
7004 unsigned int age = get_age ();
7005 struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
7006
7007 if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
7008 pd->aged_rtt = rtt;
7009 else
7010 pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
7011 update_pd_age (pd, age);
7012 the->bytes_received += bytes_transmitted_ok;
7013}

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

7027{
7028 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
7029}

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

7043{
7044 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
7045}

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

7057{
7058 struct PendingMessage *pos;
7059
7061 "Complete transmission of message %" PRIu64 " %u\n",
7062 pm->logging_uuid,
7063 pm->pmt);
7064 switch (pm->pmt)
7065 {
7066 case PMT_CORE:
7068 /* Full message sent, we are done */
7070 return;
7071
7072 case PMT_FRAGMENT_BOX:
7073 /* Fragment sent over reliable channel */
7074 pos = pm->frag_parent;
7078 "pos frag_off %lu pos bytes_msg %lu pmt %u parent %u\n",
7079 (unsigned long) pos->frag_off,
7080 (unsigned long) pos->bytes_msg,
7081 pos->pmt,
7082 NULL == pos->frag_parent ? 1 : 0);
7083 /* check if subtree is done */
7084 while ((NULL == pos->head_frag) && (pos->frag_off == (pos->bytes_msg
7085 - sizeof(struct
7087 &&
7088 (NULL != pos->frag_parent))
7089 {
7090 pm = pos;
7091 pos = pm->frag_parent;
7092 if ((NULL == pos) && (PMT_DV_BOX == pm->pmt))
7093 {
7095 return;
7096 }
7097 else if (PMT_DV_BOX == pm->pmt)
7098 {
7100 return;
7101 }
7104 }
7105
7106 /* Was this the last applicable fragment? */
7107 if ((NULL == pos->head_frag) && (NULL == pos->frag_parent || PMT_DV_BOX ==
7108 pos->pmt) &&
7109 (pos->frag_off == pos->bytes_msg))
7111 return;
7112
7113 case PMT_DV_BOX:
7115 "Completed transmission of message %" PRIu64 " (DV Box)\n",
7116 pm->logging_uuid);
7117 if (NULL != pm->frag_parent)
7118 {
7119 pos = pm->frag_parent;
7121 pos->bpm = NULL;
7123 }
7124 else
7126 return;
7127 }
7128}

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

7141{
7142 struct GNUNET_TIME_Relative delay;
7143
7145 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
7146 if (NULL != pa->queue && 1 == pa->num_send)
7148 if (NULL != pa->dvh && 1 == pa->num_send)
7149 update_dvh_performance (pa->dvh, delay, pa->message_size);
7150 if (NULL != pa->pm)
7153}

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

7166{
7167 unsigned int n_acks;
7168
7169 (void) cls;
7170 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7171 / sizeof(struct TransportCummulativeAckPayloadP);
7172 if (0 == n_acks)
7173 {
7174 GNUNET_break_op (0);
7175 return GNUNET_SYSERR;
7176 }
7177 if ((ntohs (ra->header.size) - sizeof(*ra)) !=
7178 n_acks * sizeof(struct TransportCummulativeAckPayloadP))
7179 {
7180 GNUNET_break_op (0);
7181 return GNUNET_SYSERR;
7182 }
7183 return GNUNET_OK;
7184}

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

7197{
7198 struct CommunicatorMessageContext *cmc = cls;
7199 const struct TransportCummulativeAckPayloadP *ack;
7200 unsigned int n_acks;
7201 uint32_t ack_counter;
7202
7203 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7204 / sizeof(struct TransportCummulativeAckPayloadP);
7205 ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
7206 for (unsigned int i = 0; i < n_acks; i++)
7207 {
7208 struct PendingAcknowledgement *pa =
7210 if (NULL == pa)
7211 {
7213 "Received ACK from %s with UUID %s which is unknown to us!\n",
7214 GNUNET_i2s (&cmc->im.sender),
7215 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7217 GST_stats,
7218 "# FRAGMENT_ACKS dropped, no matching pending message",
7219 1,
7220 GNUNET_NO);
7221 continue;
7222 }
7224 "Received ACK from %s with UUID %s\n",
7225 GNUNET_i2s (&cmc->im.sender),
7226 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7227 handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
7228 }
7229
7230 ack_counter = htonl (ra->ack_counter);
7231 (void) ack_counter; /* silence compiler warning for now */
7232 // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
7233 // (DV and/or Neighbour?)
7234 finish_cmc_handling (cmc);
7235}

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

7249{
7250 uint16_t size = ntohs (be->header.size) - sizeof(*be);
7251 const struct GNUNET_MessageHeader *inbox =
7252 (const struct GNUNET_MessageHeader *) &be[1];
7253 const char *is;
7254 uint16_t isize;
7255
7256 (void) cls;
7257 if (ntohs (inbox->size) >= size)
7258 {
7259 GNUNET_break_op (0);
7260 return GNUNET_SYSERR;
7261 }
7262 isize = ntohs (inbox->size);
7263 is = ((const char *) inbox) + isize;
7264 size -= isize;
7265 if ('\0' != is[size - 1])
7266 {
7267 GNUNET_break_op (0);
7268 return GNUNET_SYSERR;
7269 }
7270 return GNUNET_YES;
7271}

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

7286{
7287 const struct GNUNET_PeerIdentity *my_identity;
7288 struct CommunicatorMessageContext *cmc = cls;
7290 struct GNUNET_MQ_Envelope *env;
7291 struct TransportClient *tc;
7292 const struct GNUNET_MessageHeader *inbox =
7293 (const struct GNUNET_MessageHeader *) &be[1];
7294 uint16_t isize = ntohs (inbox->size);
7295 const char *target_communicator = ((const char *) inbox) + isize;
7296 char *sender;
7297 char *self;
7298
7301
7302 GNUNET_asprintf (&sender,
7303 "%s",
7304 GNUNET_i2s (&cmc->im.sender));
7305 GNUNET_asprintf (&self,
7306 "%s",
7308
7309 /* Find client providing this communicator */
7310 for (tc = clients_head; NULL != tc; tc = tc->next)
7311 if ((CT_COMMUNICATOR == tc->type) &&
7312 (0 ==
7313 strcmp (tc->details.communicator.address_prefix, target_communicator)))
7314 break;
7315 if (NULL == tc)
7316 {
7317 char *stastr;
7318
7320 &stastr,
7321 "# Backchannel message dropped: target communicator `%s' unknown",
7322 target_communicator);
7324 GNUNET_free (stastr);
7325 finish_cmc_handling (cmc);
7326 return;
7327 }
7328 /* Finally, deliver backchannel message to communicator */
7330 "Delivering backchannel message from %s to %s of type %u to %s\n",
7331 sender,
7332 self,
7333 ntohs (inbox->type),
7334 target_communicator);
7336 cbi,
7337 isize,
7339 cbi->pid = cmc->im.sender;
7340 memcpy (&cbi[1], inbox, isize);
7341 GNUNET_MQ_send (tc->mq, env);
7342 finish_cmc_handling (cmc);
7343}

References clients_head, CT_COMMUNICATOR, env, finish_cmc_handling(), GNUNET_asprintf(), GNUNET_assert, 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_PILS_get_identity(), GNUNET_STATISTICS_update(), GST_stats, CommunicatorMessageContext::im, my_identity, GNUNET_TRANSPORT_CommunicatorBackchannelIncoming::pid, pils, 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 7356 of file gnunet-service-transport.c.

7357{
7358 struct DistanceVector *dv = cls;
7359 struct DistanceVectorHop *pos;
7360
7361 dv->timeout_task = NULL;
7362 while (NULL != (pos = dv->dv_head))
7363 {
7364 GNUNET_assert (dv == pos->dv);
7366 break;
7368 }
7369 if (NULL == pos)
7370 {
7371 free_dv_route (dv);
7372 return;
7373 }
7374 dv->timeout_task =
7376}

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

7381{
7382
7383 const struct GNUNET_PeerIdentity target = vl->target;
7384
7385
7387 {
7388 struct RingBufferEntry *ring_buffer_copy[RING_BUFFER_SIZE];
7389 unsigned int tail = GNUNET_YES == is_ring_buffer_full ? ring_buffer_head :
7390 0;
7391 unsigned int head = GNUNET_YES == is_ring_buffer_full ? RING_BUFFER_SIZE :
7394 struct CommunicatorMessageContext *cmc;
7395 struct RingBufferEntry *rbe;
7396 struct GNUNET_MessageHeader *mh;
7397
7399 "Sending from ring buffer, which has %u items\n",
7400 head);
7401
7402 ring_buffer_head = 0;
7403 for (unsigned int i = 0; i < head; i++)
7404 {
7405 rbe = ring_buffer[(i + tail) % RING_BUFFER_SIZE];
7406 cmc = rbe->cmc;
7407 mh = rbe->mh;
7408
7409 im = cmc->im;
7410 // mh = cmc->mh;
7412 "Sending message of type %u to ring buffer target %s using vl target %s index %u\n",
7413 mh->type,
7414 GNUNET_i2s (&im.sender),
7415 GNUNET_i2s2 (&target),
7416 (i + tail) % RING_BUFFER_SIZE);
7417 if (0 == GNUNET_memcmp (&target, &im.sender))
7418 {
7420 "Finish handling message of type %u and size %u\n",
7421 (unsigned int) ntohs (mh->type),
7422 (unsigned int) ntohs (mh->size));
7424 GNUNET_free (mh);
7425 GNUNET_free (rbe->cmc);
7426 GNUNET_free (rbe);
7427 }
7428 else
7429 {
7430 ring_buffer_copy[ring_buffer_head] = rbe;
7432 }
7433 }
7434
7437 {
7439 }
7440
7441 for (unsigned int i = 0; i < ring_buffer_head; i++)
7442 {
7443 ring_buffer[i] = ring_buffer_copy[i];
7445 "ring_buffer_copy[i]->mh->type for i %u %u\n",
7446 i,
7447 ring_buffer_copy[i]->mh->type);
7449 "ring_buffer[i]->mh->type for i %u %u\n",
7450 i,
7451 ring_buffer[i]->mh->type);
7452 }
7453
7455 "%u items still in ring buffer\n",
7457 }
7458
7460 {
7461 struct PendingMessage *ring_buffer_dv_copy[RING_BUFFER_SIZE];
7462 struct PendingMessage *pm;
7463 unsigned int tail = GNUNET_YES == is_ring_buffer_dv_full ?
7465 0;
7466 unsigned int head = GNUNET_YES == is_ring_buffer_dv_full ?
7469
7471 "Sending from ring buffer dv, which has %u items\n",
7472 head);
7473
7475 for (unsigned int i = 0; i < head; i++)
7476 {
7477 pm = ring_buffer_dv[(i + tail) % RING_BUFFER_SIZE];
7478
7480 "Sending to ring buffer target %s using vl target %s\n",
7481 GNUNET_i2s (&pm->target),
7482 GNUNET_i2s2 (&target));
7483 if (0 == GNUNET_memcmp (&target, &pm->target))
7484 {
7486 "Adding PendingMessage to vl, checking transmission.\n");
7487 pm->vl = vl;
7491 pm);
7492
7494 }
7495 else
7496 {
7497 ring_buffer_dv_copy[ring_buffer_dv_head] = pm;
7499 }
7500 }
7501
7503 {
7505 }
7506
7507 for (unsigned int i = 0; i < ring_buffer_dv_head; i++)
7508 ring_buffer_dv[i] = ring_buffer_dv_copy[i];
7509
7511 "%u items still in ring buffer dv.\n",
7513
7514 }
7515}

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

7527{
7528 struct DistanceVector *dv = hop->dv;
7529 struct VirtualLink *vl;
7530
7531 vl = lookup_virtual_link (&dv->target);
7532 if (NULL == vl)
7533 {
7534
7535 vl = GNUNET_new (struct VirtualLink);
7537 "Creating new virtual link %p to %s using DV!\n",
7538 vl,
7539 GNUNET_i2s (&dv->target));
7540 vl->burst_addr = NULL;
7541 vl->confirmed = GNUNET_YES;
7542 vl->message_uuid_ctr =
7543 GNUNET_CRYPTO_random_u64 (UINT64_MAX);
7544 vl->target = dv->target;
7550 links,
7551 &vl->target,
7552 vl,
7554 vl->dv = dv;
7555 dv->vl = vl;
7556 vl->visibility_task =
7559 /* We lacked a confirmed connection to the target
7560 before, so tell CORE about it (finally!) */
7563 }
7564 else
7565 {
7566 /* Link was already up, remember dv is also now available and we are done */
7567 vl->dv = dv;
7568 dv->vl = vl;
7569 if (GNUNET_NO == vl->confirmed)
7570 {
7571 vl->confirmed = GNUNET_YES;
7572 vl->visibility_task =
7575 /* We lacked a confirmed connection to the target
7576 before, so tell CORE about it (finally!) */
7579 }
7580 else
7582 "Virtual link to %s could now also use DV!\n",
7583 GNUNET_i2s (&dv->target));
7584 }
7585}

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

7618{
7619 const struct GNUNET_PeerIdentity *my_identity;
7620 struct DistanceVectorHop *hop;
7621 struct DistanceVector *dv;
7622 struct Neighbour *next_hop;
7623 unsigned int shorter_distance;
7624
7625 if (path_len < 3)
7626 {
7627 /* what a boring path! not allowed! */
7628 GNUNET_break (0);
7629 return GNUNET_SYSERR;
7630 }
7631
7634
7635 GNUNET_assert (0 == GNUNET_memcmp (my_identity, &path[0]));
7636 next_hop = lookup_neighbour (&path[1]);
7637 if (NULL == next_hop)
7638 {
7639 /* next hop must be a neighbour, otherwise this whole thing is useless! */
7640 GNUNET_break (0);
7641 return GNUNET_SYSERR;
7642 }
7643 for (unsigned int i = 2; i < path_len; i++)
7644 {
7645 struct Neighbour *n = lookup_neighbour (&path[i]);
7646 struct GNUNET_TIME_Absolute q_timeout;
7647
7648 if (NULL != n)
7649 {
7650 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
7651 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
7652 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
7654 "remaining %lu to %s\n",
7655 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout)
7656 .rel_value_us,
7657 GNUNET_i2s (&n->pid));
7658 if (0 != GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
7659 {
7660 /* Useless path: we have a direct active connection to some hop
7661 in the middle of the path, so this one is not even
7662 terribly useful for redundancy */
7664 "Path of %u hops useless: directly link to hop %u (%s)\n",
7665 path_len,
7666 i,
7667 GNUNET_i2s (&path[i]));
7669 "# Useless DV path ignored: hop is neighbour",
7670 1,
7671 GNUNET_NO);
7672 return GNUNET_SYSERR;
7673 }
7674 }
7675 }
7676 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
7677 if (NULL == dv)
7678 {
7679 dv = GNUNET_new (struct DistanceVector);
7680 dv->target = path[path_len - 1];
7683 dv);
7686 dv_routes,
7687 &dv->target,
7688 dv,
7690 }
7691 /* Check if we have this path already! */
7692 shorter_distance = 0;
7693 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
7694 pos = pos->next_dv)
7695 {
7696 if (pos->distance < path_len - 3)
7697 shorter_distance++;
7698 /* Note that the distances in 'pos' excludes us (path[0]),
7699 the next_hop (path[1]) and the target so we need to subtract three
7700 and check next_hop explicitly */
7701 if ((pos->distance == path_len - 3) && (pos->next_hop == next_hop))
7702 {
7703 int match = GNUNET_YES;
7704
7705 for (unsigned int i = 0; i < pos->distance; i++)
7706 {
7707 if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
7708 {
7709 match = GNUNET_NO;
7710 break;
7711 }
7712 }
7713 if (GNUNET_YES == match)
7714 {
7715 struct GNUNET_TIME_Relative last_timeout;
7716
7717 /* Re-discovered known path, update timeout */
7719 "# Known DV path refreshed",
7720 1,
7721 GNUNET_NO);
7722 last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
7723 pos->timeout =
7725 pos->path_valid_until =
7726 GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
7727 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
7728 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
7729 if (0 <
7732 if (last_timeout.rel_value_us <
7735 .rel_value_us)
7736 {
7737 /* Some peer send DV learn messages too often, we are learning
7738 the same path faster than it would be useful; do not forward! */
7740 "Rediscovered path too quickly, not forwarding further\n")
7741 ;
7742 return GNUNET_NO;
7743 }
7745 "Refreshed known path to %s valid until %s, forwarding further\n",
7746 GNUNET_i2s (&dv->target),
7748 pos->path_valid_until));
7749 return GNUNET_YES;
7750 }
7751 }
7752 }
7753 /* Count how many shorter paths we have (incl. direct
7754 neighbours) before simply giving up on this one! */
7755 if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
7756 {
7757 /* We have a shorter path already! */
7759 "Have many shorter DV paths %s, not forwarding further\n",
7760 GNUNET_i2s (&dv->target));
7761 return GNUNET_NO;
7762 }
7763 /* create new DV path entry */
7765 "Discovered new DV path to %s valid until %s\n",
7766 GNUNET_i2s (&dv->target),
7767 GNUNET_STRINGS_absolute_time_to_string (path_valid_until));
7768 hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
7769 + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7770 hop->next_hop = next_hop;
7771 hop->dv = dv;
7772 hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
7773 memcpy (&hop[1],
7774 &path[2],
7775 sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7777 hop->path_valid_until = path_valid_until;
7778 hop->distance = path_len - 3;
7779 hop->pd.aged_rtt = network_latency;
7780 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
7782 next_hop->dv_head,
7783 next_hop->dv_tail,
7784 hop);
7785 if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
7787 return GNUNET_YES;
7788}

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_PILS_get_identity(), 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_stats, lookup_neighbour(), MAX_DV_PATHS_TO_TARGET, my_identity, DistanceVectorHop::next_hop, DistanceVectorHop::path, path_cleanup_cb(), DistanceVectorHop::path_valid_until, DistanceVectorHop::pd, Neighbour::pid, pils, 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 7799 of file gnunet-service-transport.c.

7800{
7801 const struct GNUNET_PeerIdentity *my_identity;
7802 uint16_t size = ntohs (dvl->header.size);
7803 uint16_t num_hops = ntohs (dvl->num_hops);
7804 const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
7805
7806 (void) cls;
7807 if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
7808 {
7809 GNUNET_break_op (0);
7810 return GNUNET_SYSERR;
7811 }
7812 if (num_hops > MAX_DV_HOPS_ALLOWED)
7813 {
7814 GNUNET_break_op (0);
7815 return GNUNET_SYSERR;
7816 }
7817
7820
7821 for (unsigned int i = 0; i < num_hops; i++)
7822 {
7823 if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
7824 {
7825 GNUNET_break_op (0);
7826 return GNUNET_SYSERR;
7827 }
7828 if (0 == GNUNET_memcmp (my_identity, &hops[i].hop))
7829 {
7830 GNUNET_break_op (0);
7831 return GNUNET_SYSERR;
7832 }
7833 }
7834 return GNUNET_YES;
7835}

References GNUNET_assert, GNUNET_break_op, GNUNET_memcmp, GNUNET_PILS_get_identity(), GNUNET_SYSERR, GNUNET_YES, TransportDVLearnMessage::header, DVPathEntryP::hop, TransportDVLearnMessage::initiator, MAX_DV_HOPS_ALLOWED, my_identity, TransportDVLearnMessage::num_hops, pils, GNUNET_MessageHeader::size, and size.

Here is the call graph for this function:

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

7852{
7853 struct SignDhpCls *sign_dhp_cls = cls;
7854 struct VirtualLink *vl;
7855 struct DVPathEntryP *dhops = sign_dhp_cls->dhops;
7856 uint16_t nhops = sign_dhp_cls->nhops;
7857 const struct GNUNET_PeerIdentity *next_hop = sign_dhp_cls->next_hop;
7858 struct TransportDVLearnMessage *fwd = sign_dhp_cls->fwd;
7859 struct Neighbour *n;
7860
7861 sign_dhp_cls->pr->op = NULL;
7864 sign_dhp_cls->pr);
7865 GNUNET_free (sign_dhp_cls->pr);
7866 dhops[nhops].hop_sig = *sig;
7867
7868 /*route_control_message_without_fc (next_hop,
7869 &fwd->header,
7870 RMO_UNCONFIRMED_ALLOWED);*/
7871 vl = lookup_virtual_link (next_hop);
7872 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
7873 {
7875 &fwd->header,
7877 }
7878 else
7879 {
7880 /* Use route via neighbour */
7881 n = lookup_neighbour (next_hop);
7882 if (NULL != n)
7884 n,
7885 &fwd->header,
7887 }
7888 GNUNET_free (sign_dhp_cls);
7889}

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

7910{
7911 struct DVPathEntryP *dhops;
7912 char buf[sizeof(struct TransportDVLearnMessage)
7913 + (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
7914 struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
7915 struct GNUNET_TIME_Relative nnd;
7916 const struct GNUNET_PeerIdentity *my_identity;
7917
7918 /* compute message for forwarding */
7920 "Forwarding DV learn message originating from %s to %s\n",
7921 GNUNET_i2s (&msg->initiator),
7922 GNUNET_i2s2 (next_hop));
7925 fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
7926 + (nhops + 1) * sizeof(struct DVPathEntryP));
7927 fwd->num_hops = htons (nhops + 1);
7928 fwd->bidirectional = htons (bi_history);
7931 msg->non_network_delay));
7933 fwd->init_sig = msg->init_sig;
7934 fwd->initiator = msg->initiator;
7935 fwd->challenge = msg->challenge;
7936 fwd->monotonic_time = msg->monotonic_time;
7937
7940
7941 dhops = (struct DVPathEntryP *) &fwd[1];
7942 GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
7943 dhops[nhops].hop = *my_identity;
7944 {
7945 struct DvHopPS dhp = {
7947 .purpose.size = htonl (sizeof(dhp)),
7948 .pred = (0 == nhops) ? msg->initiator : dhops[nhops - 1].hop,
7949 .succ = *next_hop,
7951 };
7952 struct SignDhpCls *sign_dhp_cls = GNUNET_new (struct SignDhpCls);
7953 sign_dhp_cls->dhops = dhops;
7954 sign_dhp_cls->nhops = nhops;
7955 sign_dhp_cls->next_hop = next_hop;
7956 sign_dhp_cls->fwd = fwd;
7957 sign_dhp_cls->pr = GNUNET_new (struct PilsRequest);
7960 sign_dhp_cls->pr);
7961 sign_dhp_cls->pr->op =
7963 &dhp.purpose,
7965 sign_dhp_cls);
7966 }
7967}

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_get_identity(), 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(), TransportDVLearnMessage::header, DVPathEntryP::hop, TransportDVLearnMessage::init_sig, TransportDVLearnMessage::initiator, MAX_DV_HOPS_ALLOWED, TransportDVLearnMessage::monotonic_time, msg, my_identity, 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 7980 of file gnunet-service-transport.c.

7985{
7986 struct DvInitPS ip = { .purpose.purpose = htonl (
7988 .purpose.size = htonl (sizeof(ip)),
7989 .monotonic_time = sender_monotonic_time,
7990 .challenge = *challenge };
7991
7992 if (
7993 GNUNET_OK !=
7995 &ip,
7996 init_sig,
7997 &init->public_key))
7998 {
7999 GNUNET_break_op (0);
8000 return GNUNET_SYSERR;
8001 }
8002 return GNUNET_OK;
8003}

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

8065{
8066 struct NeighbourSelectionContext *nsc = cls;
8067
8068 (void) value;
8069 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8070 return GNUNET_YES; /* skip initiator */
8071 for (unsigned int i = 0; i < nsc->nhops; i++)
8072 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8073 return GNUNET_YES;
8074 /* skip peers on path */
8075 nsc->num_eligible++;
8076 return GNUNET_YES;
8077}

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

8094{
8095 struct NeighbourSelectionContext *nsc = cls;
8096
8098 "transmission %s\n",
8099 GNUNET_i2s (pid));
8100 (void) value;
8101 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8102 return GNUNET_YES; /* skip initiator */
8103 for (unsigned int i = 0; i < nsc->nhops; i++)
8104 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8105 return GNUNET_YES;
8106 /* skip peers on path */
8107 for (unsigned int i = 0; i < nsc->num_selections; i++)
8108 {
8109 if (nsc->selections[i] == nsc->num_eligible)
8110 {
8112 nsc->dvl,
8113 nsc->bi_history,
8114 nsc->nhops,
8115 nsc->hops,
8116 nsc->in_time);
8117 break;
8118 }
8119 }
8120 nsc->num_eligible++;
8121 return GNUNET_YES;
8122}

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

8172{
8173 double target_total = 50.0; /* FIXME: use LOG(NSE)? */
8174 double eligible_ratio =
8175 ((double) eligible_count) / ((double) neighbour_count);
8176 double boost_factor = eligible_ratio * eligible_ratio;
8177 unsigned int rnd;
8178 double left;
8179
8180 if (hops_taken >= 64)
8181 {
8182 GNUNET_break (0);
8183 return 0; /* precaution given bitshift below */
8184 }
8185 for (unsigned int i = 1; i < hops_taken; i++)
8186 {
8187 /* For each hop, subtract the expected number of targets
8188 reached at distance d (so what remains divided by 2^d) */
8189 target_total -= (target_total * boost_factor / (1LLU << i));
8190 }
8191 rnd =
8192 (unsigned int) floor (target_total * boost_factor / (1LLU << hops_taken));
8193 /* round up or down probabilistically depending on how close we were
8194 when floor()ing to rnd */
8195 left = target_total - (double) rnd;
8196 if (UINT32_MAX * left >
8197 GNUNET_CRYPTO_random_u64 (UINT32_MAX))
8198 rnd++; /* round up */
8200 "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
8201 hops_taken,
8202 rnd,
8203 eligible_count,
8204 neighbour_count);
8205 return rnd;
8206}

References GNUNET_break, 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 8216 of file gnunet-service-transport.c.

8217{
8218 struct Neighbour *n = cls;
8219
8220 n->sc = NULL;
8221 if (GNUNET_YES != success)
8223 "Failed to store other peer's monotonic time in peerstore!\n");
8224}

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

8229{
8230 struct GNUNET_TIME_Relative host_latency_sum;
8231 struct GNUNET_TIME_Relative latency;
8232 struct GNUNET_TIME_Relative network_latency;
8233 uint16_t nhops = ntohs (dvl->num_hops);;
8234
8235 /* We initiated this, learn the forward path! */
8236 host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
8237
8238 // Need also something to lookup initiation time
8239 // to compute RTT! -> add RTT argument here?
8241 dvl->monotonic_time));
8242 GNUNET_assert (latency.rel_value_us >= host_latency_sum.rel_value_us);
8243 // latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
8244 // (based on dvl->challenge, we can identify time of origin!)
8245
8246 network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
8247 /* assumption: latency on all links is the same */
8248 network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
8249
8250 return network_latency;
8251}

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

8263{
8264 struct CommunicatorMessageContext *cmc = cls;
8266 int bi_hop;
8267 uint16_t nhops;
8268 uint16_t bi_history;
8269 const struct DVPathEntryP *hops;
8270 int do_fwd;
8271 int did_initiator;
8272 struct GNUNET_TIME_Absolute in_time;
8273 struct Neighbour *n;
8274 const struct GNUNET_PeerIdentity *my_identity;
8275
8276 nhops = ntohs (dvl->num_hops); /* 0 = sender is initiator */
8277 bi_history = ntohs (dvl->bidirectional);
8278 hops = (const struct DVPathEntryP *) &dvl[1];
8279 if (0 == nhops)
8280 {
8281 /* sanity check */
8282 if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
8283 {
8284 GNUNET_break (0);
8285 finish_cmc_handling (cmc);
8286 return;
8287 }
8288 }
8289 else
8290 {
8292 "handle dv learn message last hop %s\n",
8293 GNUNET_i2s (&hops[nhops - 1].hop));
8294 /* sanity check */
8295 if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
8296 {
8297 GNUNET_break (0);
8298 finish_cmc_handling (cmc);
8299 return;
8300 }
8301 }
8302
8304 cc = cmc->tc->details.communicator.cc;
8305 bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
8306 cc); // FIXME: add bi-directional flag to cc?
8307 in_time = GNUNET_TIME_absolute_get ();
8308
8309 /* continue communicator here, everything else can happen asynchronous! */
8310 finish_cmc_handling (cmc);
8311
8312 n = lookup_neighbour (&dvl->initiator);
8313 if (NULL != n)
8314 {
8315 if ((n->dv_monotime_available == GNUNET_YES) &&
8318 {
8320 "DV learn from %s discarded due to time travel",
8321 GNUNET_i2s (&dvl->initiator));
8323 "# DV learn discarded due to time travel",
8324 1,
8325 GNUNET_NO);
8326 return;
8327 }
8329 &dvl->initiator,
8330 &dvl->challenge,
8331 &dvl->init_sig))
8332 {
8334 "DV learn signature from %s invalid\n",
8335 GNUNET_i2s (&dvl->initiator));
8336 GNUNET_break_op (0);
8337 return;
8338 }
8341 {
8342 if (NULL != n->sc)
8343 {
8345 "store cancel\n");
8347 }
8348 n->sc =
8350 "transport",
8351 &dvl->initiator,
8353 &dvl->monotonic_time,
8354 sizeof(dvl->monotonic_time),
8358 n);
8359 }
8360 }
8361
8364
8365 /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
8366 If signature verification load too high, implement random drop strategy */
8367 for (unsigned int i = 0; i < nhops; i++)
8368 {
8369 struct DvHopPS dhp = { .purpose.purpose =
8371 .purpose.size = htonl (sizeof(dhp)),
8372 .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
8373 .succ = (nhops == i + 1) ? *my_identity
8374 : hops[i + 1].hop,
8375 .challenge = dvl->challenge };
8376
8377 if (GNUNET_OK !=
8379 &dhp,
8380 &hops[i].hop_sig,
8381 &hops[i].hop.public_key))
8382 {
8384 "DV learn from %s signature of hop %u invalid\n",
8385 GNUNET_i2s (&dvl->initiator),
8386 i);
8388 "signature of hop %s invalid\n",
8389 GNUNET_i2s (&hops[i].hop));
8391 "pred %s\n",
8392 GNUNET_i2s (&dhp.pred));
8394 "succ %s\n",
8395 GNUNET_i2s (&dhp.succ));
8397 "hash %s\n",
8398 GNUNET_sh2s (&dhp.challenge.value));
8399 GNUNET_break_op (0);
8400 return;
8401 }
8402 }
8403 if (GNUNET_EXTRA_LOGGING > 0)
8404 {
8405 char *path;
8406
8407 path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
8408 for (unsigned int i = 0; i < nhops; i++)
8409 {
8410 char *tmp;
8411
8412 GNUNET_asprintf (&tmp,
8413 "%s%s%s",
8414 path,
8415 (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
8416 GNUNET_i2s (&hops[i].hop));
8417 GNUNET_free (path);
8418 path = tmp;
8419 }
8421 "Received DVInit via %s%s%s\n",
8422 path,
8423 bi_hop ? "<->" : "-->",
8425 GNUNET_free (path);
8426 }
8427 do_fwd = GNUNET_YES;
8428 if (0 == GNUNET_memcmp (my_identity, &dvl->initiator))
8429 {
8430 struct GNUNET_PeerIdentity path[nhops + 1];
8431 struct GNUNET_TIME_Relative network_latency;
8432
8433 /* We initiated this, learn the forward path! */
8434 path[0] = *my_identity;
8435 path[1] = hops[0].hop;
8436
8437 network_latency = get_network_latency (dvl);
8438
8439 for (unsigned int i = 2; i <= nhops; i++)
8440 {
8441 struct GNUNET_TIME_Relative ilat;
8442
8443 /* assumption: linear latency increase per hop */
8444 ilat = GNUNET_TIME_relative_multiply (network_latency, i);
8445 path[i] = hops[i - 1].hop;
8447 "Learned path with %u hops to %s with latency %s\n",
8448 i,
8449 GNUNET_i2s (&path[i]),
8451 learn_dv_path (path,
8452 i + 1,
8453 ilat,
8456 }
8457 /* as we initiated, do not forward again (would be circular!) */
8458 do_fwd = GNUNET_NO;
8459 return;
8460 }
8461 if (bi_hop)
8462 {
8463 /* last hop was bi-directional, we could learn something here! */
8464 struct GNUNET_PeerIdentity path[nhops + 2];
8465 struct GNUNET_TIME_Relative ilat;
8466 struct GNUNET_TIME_Relative network_latency;
8467
8468 path[0] = *my_identity;
8469 path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
8470 for (unsigned int i = 0; i < nhops; i++)
8471 {
8472 int iret;
8473
8474 if (0 == (bi_history & (1 << i)))
8475 break; /* i-th hop not bi-directional, stop learning! */
8476 if (i == nhops - 1)
8477 {
8478 path[i + 2] = dvl->initiator;
8479 }
8480 else
8481 {
8482 path[i + 2] = hops[nhops - i - 2].hop;
8483 }
8484
8486 "Learned inverse path with %u hops to %s\n",
8487 i + 2,
8488 GNUNET_i2s (&path[i + 2]));
8489 network_latency = get_network_latency (dvl);
8490 ilat = GNUNET_TIME_relative_multiply (network_latency, i + 2);
8491 iret = learn_dv_path (path,
8492 i + 3,
8493 ilat,
8496 if (GNUNET_SYSERR == iret)
8497 {
8498 /* path invalid or too long to be interesting for US, thus should also
8499 not be interesting to our neighbours, cut path when forwarding to
8500 'i' hops, except of course for the one that goes back to the
8501 initiator */
8503 "# DV learn not forwarded due invalidity of path",
8504 1,
8505 GNUNET_NO);
8506 do_fwd = GNUNET_NO;
8507 break;
8508 }
8509 if ((GNUNET_NO == iret) && (nhops == i + 1))
8510 {
8511 /* we have better paths, and this is the longest target,
8512 so there cannot be anything interesting later */
8514 "# DV learn not forwarded, got better paths",
8515 1,
8516 GNUNET_NO);
8517 do_fwd = GNUNET_NO;
8518 break;
8519 }
8520 }
8521 }
8522 if (MAX_DV_HOPS_ALLOWED == nhops)
8523 {
8524 /* At limit, we're out of here! */
8525 return;
8526 }
8527
8528 /* Forward to initiator, if path non-trivial and possible */
8529 bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
8530 did_initiator = GNUNET_NO;
8531 if ((1 <= nhops) &&
8532 (GNUNET_YES ==
8534 {
8535 /* send back to origin! */
8537 "Sending DVL back to initiator %s\n",
8538 GNUNET_i2s (&dvl->initiator));
8539 forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
8540 did_initiator = GNUNET_YES;
8541 }
8542 /* We forward under two conditions: either we still learned something
8543 ourselves (do_fwd), or the path was darn short and thus the initiator is
8544 likely to still be very interested in this (and we did NOT already
8545 send it back to the initiator) */
8546 if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
8547 (GNUNET_NO == did_initiator)))
8548 {
8549 /* Pick random neighbours that are not yet on the path */
8550 struct NeighbourSelectionContext nsc;
8551 unsigned int n_cnt;
8552
8554 nsc.nhops = nhops;
8555 nsc.dvl = dvl;
8556 nsc.bi_history = bi_history;
8557 nsc.hops = hops;
8558 nsc.in_time = in_time;
8559 nsc.num_eligible = 0;
8562 &nsc);
8563 if (0 == nsc.num_eligible)
8564 return; /* done here, cannot forward to anyone else */
8565 nsc.num_selections = calculate_fork_degree (nhops, n_cnt, nsc.num_eligible);
8566 nsc.num_selections =
8567 GNUNET_MIN (MAX_DV_DISCOVERY_SELECTION, nsc.num_selections);
8569 "Forwarding DVL to %u other peers\n",
8570 nsc.num_selections);
8571 for (unsigned int i = 0; i < nsc.num_selections; i++)
8572 nsc.selections[i] =
8573 (nsc.num_selections == n_cnt)
8574 ? i /* all were selected, avoid collisions by chance */
8575 : GNUNET_CRYPTO_random_u32 (n_cnt);
8576 nsc.num_eligible = 0;
8579 &nsc);
8580 }
8581}

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_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_PILS_get_identity(), 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_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, my_identity, neighbour_store_dvmono_cb(), neighbours, NeighbourSelectionContext::nhops, NeighbourSelectionContext::num_eligible, TransportDVLearnMessage::num_hops, NeighbourSelectionContext::num_selections, peerstore, pils, 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 8592 of file gnunet-service-transport.c.

8593{
8594 uint16_t size = ntohs (dvb->header.size);
8595 uint16_t num_hops = ntohs (dvb->num_hops);
8596 const struct GNUNET_PeerIdentity *hops =
8597 (const struct GNUNET_PeerIdentity *) &dvb[1];
8598 const struct GNUNET_PeerIdentity *my_identity;
8599
8600 (void) cls;
8601 if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
8602 + sizeof(struct GNUNET_MessageHeader))
8603 {
8604 GNUNET_break_op (0);
8605 return GNUNET_SYSERR;
8606 }
8607
8610
8611 /* This peer must not be on the path */
8612 for (unsigned int i = 0; i < num_hops; i++)
8613 if (0 == GNUNET_memcmp (&hops[i], my_identity))
8614 {
8615 GNUNET_break_op (0);
8616 return GNUNET_SYSERR;
8617 }
8618 return GNUNET_YES;
8619}

References GNUNET_assert, GNUNET_break_op, GNUNET_memcmp, GNUNET_PILS_get_identity(), GNUNET_SYSERR, GNUNET_YES, TransportDVBoxMessage::header, my_identity, TransportDVBoxMessage::num_hops, pils, GNUNET_MessageHeader::size, and size.

Here is the call graph for this function:

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

8642{
8643 struct VirtualLink *vl = next_hop->vl;
8644 struct PendingMessage *pm;
8645 size_t msg_size = sizeof(struct TransportDVBoxMessage)
8646 + num_hops * sizeof(struct GNUNET_PeerIdentity)
8647 + enc_payload_size;
8648 char *buf;
8649 char msg_buf[msg_size] GNUNET_ALIGN;
8650 struct GNUNET_PeerIdentity *dhops;
8651
8652 hdr->num_hops = htons (num_hops);
8653 hdr->total_hops = htons (total_hops);
8654 hdr->header.size = htons (msg_size);
8655 memcpy (msg_buf, hdr, sizeof(*hdr));
8656 dhops = (struct GNUNET_PeerIdentity *) &msg_buf[sizeof(struct
8658 ;
8659 memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
8660 memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
8661
8662 if (GNUNET_YES == ntohs (hdr->without_fc))
8663 {
8665 "Forwarding control message (payload size %u) in DV Box to next hop %s (%u/%u) \n",
8666 enc_payload_size,
8667 GNUNET_i2s (&next_hop->pid),
8668 (unsigned int) num_hops,
8669 (unsigned int) total_hops);
8670 route_via_neighbour (next_hop, (const struct
8671 GNUNET_MessageHeader *) msg_buf,
8673 }
8674 else
8675 {
8676 pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
8678 "2 created pm %p storing vl %p \n",
8679 pm,
8680 vl);
8681 pm->pmt = PMT_DV_BOX;
8682 pm->vl = vl;
8683 pm->target = next_hop->pid;
8685 pm->logging_uuid = logging_uuid_gen++;
8687 pm->bytes_msg = msg_size;
8688 buf = (char *) &pm[1];
8689 memcpy (buf, msg_buf, msg_size);
8690
8692 "Created pending message %" PRIu64
8693 " for DV Box with next hop %s (%u/%u)\n",
8694 pm->logging_uuid,
8695 GNUNET_i2s (&next_hop->pid),
8696 (unsigned int) num_hops,
8697 (unsigned int) total_hops);
8698
8699 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
8700 {
8702 vl->pending_msg_head,
8703 vl->pending_msg_tail,
8704 pm);
8705
8707 }
8708 else
8709 {
8711 "The virtual link is not ready for forwarding a DV Box with payload, storing PendingMessage in ring buffer.\n");
8712
8714 {
8716
8717 GNUNET_free (pm_old);
8718 }
8721 {
8724 }
8725 else
8727
8729 "%u items stored in DV ring buffer\n",
8732 }
8733 }
8734}

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

8744{
8745 if (NULL != b->get)
8746 {
8748 b->get = NULL;
8749 GNUNET_assert (NULL != b->cmc);
8751 b->cmc = NULL;
8752 }
8753 if (NULL != b->task)
8754 {
8756 b->task = NULL;
8757 }
8758 if (NULL != b->sc)
8759 {
8761 "store cancel\n");
8763 b->sc = NULL;
8764 }
8766 "Removing backtalker for %s\n",
8767 GNUNET_i2s (&b->pid));
8769 GNUNET_YES ==
8771 GNUNET_free (b);
8772}

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

8787{
8788 struct Backtalker *b = value;
8789
8790 (void) cls;
8791 (void) pid;
8792 free_backtalker (b);
8793 return GNUNET_OK;
8794}

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

8804{
8805 struct Backtalker *b = cls;
8806
8808 "backtalker timeout.\n");
8809 b->task = NULL;
8811 {
8813 return;
8814 }
8815 GNUNET_assert (NULL == b->sc);
8816 free_backtalker (b);
8817}

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

8832{
8833 struct Backtalker *b = cls;
8834 struct GNUNET_TIME_AbsoluteNBO *mtbe;
8835 struct GNUNET_TIME_Absolute mt;
8836
8837 (void) emsg;
8838 if (NULL == record)
8839 {
8840 /* we're done with #backtalker_monotime_cb() invocations,
8841 continue normal processing */
8842 b->get = NULL;
8843 GNUNET_assert (NULL != b->cmc);
8844 b->cmc->mh = (const struct GNUNET_MessageHeader *) &b[1];
8845 if (0 != b->body_size)
8847 else
8849 b->cmc = NULL;
8850 return;
8851 }
8852 if (sizeof(*mtbe) != record->value_size)
8853 {
8855 GNUNET_break (0);
8856 return;
8857 }
8858 mtbe = record->value;
8859 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
8860 if (mt.abs_value_us > b->monotonic_time.abs_value_us)
8861 {
8863 "Backtalker message from %s dropped, monotime in the past\n",
8864 GNUNET_i2s (&b->pid));
8866 GST_stats,
8867 "# Backchannel messages dropped: monotonic time not increasing",
8868 1,
8869 GNUNET_NO);
8870 b->monotonic_time = mt;
8871 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
8872 */
8873 b->body_size = 0;
8874 }
8876}

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

8888{
8889 struct Backtalker *b = cls;
8890
8891 if (GNUNET_OK != success)
8892 {
8894 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
8895 }
8896 b->sc = NULL;
8897 if (NULL != b->task)
8898 {
8900 b->task = NULL;
8901 }
8903}

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

8913{
8914 struct GNUNET_TIME_AbsoluteNBO mtbe;
8915
8916 if (NULL != b->sc)
8917 {
8919 "store cancel before store with sc %p\n",
8920 b->sc);
8921 /*GNUNET_PEERSTORE_store_cancel (b->sc);
8922 b->sc = NULL;*/
8924 "store cancel before store with sc %p is null\n",
8925 b->sc);
8926 }
8927 else
8928 {
8930 b->task = NULL;
8931 }
8933 b->sc =
8935 "transport",
8936 &b->pid,
8938 &mtbe,
8939 sizeof(mtbe),
8943 b);
8944}

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

8957{
8958 struct DecapsDvBoxCls *decaps_dv_box_cls = cls;
8959 struct CommunicatorMessageContext *cmc = decaps_dv_box_cls->cmc;
8960 const struct TransportDVBoxMessage *dvb = decaps_dv_box_cls->dvb;
8961 const unsigned char *hdr;
8962 size_t hdr_len;
8964
8965 decaps_dv_box_cls->pr->op = NULL;
8968 decaps_dv_box_cls->pr);
8969 GNUNET_free (decaps_dv_box_cls->pr);
8970 if (NULL == km)
8971 {
8972 GNUNET_break_op (0);
8973 finish_cmc_handling (cmc);
8974 return;
8975 }
8976 key = (struct GNUNET_CRYPTO_AeadSecretKey*) km;
8977 hdr = (const unsigned char *) &dvb[1];
8978 hdr_len = ntohs (dvb->orig_size) - sizeof(*dvb) - sizeof(struct
8980 * ntohs (dvb->total_hops);
8981
8982 /* begin actual decryption */
8983 {
8984 struct Backtalker *b;
8985 struct GNUNET_TIME_Absolute monotime;
8986 struct TransportDVBoxPayloadP *ppay;
8987 unsigned char pt[hdr_len + sizeof *ppay] GNUNET_ALIGN;
8988 unsigned char *body;
8989 const struct GNUNET_MessageHeader *mh;
8990
8991 ppay = (struct TransportDVBoxPayloadP *) pt;
8992 body = &pt[sizeof *ppay];
8993 GNUNET_assert (hdr_len >=
8994 sizeof(*ppay) + sizeof(struct GNUNET_MessageHeader));
8995 if (GNUNET_OK != GNUNET_CRYPTO_aead_decrypt (hdr_len,
8996 hdr,
8997 0,
8998 NULL,
8999 key,
9000 &dvb->iv,
9001 &dvb->mac,
9002 pt))
9003 {
9005 "Error decrypting DV payload header\n");
9006 GNUNET_break_op (0);
9007 finish_cmc_handling (cmc);
9008 return;
9009 }
9010 mh = (const struct GNUNET_MessageHeader *) body;
9011 if (ntohs (mh->size) != sizeof(body))
9012 {
9013 GNUNET_break_op (0);
9014 finish_cmc_handling (cmc);
9015 return;
9016 }
9017 /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
9018 switch (ntohs (mh->type))
9019 {
9021 GNUNET_break_op (0);
9022 finish_cmc_handling (cmc);
9023 return;
9024
9026 GNUNET_break_op (0);
9027 finish_cmc_handling (cmc);
9028 return;
9029
9030 default:
9031 /* permitted, continue */
9032 break;
9033 }
9034 monotime = GNUNET_TIME_absolute_ntoh (ppay->monotonic_time);
9036 "Decrypted backtalk from %s\n",
9037 GNUNET_i2s (&ppay->sender));
9039 &ppay->sender);
9040 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
9041 {
9043 GST_stats,
9044 "# Backchannel messages dropped: monotonic time not increasing",
9045 1,
9046 GNUNET_NO);
9047 finish_cmc_handling (cmc);
9048 return;
9049 }
9050 if ((NULL == b) ||
9051 (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
9052 {
9053 /* Check signature */
9054 const struct GNUNET_PeerIdentity *my_identity;
9055 struct EphemeralConfirmationPS ec;
9056
9059
9060 ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL);
9061 ec.target = *my_identity;
9062 ec.ephemeral_key = dvb->ephemeral_key;
9063 ec.purpose.size = htonl (sizeof(ec));
9064 ec.sender_monotonic_time = ppay->monotonic_time;
9065 if (
9066 GNUNET_OK !=
9069 &ec,
9070 &ppay->sender_sig,
9071 &ppay->sender.public_key))
9072 {
9073 /* Signature invalid, discard! */
9074 GNUNET_break_op (0);
9075 finish_cmc_handling (cmc);
9076 return;
9077 }
9078 }
9079 /* Update sender, we now know the real origin! */
9081 "DVBox received for me from %s via %s\n",
9082 GNUNET_i2s2 (&ppay->sender),
9083 GNUNET_i2s (&cmc->im.sender));
9084 cmc->im.sender = ppay->sender;
9085
9086 if (NULL != b)
9087 {
9088 /* update key cache and mono time */
9089 b->last_ephemeral = dvb->ephemeral_key;
9090 b->monotonic_time = monotime;
9092 b->timeout =
9094 cmc->mh = mh;
9096 return;
9097 }
9098 /* setup data structure to cache signature AND check
9099 monotonic time with PEERSTORE before forwarding backchannel payload */
9100 b = GNUNET_malloc (sizeof(struct Backtalker) + sizeof(hdr_len));
9101 b->pid = ppay->sender;
9102 b->body_size = hdr_len;
9103 memcpy (&b[1], body, hdr_len);
9107 &b->pid,
9108 b,
9110 b->monotonic_time = monotime; /* NOTE: to be checked still! */
9111 b->cmc = cmc;
9112 b->timeout =
9115 b->get =
9117 "transport",
9118 &b->pid,
9121 b);
9122 } /* end actual decryption */
9123}

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(), 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_aead_decrypt(), 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_PILS_get_identity(), GNUNET_SCHEDULER_add_at(), GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL, GNUNET_STATISTICS_update(), GNUNET_TIME_absolute_ntoh(), GNUNET_TIME_relative_to_absolute(), GNUNET_YES, GST_stats, CommunicatorMessageContext::im, TransportDVBoxMessage::iv, key, Backtalker::last_ephemeral, TransportDVBoxMessage::mac, mh, CommunicatorMessageContext::mh, TransportDVBoxPayloadP::monotonic_time, Backtalker::monotonic_time, my_identity, PilsRequest::op, TransportDVBoxMessage::orig_size, peerstore, Backtalker::pid, pils, 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 9134 of file gnunet-service-transport.c.

9135{
9136 struct CommunicatorMessageContext *cmc = cls;
9137 uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
9138 uint16_t num_hops = ntohs (dvb->num_hops);
9139 const struct GNUNET_PeerIdentity *hops =
9140 (const struct GNUNET_PeerIdentity *) &dvb[1];
9141 const char *enc_payload = (const char *) &hops[num_hops];
9142 uint16_t enc_payload_size =
9143 size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
9144 struct DecapsDvBoxCls *decaps_dv_box_cls;
9145 const struct GNUNET_PeerIdentity *my_identity;
9146
9149
9150 if (GNUNET_EXTRA_LOGGING > 0)
9151 {
9152 char *path;
9153
9155 for (unsigned int i = 0; i < num_hops; i++)
9156 {
9157 char *tmp;
9158
9159 GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
9160 GNUNET_free (path);
9161 path = tmp;
9162 }
9164 "Received DVBox with remaining path %s\n",
9165 path);
9166 GNUNET_free (path);
9167 }
9168
9169 if (num_hops > 0)
9170 {
9171 /* We're trying from the end of the hops array, as we may be
9172 able to find a shortcut unknown to the origin that way */
9173 for (int i = num_hops - 1; i >= 0; i--)
9174 {
9175 struct Neighbour *n;
9176
9177 if (0 == GNUNET_memcmp (&hops[i], my_identity))
9178 {
9179 GNUNET_break_op (0);
9180 finish_cmc_handling (cmc);
9181 return;
9182 }
9183 n = lookup_neighbour (&hops[i]);
9184 if (NULL == n)
9185 continue;
9187 "Skipping %u/%u hops ahead while routing DV Box\n",
9188 i,
9189 num_hops);
9190
9191 forward_dv_box (n,
9192 (struct TransportDVBoxMessage *) dvb,
9193 ntohs (dvb->total_hops) + 1,
9194 num_hops - i - 1, /* number of hops left */
9195 &hops[i + 1], /* remaining hops */
9196 enc_payload,
9197 enc_payload_size);
9199 "# DV hops skipped routing boxes",
9200 i,
9201 GNUNET_NO);
9203 "# DV boxes routed (total)",
9204 1,
9205 GNUNET_NO);
9206 finish_cmc_handling (cmc);
9207 return;
9208 }
9209 /* Woopsie, next hop not in neighbours, drop! */
9211 "# DV Boxes dropped: next hop unknown",
9212 1,
9213 GNUNET_NO);
9214 finish_cmc_handling (cmc);
9215 return;
9216 }
9217 /* We are the target. Unbox and handle message. */
9219 "# DV boxes opened (ultimate target)",
9220 1,
9221 GNUNET_NO);
9222 cmc->total_hops = ntohs (dvb->total_hops);
9223
9224 {
9225 // DH key derivation with received DV, could be garbage.
9226 decaps_dv_box_cls = GNUNET_new (struct DecapsDvBoxCls);
9227 decaps_dv_box_cls->cmc = cmc;
9228 decaps_dv_box_cls->dvb = dvb;
9229 decaps_dv_box_cls->pr = GNUNET_new (struct PilsRequest);
9230
9233 decaps_dv_box_cls->pr);
9234 decaps_dv_box_cls->pr->op = GNUNET_PILS_kem_decaps (pils,
9235 &dvb->ephemeral_key,
9237 decaps_dv_box_cls);
9238 }
9239 // TODO keep track of cls and potentially clean
9240}

References DecapsDvBoxCls::cmc, decaps_dv_box_cb(), DecapsDvBoxCls::dvb, TransportDVBoxMessage::ephemeral_key, finish_cmc_handling(), forward_dv_box(), GNUNET_asprintf(), GNUNET_assert, 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_get_identity(), GNUNET_PILS_kem_decaps(), GNUNET_STATISTICS_update(), GNUNET_strdup, GST_stats, TransportDVBoxMessage::header, lookup_neighbour(), my_identity, 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 9251 of file gnunet-service-transport.c.

9253{
9254 struct TransportClient *tc = cls;
9255
9256 if (CT_COMMUNICATOR != tc->type)
9257 {
9258 GNUNET_break (0);
9259 return GNUNET_SYSERR;
9260 }
9262 return GNUNET_OK;
9263}

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

9296{
9297 struct CheckKnownAddressContext *ckac = cls;
9298 struct ValidationState *vs = value;
9299
9300 (void) pid;
9301 if (0 != strcmp (vs->address, ckac->address))
9302 return GNUNET_OK;
9303 ckac->vs = vs;
9304 return GNUNET_NO;
9305}

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

11960{
11961 struct ValidationState *vs;
11962 struct Queue *q;
11964 GST_cfg);
11965
11966 (void) cls;
11967 validation_task = NULL;
11969 /* drop validations past their expiration */
11970 while (
11971 (NULL != vs) &&
11973 {
11975 "Validation response %s cleaned up\n",
11976 GNUNET_sh2s (&vs->challenge.value));
11979 }
11980 if (NULL == vs)
11981 {
11983 "Address validation task not scheduled anymore, nothing to do\n");
11984 return; /* woopsie, no more addresses known, should only
11985 happen if we're really a lonely peer */
11986 }
11987 q = find_queue (&vs->pid, vs->address);
11988 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
11989 {
11991 "To early to start next address validation for challenge %s\n",
11992 GNUNET_sh2s (&vs->challenge.value));
11993 return;
11994 }
11995 if (NULL == q)
11996 {
11997 vs->awaiting_queue = GNUNET_YES;
11998 suggest_to_connect (&vs->pid, vs->address);
11999 }
12000 else
12002 /* Finally, reschedule next attempt */
12003 vs->challenge_backoff =
12004 GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
12007 "Address validation task will run again in %s\n",
12008 GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
12009 GNUNET_YES));
12012 vs->challenge_backoff));
12013}

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

9327{
9329
9330 if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
9331 return; /* be lazy */
9332 vs->next_challenge = new_time;
9333 if (NULL == vs->hn)
9334 vs->hn =
9336 else
9339 (NULL != validation_task))
9340 return;
9341 if (NULL != validation_task)
9343 /* randomize a bit */
9346 new_time = GNUNET_TIME_absolute_add (new_time, delta);
9349}

References GNUNET_TIME_Absolute::abs_value_us, delta, GNUNET_CONTAINER_heap_insert(), GNUNET_CONTAINER_heap_peek(), GNUNET_CONTAINER_heap_update_cost(), 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 9359 of file gnunet-service-transport.c.

9361{
9362 struct GNUNET_TIME_Absolute now;
9363 struct ValidationState *vs;
9364 struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
9365
9367 pid,
9369 &ckac);
9370 if (NULL != (vs = ckac.vs))
9371 {
9372 /* if 'vs' is not currently valid, we need to speed up retrying the
9373 * validation */
9374 if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
9375 {
9376 /* reduce backoff as we got a fresh advertisement */
9377 vs->challenge_backoff =
9380 vs->challenge_backoff,
9381 2));
9384 vs->challenge_backoff));
9385 }
9386 return;
9387 }
9389 vs = GNUNET_new (struct ValidationState);
9390 vs->pid = *pid;
9391 vs->valid_until =
9393 vs->first_challenge_use = now;
9394 vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
9395 GNUNET_CRYPTO_random_block (&vs->challenge,
9396 sizeof(vs->challenge));
9397 vs->address = GNUNET_strdup (address);
9398 GNUNET_CRYPTO_hash (vs->address, strlen (vs->address), &vs->hc);
9400 "Starting address validation `%s' of peer %s using challenge %s\n",
9401 address,
9402 GNUNET_i2s (pid),
9403 GNUNET_sh2s (&vs->challenge.value));
9407 &vs->pid,
9408 vs,
9411}

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

9738{
9739 struct Neighbour *n;
9740
9741 n = lookup_neighbour (pid);
9742 if (NULL == n)
9743 return NULL;
9744 for (struct Queue *pos = n->queue_head; NULL != pos;
9745 pos = pos->next_neighbour)
9746 {
9747 if (0 == strcmp (pos->address, address))
9748 return pos;
9749 }
9750 return NULL;
9751}

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

11856{
11857 static uint32_t idgen = 0;
11858 struct TransportClient *tc;
11859 char *prefix;
11860 struct GNUNET_TRANSPORT_CreateQueue *cqm;
11861 struct GNUNET_MQ_Envelope *env;
11862 size_t alen;
11863
11865 if (NULL == prefix)
11866 {
11867 GNUNET_break (0); /* We got an invalid address!? */
11868 return;
11869 }
11871 if (NULL == tc)
11872 {
11874 "# Suggestions ignored due to missing communicator",
11875 1,
11876 GNUNET_NO);
11878 "Cannot connect to %s at `%s', no matching communicator present\n",
11879 GNUNET_i2s (pid),
11880 address);
11882 return;
11883 }
11884 /* forward suggestion for queue creation to communicator */
11886 "Request #%u for `%s' communicator to create queue to `%s' at `%s'\n",
11887 (unsigned int) idgen,
11888 prefix,
11889 GNUNET_i2s (pid),
11890 address);
11892 alen = strlen (address) + 1;
11893 env =
11895 cqm->request_id = htonl (idgen++);
11896 cqm->receiver = *pid;
11897 memcpy (&cqm[1], address, alen);
11898 GNUNET_MQ_send (tc->mq, env);
11899}

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

9426{
9427 struct Queue *q;
9428 int pfx_len;
9429 const char *eou;
9430 char *address;
9431 (void) cls;
9432
9433 eou = strstr (uri,
9434 "://");
9435 pfx_len = eou - uri;
9436 eou += 3;
9438 "%.*s-%s",
9439 pfx_len,
9440 uri,
9441 eou);
9442
9444 "helo for client %s\n",
9445 address);
9446 q = find_queue (pid, address);
9447 if (NULL == q)
9448 {
9450 }
9451 else
9454}

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

9468{
9469 struct IncomingRequest *ir = cls;
9471 struct GNUNET_MessageHeader *hello;
9472 const struct GNUNET_PeerIdentity *my_identity;
9473
9474 if (NULL != emsg)
9475 {
9477 "Got failure from PEERSTORE: %s\n",
9478 emsg);
9479 return;
9480 }
9481 hello = record->value;
9484 if (0 == GNUNET_memcmp (&record->peer, my_identity))
9485 {
9487 return;
9488 }
9489 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
9492 NULL);
9493 GNUNET_HELLO_parser_free (parser);
9494}

References GNUNET_assert, 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(), GNUNET_PILS_get_identity(), hello_for_incoming_cb(), my_identity, IncomingRequest::nc, pils, 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 9498 of file gnunet-service-transport.c.

9499{
9501 "Error in PEERSTORE monitoring\n");
9502}

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

9507{
9509 "Done with initial PEERSTORE iteration during monitoring\n");
9510}

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

9525{
9526 struct SignTValidationCls *sign_t_validation_cls = cls;
9527 struct CommunicatorMessageContext *cmc = sign_t_validation_cls->cmc;
9528 struct TransportValidationResponseMessage tvr = sign_t_validation_cls->tvr;
9529 struct VirtualLink *vl;
9530 struct Neighbour *n;
9531 struct IncomingRequest *ir;
9532 struct GNUNET_PeerIdentity sender;
9533
9534 sign_t_validation_cls->pr->op = NULL;
9537 sign_t_validation_cls->pr);
9538 GNUNET_free (sign_t_validation_cls->pr);
9539 tvr.signature = *sig;
9540 sender = cmc->im.sender;
9541 vl = lookup_virtual_link (&sender);
9542 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9543 {
9544 // route_control_message_without_fc (&cmc->im.sender,
9546 &tvr.header,
9548 }
9549 else
9550 {
9551 /* Use route via neighbour */
9552 n = lookup_neighbour (&sender);
9553 if (NULL != n)
9554 route_via_neighbour (n, &tvr.header,
9557 }
9558
9559 finish_cmc_handling (cmc);
9560 if (NULL != vl)
9561 return;
9562
9563 /* For us, the link is still down, but we need bi-directional
9564 connections (for flow-control and for this to be useful for
9565 CORE), so we must try to bring the link up! */
9566
9567 /* (1) Check existing queues, if any, we may be lucky! */
9568 n = lookup_neighbour (&sender);
9569 if (NULL != n)
9570 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
9571 start_address_validation (&sender, q->address);
9572 /* (2) Also try to see if we have addresses in PEERSTORE for this peer
9573 we could use */
9574 for (ir = ir_head; NULL != ir; ir = ir->next)
9575 if (0 == GNUNET_memcmp (&ir->pid, &sender))
9576 return;
9577 /* we are already trying */
9578 ir = GNUNET_new (struct IncomingRequest);
9579 ir->pid = sender;
9581
9583 GNUNET_YES,
9584 "peerstore",
9585 NULL,
9588 NULL,
9590 NULL,
9592 ir);
9593 ir_total++;
9594 /* Bound attempts we do in parallel here, might otherwise get excessive */
9597};

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

9612{
9613 struct CommunicatorMessageContext *cmc = cls;
9614 struct TransportValidationResponseMessage tvr = { 0 };
9615 struct GNUNET_TIME_RelativeNBO validity_duration;
9616
9617 /* DV-routed messages are not allowed for validation challenges */
9618 if (cmc->total_hops > 0)
9619 {
9620 GNUNET_break_op (0);
9621 finish_cmc_handling (cmc);
9622 return;
9623 }
9624 validity_duration = cmc->im.expected_address_validity;
9626 "Received address validation challenge %s\n",
9627 GNUNET_sh2s (&tvc->challenge.value));
9628 /* If we have a virtual link, we use this mechanism to signal the
9629 size of the flow control window, and to allow the sender
9630 to ask for increases. If for us the virtual link is still down,
9631 we will always give a window size of zero. */
9632 tvr.header.type =
9634 tvr.header.size = htons (sizeof(tvr));
9635 tvr.reserved = htonl (0);
9636 tvr.challenge = tvc->challenge;
9637 tvr.origin_time = tvc->sender_time;
9638 tvr.validity_duration = validity_duration;
9639 {
9640 /* create signature */
9641 struct TransportValidationPS tvp = {
9643 .purpose.size = htonl (sizeof(tvp)),
9644 .validity_duration = validity_duration,
9645 .challenge = tvc->challenge
9646 };
9647 struct SignTValidationCls *sign_t_validation_cls;
9648
9649 sign_t_validation_cls = GNUNET_new (struct SignTValidationCls);
9650 sign_t_validation_cls->cmc = cmc;
9651 sign_t_validation_cls->tvr = tvr;
9652 sign_t_validation_cls->pr = GNUNET_new (struct PilsRequest);
9655 sign_t_validation_cls->pr);
9656 sign_t_validation_cls->pr->op =
9658 &tvp.purpose,
9660 sign_t_validation_cls);
9661 }
9662}

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

9695{
9696 struct CheckKnownChallengeContext *ckac = cls;
9697 struct ValidationState *vs = value;
9698
9699 (void) pid;
9700 if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
9701 return GNUNET_OK;
9702 ckac->vs = vs;
9703 return GNUNET_NO;
9704}

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

9716{
9717 struct ValidationState *vs = cls;
9718
9719 vs->sc = NULL;
9720 if (GNUNET_YES == success)
9721 return;
9723 "# Peerstore failed to store foreign address",
9724 1,
9725 GNUNET_NO);
9726}

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

11911{
11913 struct GNUNET_TIME_Absolute monotonic_time;
11914
11915 if (NULL != vs->revalidation_task)
11916 {
11917 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
11918 vs->revalidation_task = NULL;
11919 }
11920 /*memcpy (&hkey,
11921 &hc,
11922 sizeof (hkey));*/
11924 "Remove key %s for address %s map size %u contains %u\n",
11925 GNUNET_h2s (&vs->hc),
11926 vs->address,
11929 &vs->hc));
11931
11933 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
11934 vs->last_challenge_use.abs_value_us)
11935 {
11936 vs->first_challenge_use = monotonic_time;
11937 }
11938 vs->last_challenge_use = monotonic_time;
11939 tvc.header.type =
11941 tvc.header.size = htons (sizeof(tvc));
11942 tvc.reserved = htonl (0);
11943 tvc.challenge = vs->challenge;
11944 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
11946 "Sending address validation challenge %s to %s\n",
11947 GNUNET_sh2s (&tvc.challenge.value),
11948 GNUNET_i2s (&q->neighbour->pid));
11949 queue_send_msg (q, NULL, &tvc, sizeof(tvc));
11950}

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

9759{
9760 struct ValidationState *vs = cls;
9761 struct Queue *q;
9762 struct GNUNET_TIME_Absolute now;
9763
9764 vs->revalidation_task = NULL;
9765 q = find_queue (&vs->pid, vs->address);
9766 if (NULL == q)
9767 {
9768 now = GNUNET_TIME_absolute_get ();
9769 vs->awaiting_queue = GNUNET_YES;
9770 suggest_to_connect (&vs->pid, vs->address);
9772 }
9773 else
9775}

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

9783{
9784 (void) cls;
9786 "Key in revalidate map %s \n",
9787 GNUNET_h2s (key));
9788 return GNUNET_YES;
9789}

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

9804{
9805 struct CommunicatorMessageContext *cmc = cls;
9806 struct ValidationState *vs;
9807 struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
9808 .vs = NULL};
9809 struct GNUNET_TIME_Absolute origin_time;
9810 struct Queue *q;
9811 struct Neighbour *n;
9812 struct VirtualLink *vl;
9814 GST_cfg);
9815
9816 /* check this is one of our challenges */
9818 &cmc->im.sender,
9820 &ckac);
9821 if (NULL == (vs = ckac.vs))
9822 {
9823 /* This can happen simply if we 'forgot' the challenge by now,
9824 i.e. because we received the validation response twice */
9826 "# Validations dropped, challenge unknown",
9827 1,
9828 GNUNET_NO);
9830 "Validation response %s dropped, challenge unknown\n",
9831 GNUNET_sh2s (&tvr->challenge.value));
9832 finish_cmc_handling (cmc);
9833 return;
9834 }
9835
9836 /* sanity check on origin time */
9837 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
9838 if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
9839 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
9840 {
9842 "Diff first use %" PRIu64 " and last use %" PRIu64 "\n",
9843 vs->first_challenge_use.abs_value_us - origin_time.abs_value_us,
9844 origin_time.abs_value_us - vs->last_challenge_use.abs_value_us);
9845 GNUNET_break_op (0);
9846 finish_cmc_handling (cmc);
9847 return;
9848 }
9849
9850 {
9851 /* check signature */
9852 struct TransportValidationPS tvp = {
9854 .purpose.size = htonl (sizeof(tvp)),
9855 .validity_duration = tvr->validity_duration,
9856 .challenge = tvr->challenge
9857 };
9858
9859 if (
9860 GNUNET_OK !=
9862 &tvp,
9863 &tvr->signature,
9864 &cmc->im.sender.public_key))
9865 {
9866 GNUNET_break_op (0);
9867 finish_cmc_handling (cmc);
9868 return;
9869 }
9870 }
9871
9872 /* validity is capped by our willingness to keep track of the
9873 validation entry and the maximum the other peer allows */
9876 tvr->validity_duration),
9878 vs->validated_until =
9882 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
9883 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
9884 GNUNET_CRYPTO_random_block (&vs->challenge,
9885 sizeof(vs->challenge));
9886 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
9887 vs->validated_until,
9888 GNUNET_TIME_relative_multiply (vs->validation_rtt,
9890 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, <, now))
9891 {
9893 "First challenge use is now %" PRIu64 " %s \n",
9894 vs->first_challenge_use.abs_value_us,
9895 GNUNET_sh2s (&vs->challenge.value));
9896 vs->first_challenge_use = now;
9897 }
9898 else
9900 "First challenge use is later %" PRIu64 " %s \n",
9901 vs->first_challenge_use.abs_value_us,
9902 GNUNET_sh2s (&vs->challenge.value));
9903 vs->last_challenge_use =
9904 GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
9905 update_next_challenge_time (vs, vs->first_challenge_use);
9907 "Validation response %s from %s accepted, address valid until %s\n",
9908 GNUNET_sh2s (&tvr->challenge.value),
9909 GNUNET_i2s (&cmc->im.sender),
9911 /*memcpy (&hkey,
9912 &hc,
9913 sizeof (hkey));*/
9915 "Key %s for address %s map size %u contains %u\n",
9916 GNUNET_h2s (&vs->hc),
9917 vs->address,
9920 &vs->hc));
9924 &vs->hc,
9925 vs,
9929 NULL);
9930 vs->revalidation_task =
9935 "transport",
9936 &cmc->im.sender,
9938 vs->address,
9939 strlen (vs->address) + 1,
9940 vs->valid_until,
9943 vs);
9944 finish_cmc_handling (cmc);
9945
9946 /* Finally, we now possibly have a confirmed (!) working queue,
9947 update queue status (if queue still is around) */
9948 q = find_queue (&vs->pid, vs->address);
9949 if (NULL == q)
9950 {
9952 "# Queues lost at time of successful validation",
9953 1,
9954 GNUNET_NO);
9955 return;
9956 }
9957 q->validated_until = vs->validated_until;
9958 q->pd.aged_rtt = vs->validation_rtt;
9959 n = q->neighbour;
9960 vl = lookup_virtual_link (&vs->pid);
9961 if (NULL == vl)
9962 {
9963 vl = GNUNET_new (struct VirtualLink);
9965 "Creating new virtual link %p to %s using direct neighbour!\n",
9966 vl,
9967 GNUNET_i2s (&vs->pid));
9968 vl->burst_addr = NULL;
9969 vl->confirmed = GNUNET_YES;
9970 vl->message_uuid_ctr =
9971 GNUNET_CRYPTO_random_u64 (UINT64_MAX);
9972 vl->target = n->pid;
9978 links,
9979 &vl->target,
9980 vl,
9982 vl->n = n;
9983 n->vl = vl;
9984 q->idle = GNUNET_YES;
9985 vl->visibility_task =
9986 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
9988 /* We lacked a confirmed connection to the target
9989 before, so tell CORE about it (finally!) */
9992 }
9993 else
9994 {
9995 /* Link was already up, remember n is also now available and we are done */
9996 if (NULL == vl->n)
9997 {
9998 vl->n = n;
9999 n->vl = vl;
10000 if (GNUNET_YES == vl->confirmed)
10002 "Virtual link to %s could now also use direct neighbour!\n",
10003 GNUNET_i2s (&vs->pid));
10004 }
10005 else
10006 {
10007 GNUNET_assert (n == vl->n);
10008 }
10009 if (GNUNET_NO == vl->confirmed)
10010 {
10011 vl->confirmed = GNUNET_YES;
10012 q->idle = GNUNET_YES;
10013 vl->visibility_task =
10014 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
10016 /* We lacked a confirmed connection to the target
10017 before, so tell CORE about it (finally!) */
10020 }
10021 }
10022}

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

10033{
10034 struct TransportClient *tc = cls;
10035 struct CommunicatorMessageContext *cmc =
10037
10038 cmc->tc = tc;
10039 cmc->im = *im;
10041 "Received message with size %u and flow control id %" PRIu64
10042 " via communicator from peer %s\n",
10043 ntohs (im->header.size),
10044 im->fc_id,
10045 GNUNET_i2s (&im->sender));
10046 cmc->im.neighbour_sender = cmc->im.sender;
10047 cmc->mh = (const struct GNUNET_MessageHeader *) &im[1];
10049}

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

10062{
10063 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10064 (void) cls;
10065
10067 "Flow control header size %u size of addresses %u number of addresses %u size of message struct %lu second struct %lu\n",
10068 ntohs (fc->header.size),
10069 ntohl (fc->size_of_addresses),
10070 ntohl (fc->number_of_addresses),
10071 sizeof(struct TransportFlowControlMessage),
10072 sizeof (struct TransportGlobalNattedAddress));
10073
10074 if (0 == number_of_addresses || ntohs (fc->header.size) == sizeof(struct
10076 + ntohl (fc->number_of_addresses) * sizeof (struct
10078 + ntohl (fc->size_of_addresses))
10079 return GNUNET_OK;
10080 else
10081 {
10082 GNUNET_break_op (0);
10083 return GNUNET_SYSERR;
10084 }
10085}

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

10119{
10120 struct VirtualLink *vl = cls;
10121 const char *slash;
10122 char *address_uri;
10123 char *prefix;
10124 char *uri_without_port;
10125
10126 slash = strrchr (uri, '/');
10127 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
10128 GNUNET_assert (NULL != slash);
10129 slash++;
10130 GNUNET_asprintf (&address_uri,
10131 "%s-%s",
10132 prefix,
10133 slash);
10134
10135 uri_without_port = get_address_without_port (address_uri);
10137 "iterate_address_start_burst %s %s %s %s\n",
10138 uri_without_port,
10139 uri,
10140 address_uri,
10141 slash);
10142 if (0 == strcmp (uri_without_port, slash))
10143 {
10144 vl->burst_addr = GNUNET_strndup (uri_without_port, strlen (uri_without_port)
10145 );
10146 }
10147 else
10148 vl->burst_addr = NULL;
10149
10151 GNUNET_free (uri_without_port);
10152}

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

10159{
10160 struct GNUNET_StartBurstCls *sb_cls = cls;
10161 struct VirtualLink *vl = sb_cls->vl;
10162 struct GNUNET_MessageHeader *hello;
10164
10165 if (NULL != emsg)
10166 {
10168 "Got failure from PEERSTORE: %s\n",
10169 emsg);
10170 return;
10171 }
10172 if (NULL == record)
10173 {
10175 "Hello iteration end for %s\n",
10176 GNUNET_i2s (&vl->target));
10177 vl->ic = NULL;
10178 GNUNET_free (sb_cls);
10179 return;
10180 }
10181
10183 "check_for_burst_address\n");
10184 hello = record->value;
10185 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
10188 vl);
10189 GNUNET_HELLO_parser_free (parser);
10190
10192 GNUNET_free (sb_cls);
10193}

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

10198{
10200}

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

10205{
10206 struct GNUNET_StartBurstCls *sb_cls = cls;
10207 struct VirtualLink *vl = sb_cls->vl;
10208 struct GNUNET_TRANSPORT_StartBurst *sb;
10209 struct GNUNET_MQ_Envelope *env;
10210 char *uri_without_port = vl->burst_addr;
10211
10212 burst_task = NULL;
10213 /*char buf[strlen (uri_without_port) + 1];
10214
10215 GNUNET_memcpy (buf, uri_without_port, strlen (uri_without_port));
10216 buf[strlen (uri_without_port)] = '\0';*/
10217 env =
10219 strlen (uri_without_port) + 1,
10221 sb->rtt = GNUNET_TIME_relative_hton (sb_cls->rtt);
10222 sb->pid = vl->target;
10223 memcpy (&sb[1], uri_without_port, strlen (uri_without_port) + 1);
10224 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
10225 {
10227 "iterate_address_start_burst client tc prefix %s\n",
10228 tc->details.communicator.address_prefix);
10229 if (CT_COMMUNICATOR != tc->type)
10230 continue;
10231 if (GNUNET_YES == tc->details.communicator.can_burst)
10232 {
10234 "iterate_address_start_burst %s call %lu %u rtt %lu\n",
10235 uri_without_port,
10236 strlen (uri_without_port),
10237 ntohs (sb->header.size),
10238 (unsigned long) sb_cls->rtt.rel_value_us);
10239 GNUNET_MQ_send (tc->mq, env);
10243 60),
10245 NULL);
10246 // TODO We need some algo to choose from available communicators. Can we run two bursts at once? Atm we only implemented udp burst.
10247 break;
10248 }
10249 }
10250 GNUNET_free (env);
10251 GNUNET_free (sb_cls);
10252}

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

10257{
10258 struct GNUNET_StartBurstCls *sb_cls = cls;
10259 struct VirtualLink *vl = sb_cls->vl;
10260
10261 if (GNUNET_YES != use_burst)
10262 return;
10264 "burst_task %p ready %s burst addr %s (%p)\n",
10265 burst_task,
10266 sb_cls->sync_ready ? "yes" : "no",
10267 vl->burst_addr,
10268 vl->burst_addr);
10269 if (NULL != burst_task && GNUNET_NO == sb_cls->sync_ready)
10270 {
10272 burst_task = NULL;
10274 return;
10275 }
10276 if (GNUNET_NO == burst_running && NULL != vl->burst_addr && NULL == burst_task
10277 )
10278 {
10280 &start_burst,
10281 sb_cls);
10282 }
10283 else if (NULL == vl->burst_addr)
10284 {
10286 "peerstore",
10287 &vl->target,
10290 sb_cls);
10291 }
10292}

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

10305{
10306 struct CommunicatorMessageContext *cmc = cls;
10307 struct VirtualLink *vl;
10309 uint32_t seq;
10310 struct GNUNET_TIME_Absolute st;
10311 uint64_t os;
10312 uint64_t wnd;
10313 uint32_t random;
10314
10316 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
10317 vl = lookup_virtual_link (&cmc->im.sender);
10318 if (NULL == vl)
10319 {
10320 vl = GNUNET_new (struct VirtualLink);
10322 "No virtual link for %p FC creating new unconfirmed virtual link to %s!\n",
10323 vl,
10324 GNUNET_i2s (&cmc->im.sender));
10325 vl->burst_addr = NULL;
10326 vl->confirmed = GNUNET_NO;
10327 vl->message_uuid_ctr =
10328 GNUNET_CRYPTO_random_u64 (UINT64_MAX);
10329 vl->target = cmc->im.sender;
10335 links,
10336 &vl->target,
10337 vl,
10339 }
10340 if (NULL != vl->n)
10341 {
10342 for (struct Queue *q = vl->n->queue_head; NULL != q; q = q->next_neighbour)
10343 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
10344 }
10345
10347 "remaining %lu timeout for neighbour %p\n",
10348 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout).
10349 rel_value_us,
10350 vl->n);
10351 if (NULL == vl->n ||
10352 0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
10353 {
10354 struct GNUNET_TIME_Relative rtt;
10355 struct GNUNET_BurstSync burst_sync;
10356 struct GNUNET_StartBurstCls *bcls;
10357
10358 bcls = GNUNET_new (struct GNUNET_StartBurstCls);
10359 bcls->vl = vl;
10360 vl->sb_cls = bcls;
10361 if (NULL != vl->dv)
10362 rtt = calculate_rtt (vl->dv);
10363 else
10365 burst_sync.rtt_average = fc->rtt;
10366 bcls->rtt = GNUNET_TIME_relative_ntoh (burst_sync.rtt_average);
10367 burst_sync.sync_ready = fc->sync_ready;
10368
10370 &burst_sync,
10371 &queue_burst,
10372 bcls);
10373 }
10374 if (0 != ntohl (fc->number_of_addresses))
10375 {
10376 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10377 const char *tgnas;
10378 unsigned int off = 0;
10379
10380 tgnas = (const char *) &fc[1];
10381
10382 for (int i = 1; i <= number_of_addresses; i++)
10383 {
10384 struct TransportGlobalNattedAddress *tgna;
10385 char *addr;
10386 unsigned int address_length;
10387
10388 tgna = (struct TransportGlobalNattedAddress*) &tgnas[off];
10389 addr = (char *) &tgna[1];
10390 address_length = ntohl (tgna->address_length);
10391 off += sizeof(struct TransportGlobalNattedAddress) + address_length;
10392
10394 "received address %s length %u\n",
10395 addr,
10396 ntohl (tgna->address_length));
10397
10398 GNUNET_NAT_add_global_address (nh, addr, ntohl (tgna->address_length));
10399 }
10400 }
10402 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
10403 {
10405 "FC dropped: Message out of order\n");
10406 /* out of order, drop */
10408 "# FC dropped: message out of order",
10409 1,
10410 GNUNET_NO);
10411 finish_cmc_handling (cmc);
10412 return;
10413 }
10414 seq = ntohl (fc->seq);
10415 if (seq < vl->last_fc_seq)
10416 {
10417 /* Wrap-around/reset of other peer; start all counters from zero */
10419 }
10420 vl->last_fc_seq = seq;
10421 vl->last_fc_timestamp = st;
10423 os = GNUNET_ntohll (fc->outbound_sent);
10425 (int64_t) (os - vl->incoming_fc_window_size_used);
10427 "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
10428 GNUNET_i2s (&vl->target),
10429 (unsigned int) seq,
10430 (unsigned long long) vl->outbound_fc_window_size,
10431 (long long) vl->incoming_fc_window_size_loss);
10433 random = GNUNET_CRYPTO_random_u32 (UINT32_MAX);
10434 if ((GNUNET_YES == vl->confirmed) && ((wnd < vl->incoming_fc_window_size
10438 != wnd) ||
10439 (0 == random
10441 {
10443 "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",
10444 (unsigned long long) wnd,
10445 (unsigned long long) vl->incoming_fc_window_size,
10446 (unsigned long long) vl->last_outbound_window_size_received,
10449 }
10450 if ((wnd == vl->incoming_fc_window_size
10454 (NULL != vl->fc_retransmit_task))
10455 {
10457 "Stopping FC retransmission to %s: peer is current at window %llu\n",
10458 GNUNET_i2s (&vl->target),
10459 (unsigned long long) wnd);
10461 vl->fc_retransmit_task = NULL;
10462 vl->fc_retransmit_count = 0;
10463 }
10465 /* FC window likely increased, check transmission possibilities! */
10467 finish_cmc_handling (cmc);
10468}

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

10553{
10554 struct TransportClient *tc = cls;
10555
10556 if (CT_COMMUNICATOR != tc->type)
10557 {
10558 GNUNET_break (0);
10559 return GNUNET_SYSERR;
10560 }
10562 return GNUNET_OK;
10563}

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

10573{
10574 if (pm->msg_uuid_set)
10575 return;
10576 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
10577 pm->msg_uuid_set = GNUNET_YES;
10578}

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

10593{
10594 struct PendingAcknowledgement *pa;
10595
10596 pa = GNUNET_new (struct PendingAcknowledgement);
10597 pa->queue = queue;
10598 pa->dvh = dvh;
10599 pa->pm = pm;
10600 do
10601 {
10603 sizeof(pa->ack_uuid));
10604 }
10607 &pa->ack_uuid.value,
10608 pa,
10610 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
10611 GNUNET_CONTAINER_MDLL_insert (pm, pm->pa_head, pm->pa_tail, pa);
10612 if (NULL != dvh)
10615 pa->message_size = pm->bytes_msg;
10617 "Waiting for ACKnowledgment `%s' for <%" PRIu64 ">\n",
10619 pm->logging_uuid);
10620 return pa;
10621}

References PendingAcknowledgement::ack_uuid, PendingAcknowledgement::dvh, GNUNET_CONTAINER_MDLL_insert, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multiuuidmap_put(), 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 10636 of file gnunet-service-transport.c.

10639{
10640 struct PendingAcknowledgement *pa;
10641 struct PendingMessage *ff;
10642 uint16_t mtu;
10643 uint16_t msize;
10644
10645 mtu = (UINT16_MAX == queue->mtu)
10646 ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
10647 : queue->mtu;
10649 "Fragmenting message <%" PRIu64
10650 "> with size %u to %s for MTU %u\n",
10651 pm->logging_uuid,
10652 pm->bytes_msg,
10653 GNUNET_i2s (&pm->vl->target),
10654 (unsigned int) mtu);
10657 "Fragmenting message %" PRIu64 " <%" PRIu64
10658 "> with size %u to %s for MTU %u\n",
10659 pm->msg_uuid.uuid,
10660 pm->logging_uuid,
10661 pm->bytes_msg,
10662 GNUNET_i2s (&pm->vl->target),
10663 (unsigned int) mtu);
10664
10665 /* This invariant is established in #handle_add_queue_message() */
10666 GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
10667
10668 /* select fragment for transmission, descending the tree if it has
10669 been expanded until we are at a leaf or at a fragment that is small
10670 enough
10671 */
10672 ff = pm;
10673 msize = ff->bytes_msg;
10674
10675 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
10676 (ff->frag_off == msize) && (NULL != ff->head_frag))
10677 {
10678 ff = ff->head_frag; /* descent into fragmented fragments */
10679 msize = ff->bytes_msg - sizeof(struct TransportFragmentBoxMessage);
10680 }
10681
10682 if (((ff->bytes_msg > mtu) || (pm == ff)) && (ff->frag_off < msize))
10683 {
10684 /* Did not yet calculate all fragments, calculate next fragment */
10685 struct PendingMessage *frag;
10686 struct TransportFragmentBoxMessage tfb;
10687 const char *orig;
10688 char *msg;
10689 uint16_t fragmax;
10690 uint16_t fragsize;
10691 uint16_t msize_ff;
10692 uint16_t xoff = 0;
10693 pm->frag_count++;
10694
10695 orig = (const char *) &ff[1];
10696 msize_ff = ff->bytes_msg;
10697 if (pm != ff)
10698 {
10699 const struct TransportFragmentBoxMessage *tfbo;
10700
10701 tfbo = (const struct TransportFragmentBoxMessage *) orig;
10702 orig += sizeof(struct TransportFragmentBoxMessage);
10703 msize_ff -= sizeof(struct TransportFragmentBoxMessage);
10704 xoff = ntohs (tfbo->frag_off);
10705 }
10706 fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
10707 fragsize = GNUNET_MIN (msize_ff - ff->frag_off, fragmax);
10708 frag =
10709 GNUNET_malloc (sizeof(struct PendingMessage)
10710 + sizeof(struct TransportFragmentBoxMessage) + fragsize);
10712 "3 created pm %p from pm %p storing vl %p from pm %p\n",
10713 frag,
10714 ff,
10715 pm->vl,
10716 pm);
10718 frag->vl = pm->vl;
10719 frag->frag_parent = ff;
10720 frag->timeout = pm->timeout;
10721 frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
10722 frag->pmt = PMT_FRAGMENT_BOX;
10723 msg = (char *) &frag[1];
10724 tfb.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT);
10725 tfb.header.size =
10726 htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
10727 pa = prepare_pending_acknowledgement (queue, dvh, frag);
10728 tfb.ack_uuid = pa->ack_uuid;
10729 tfb.msg_uuid = pm->msg_uuid;
10730 tfb.frag_off = htons (ff->frag_off + xoff);
10731 tfb.msg_size = htons (pm->bytes_msg);
10732 memcpy (msg, &tfb, sizeof(tfb));
10733 memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
10735 ff->tail_frag, frag);
10736 ff->frag_off += fragsize;
10737 ff = frag;
10738 }
10739
10740 /* Move head to the tail and return it */
10744 ff);
10748 ff);
10749
10750 return ff;
10751}

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

10770{
10772 struct PendingAcknowledgement *pa;
10773 struct PendingMessage *bpm;
10774 char *msg;
10775
10776 if ((PMT_CORE != pm->pmt) && (PMT_DV_BOX != pm->pmt))
10777 return pm; /* already fragmented or reliability boxed, or control message:
10778 do nothing */
10779 if (NULL != pm->bpm)
10780 return pm->bpm; /* already computed earlier: do nothing */
10781 // TODO I guess we do not need this assertion. We might have a DLL with
10782 // fragments, because the MTU changed, and we do not need to fragment anymore.
10783 // But we should keep the fragments until message was completed, because
10784 // the MTU might change again.
10785 // GNUNET_assert (NULL == pm->head_frag);
10786 if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
10787 {
10788 /* failed hard */
10789 GNUNET_break (0);
10791 return NULL;
10792 }
10793
10795
10796 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
10797 + pm->bytes_msg);
10799 "4 created pm %p storing vl %p from pm %p\n",
10800 bpm,
10801 pm->vl,
10802 pm);
10804 bpm->vl = pm->vl;
10805 bpm->frag_parent = pm;
10806 // Why was this needed?
10807 // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
10808 bpm->timeout = pm->timeout;
10810 bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
10812 rbox.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX);
10813 rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
10814 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
10815
10816 rbox.ack_uuid = pa->ack_uuid;
10817 msg = (char *) &bpm[1];
10818 memcpy (msg, &rbox, sizeof(rbox));
10819 memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
10820 pm->bpm = bpm;
10822 "Preparing reliability box for message <%" PRIu64
10823 "> of size %d (%d) to %s on queue %s\n",
10824 pm->logging_uuid,
10825 pm->bytes_msg,
10826 ntohs (((const struct GNUNET_MessageHeader *) &pm[1])->size),
10827 GNUNET_i2s (&pm->vl->target),
10828 queue->address);
10829 return bpm;
10830}

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

10836{
10837 struct VirtualLink *vl = pm->vl;
10838 struct PendingMessage *pos;
10839
10840 /* re-insert sort in neighbour list */
10844 pm);
10845 pos = vl->pending_msg_tail;
10846 while ((NULL != pos) &&
10848 pos = pos->prev_vl;
10852 pos,
10853 pm);
10854}

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

10859{
10860 struct PendingMessage *pos;
10862
10863 pos = pm->head_frag;
10864 while (NULL != pos)
10865 {
10866 if (pos->frags_in_flight_round == pm->frags_in_flight_round ||
10867 GNUNET_NO == check_next_attempt_tree (pos, root))
10869 else
10870 {
10872 break;
10873 }
10874 pos = pos->next_frag;
10875 }
10876
10877 return frags_in_flight;
10878}

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

10883{
10884 struct PendingMessage *pos;
10885
10886 pos = pm->head_frag;
10887 while (NULL != pos)
10888 {
10889 pos->frags_in_flight_round = pm->frags_in_flight_round;
10891 pos = pos->next_frag;
10892 }
10893}

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

10907{
10908 if (NULL == pm->frag_parent)
10909 {
10910 pm->next_attempt = next_attempt;
10912 "Next attempt for message <%" PRIu64 "> set to %" PRIu64 "\n",
10913 pm->logging_uuid,
10914 next_attempt.abs_value_us);
10915 reorder_root_pm (pm, next_attempt);
10916 }
10917 else if ((PMT_RELIABILITY_BOX == pm->pmt) || (PMT_DV_BOX == pm->pmt))// || (PMT_FRAGMENT_BOX == pm->pmt))
10918 {
10919 struct PendingMessage *root = pm->frag_parent;
10920
10921 while (NULL != root->frag_parent)
10922 root = root->frag_parent;
10924 "Next attempt for root message <%" PRIu64 "> set to %s\n",
10925 root->logging_uuid,
10927 root->next_attempt = next_attempt;
10929 }
10930 else
10931 {
10932 struct PendingMessage *root = pm->frag_parent;
10933
10934 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
10935 root = root->frag_parent;
10936
10938 "frag_count next attempt %u\n",
10939 root->frag_count);
10940
10941 if (GNUNET_NO == root->frags_in_flight)
10942 {
10943 root->next_attempt = next_attempt;
10945 root->frags_in_flight_round++;
10947 "Next attempt for fragmented message <%" PRIu64 "> (<%" PRIu64
10948 ">)set to %" PRIu64 "\n",
10949 pm->logging_uuid,
10950 root->logging_uuid,
10952 }
10953
10954 pm->next_attempt = root->next_attempt;
10955 pm->frags_in_flight_round = root->frags_in_flight_round;
10957
10958 if (root->bytes_msg == root->frag_off)
10959 root->frags_in_flight = check_next_attempt_tree (root, root);
10960 else
10962
10963 if (GNUNET_NO == root->frags_in_flight)
10964 {
10966 "We have no fragments in flight for message %" PRIu64
10967 ", reorder root! Next attempt is %" PRIu64 "\n",
10968 root->logging_uuid,
10970 if (PMT_DV_BOX == root->pmt)
10971 root = root->frag_parent;
10972 reorder_root_pm (root, root->next_attempt);
10973 // root->next_attempt = GNUNET_TIME_UNIT_ZERO_ABS;
10974 }
10975 else
10976 {
10977 double factor = ((double) root->frag_count - 1)
10978 / (double) root->frag_count;
10979 struct GNUNET_TIME_Relative s1;
10980 struct GNUNET_TIME_Relative s2;
10981 struct GNUNET_TIME_Relative plus_mean =
10984 next_attempt);
10985
10987 "frag_count %u after factor\n",
10988 root->frag_count);
10990 factor);
10991 s2 = GNUNET_TIME_relative_divide (plus,
10992 root->frag_count);
10993 plus_mean = GNUNET_TIME_relative_add (s1, s2);
10996 "We have fragments in flight for message %" PRIu64
10997 ", do not reorder root! Actual next attempt %" PRIu64 "\n",
10998 root->logging_uuid,
11000 }
11001 }
11002}

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

11074{
11075 struct GNUNET_TIME_Absolute now;
11076
11077 now = GNUNET_TIME_absolute_get ();
11078 sc->to_early = GNUNET_NO;
11079 sc->frags_in_flight = GNUNET_NO;
11080 for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
11081 pos = pos->next_vl)
11082 {
11083 size_t real_overhead = overhead;
11084 int frag;
11085 int relb;
11086
11087 if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
11088 {
11090 "DV messages must not be DV-routed to next hop!\n");
11091 continue; /* DV messages must not be DV-routed to next hop! */
11092 }
11093 if (pos->next_attempt.abs_value_us > now.abs_value_us)
11094 {
11095 if (GNUNET_YES == pos->frags_in_flight)
11096 {
11097 sc->frags_in_flight = GNUNET_YES;
11099 "Fragments in flight for message %" PRIu64 "\n",
11100 pos->logging_uuid);
11101 }
11102 else
11103 {
11105 "Maybe too early, because message are sorted by next_attempt, if there are no fragments in flight.Checked message %"
11106 PRIu64 "\n",
11107 pos->logging_uuid);
11108 sc->to_early = GNUNET_YES;
11109 sc->to_early_retry_delay = GNUNET_TIME_absolute_get_remaining (
11110 pos->next_attempt);
11111 continue;
11112 }
11113 // break; /* too early for all messages, they are sorted by next_attempt */
11114 }
11115 if (NULL != pos->qe)
11116 {
11118 "not eligible\n");
11119 continue; /* not eligible */
11120 }
11121 sc->consideration_counter++;
11122 /* determine if we have to fragment, if so add fragmentation
11123 overhead! */
11125 "check %" PRIu64 " for sc->best\n",
11126 pos->logging_uuid);
11127 frag = GNUNET_NO;
11128 if (((0 != queue->mtu) &&
11129 (pos->bytes_msg + real_overhead > queue->mtu)) ||
11130 (pos->bytes_msg > UINT16_MAX - sizeof(struct
11132 ||
11133 (NULL != pos->head_frag /* fragments already exist, should
11134 respect that even if MTU is UINT16_MAX for
11135 this queue */))
11136 {
11138 "fragment msg with size %u, realoverhead is %lu\n",
11139 pos->bytes_msg,
11140 real_overhead);
11141 frag = GNUNET_YES;
11142 if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
11143 {
11144 /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
11145 header without the ACK UUID when using a *reliable* channel! */
11146 }
11147 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11148 }
11149 /* determine if we have to reliability-box, if so add reliability box
11150 overhead */
11151 relb = GNUNET_NO;
11152 if ((GNUNET_NO == frag) &&
11153 (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
11154 (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
11155 {
11156 real_overhead += sizeof(struct TransportReliabilityBoxMessage);
11157
11158 if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu))
11159 {
11160 frag = GNUNET_YES;
11161 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11162 }
11163 else
11164 {
11165 relb = GNUNET_YES;
11166 }
11168 "Create reliability box of msg with size %u, realoverhead is %lu %u %u %u\n",
11169 pos->bytes_msg,
11170 real_overhead,
11171 queue->mtu,
11172 frag,
11173 relb);
11174 }
11175
11176 /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
11177 message would beat it! */
11178 if (GNUNET_NO == sc->frags_in_flight && NULL != sc->best)
11179 {
11180 /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
11181 OPTIMIZE-ME: This is a heuristic, which so far has NOT been
11182 experimentally validated. There may be some huge potential for
11183 improvement here. Also, we right now only compare how well the
11184 given message fits _this_ queue, and do not consider how well other
11185 queues might suit the message. Taking other queues into consideration
11186 may further improve the result, but could also be expensive
11187 in terms of CPU time. */
11188 long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
11189 long long pm_score = frag * 40 + relb * 20 + real_overhead;
11190 long long time_delta =
11191 (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
11192 / 1000LL;
11193
11194 /* "time_delta" considers which message has been 'ready' for transmission
11195 for longer, if a message has a preference for low latency, increase
11196 the weight of the time_delta by 10x if it is favorable for that message */
11197 if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11198 (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
11199 time_delta *= 10; /* increase weight (always, both are low latency) */
11200 else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11201 (time_delta > 0))
11202 time_delta *= 10; /* increase weight, favors 'pos', which is low latency */
11203 else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11204 (time_delta < 0))
11205 time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */
11206 if (0 != queue->mtu)
11207 {
11208 /* Grant bonus if we are below MTU, larger bonus the closer we will
11209 be to the MTU */
11210 if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
11211 sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
11212 if (queue->mtu > real_overhead + pos->bytes_msg)
11213 pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
11214 }
11215 if (sc_score + time_delta > pm_score)
11216 {
11218 "sc_score of %" PRIu64 " larger, keep sc->best %" PRIu64
11219 "\n",
11220 pos->logging_uuid,
11221 sc->best->logging_uuid);
11222 continue; /* sc_score larger, keep sc->best */
11223 }
11224 }
11225 sc->best = pos;
11226 sc->dvh = dvh;
11227 sc->frag = frag;
11228 sc->relb = relb;
11229 sc->real_overhead = real_overhead;
11230 }
11231}

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

11249{
11250 struct PendingMessageScoreContext *sc = cls;
11251 struct PendingMessage *pm = sc->best;
11252 struct PendingMessage *bpm;
11253 uint16_t bsize = ntohs (hdr->size);
11254
11255 GNUNET_assert (NULL == pm->bpm);
11256 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
11258 "5 created pm %p storing vl %p from pm %p\n",
11259 bpm,
11260 pm->vl,
11261 pm);
11263 bpm->pmt = PMT_DV_BOX;
11264 bpm->vl = pm->vl;
11265 bpm->timeout = pm->timeout;
11266 bpm->bytes_msg = bsize;
11267 bpm->frag_parent = pm;
11270 "Creating DV Box %" PRIu64 " for original message %" PRIu64
11271 " (next hop is %s)\n",
11273 pm->logging_uuid,
11274 GNUNET_i2s (&next_hop->pid));
11275 memcpy (&bpm[1], hdr, bsize);
11276 pm->bpm = bpm;
11277}

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

11554{
11555 struct TransportClient *tc = cls;
11556
11557 if (CT_COMMUNICATOR != tc->type)
11558 {
11559 GNUNET_break (0);
11561 return;
11562 }
11563 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11564 queue = queue->next_client)
11565 {
11566 struct Neighbour *neighbour = queue->neighbour;
11567
11568 if ((ntohl (dqm->qid) != queue->qid) ||
11569 (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
11570 continue;
11572 "Dropped queue %s to peer %s\n",
11573 queue->address,
11574 GNUNET_i2s (&neighbour->pid));
11575 free_queue (queue);
11577 return;
11578 }
11579 GNUNET_break (0);
11581}

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

11684{
11685 struct TransportClient *tc = cls;
11686 struct QueueEntry *qe;
11687
11688 if (CT_COMMUNICATOR != tc->type)
11689 {
11690 GNUNET_break (0);
11692 return;
11693 }
11694
11695 /* find our queue entry matching the ACK */
11696 qe = NULL;
11698 "Looking for queue for PID %s\n",
11699 GNUNET_i2s (&sma->receiver));
11700 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11701 queue = queue->next_client)
11702 {
11703 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
11704 continue;
11706 "Found PID %s\n",
11707 GNUNET_i2s (&queue->neighbour->pid));
11708
11709
11710 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
11711 qep = qep->next)
11712 {
11713 if (qep->mid != GNUNET_ntohll (sma->mid) || queue->qid != ntohl (
11714 sma->qid))
11715 continue;
11717 "QueueEntry MID: %" PRIu64 " on queue QID: %u, Ack MID: %"
11718 PRIu64 " Ack QID %u\n",
11719 qep->mid,
11720 queue->qid,
11721 GNUNET_ntohll (sma->mid),
11722 ntohl (sma->qid));
11723 qe = qep;
11724 if ((NULL != qe->pm) && (qe->pm->qe != qe))
11726 "For pending message %" PRIu64 " we had retransmissions.\n",
11727 qe->pm->logging_uuid);
11728 break;
11729 }
11730 }
11731 if (NULL == qe)
11732 {
11734 "No QueueEntry found for Ack MID %" PRIu64 " QID: %u\n",
11735 GNUNET_ntohll (sma->mid),
11736 ntohl (sma->qid));
11737 // TODO I guess this can happen, if the Ack from the peer comes before the Ack from the queue.
11738 // Update: Maybe QueueEntry was accidentally freed during freeing PendingMessage.
11739 /* this should never happen */
11740 // GNUNET_break (0);
11741 // GNUNET_SERVICE_client_drop (tc->client);
11743 return;
11744 }
11747}

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

11758{
11760}

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

11776{
11777 struct TransportClient *tc = cls;
11778 struct Neighbour *neighbour = value;
11779
11780 GNUNET_assert (CT_MONITOR == tc->type);
11781 for (struct Queue *q = neighbour->queue_head; NULL != q;
11782 q = q->next_neighbour)
11783 {
11784 struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
11785 .cs = q->cs,
11786 .num_msg_pending = q->num_msg_pending,
11787 .num_bytes_pending = q->num_bytes_pending };
11788
11789 notify_monitor (tc, pid, q->address, q->nt, &me);
11790 }
11791 return GNUNET_OK;
11792}

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

11804{
11805 struct TransportClient *tc = cls;
11806
11807 if (CT_NONE != tc->type)
11808 {
11809 GNUNET_break (0);
11811 return;
11812 }
11813 tc->type = CT_MONITOR;
11814 tc->details.monitor.peer = start->peer;
11815 tc->details.monitor.one_shot = ntohl (start->one_shot);
11819}

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

11831{
11832 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
11833 {
11834 if (CT_COMMUNICATOR != tc->type)
11835 continue;
11836 if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
11837 return tc;
11838 }
11839 GNUNET_log (
11841 "Someone suggested use of communicator for `%s', but we do not have such a communicator!\n",
11842 prefix);
11843 return NULL;
11844}

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

12059{
12060 struct QueueQualityContext *ctx = cls;
12061 struct Neighbour *n = value;
12062 int do_inc;
12063
12064 (void) pid;
12065 do_inc = GNUNET_NO;
12066 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
12067 {
12068 ctx->num_queues++;
12069 if (0 == ctx->k--)
12070 ctx->q = q;
12071 /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
12072 statistics and consider those as well here? */
12073 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
12074 do_inc = GNUNET_YES;
12075 }
12076 if (GNUNET_YES == do_inc)
12077 ctx->quality_count++;
12078 return GNUNET_OK;
12079}

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

12167{
12168 struct LearnLaunchEntry *lle;
12169 struct QueueQualityContext qqc;
12170 struct TransportDVLearnMessage dvl;
12171 const struct GNUNET_PeerIdentity *my_identity;
12172
12173 (void) cls;
12174 dvlearn_task = NULL;
12176 return; /* lost all connectivity, cannot do learning */
12177 qqc.quality_count = 0;
12178 qqc.num_queues = 0;
12182 &qqc);
12183 if (qqc.quality_count > DV_LEARN_QUALITY_THRESHOLD)
12184 {
12185 struct GNUNET_TIME_Relative delay;
12186 unsigned int factor;
12187
12188 /* scale our retries by how far we are above the threshold */
12189 factor = qqc.quality_count / DV_LEARN_QUALITY_THRESHOLD;
12192 "At connection quality %u, will launch DV learn in %s\n",
12193 qqc.quality_count,
12196 return;
12197 }
12198 /* remove old entries in #dvlearn_map if it has grown too big */
12199 while (MAX_DV_LEARN_PENDING <=
12201 {
12202 lle = lle_tail;
12205 &lle->challenge.value,
12206 lle));
12208 GNUNET_free (lle);
12209 }
12210 /* setup data structure for learning */
12211 lle = GNUNET_new (struct LearnLaunchEntry);
12213 sizeof(lle->challenge));
12215 "Starting launch DV learn with challenge %s\n",
12216 GNUNET_sh2s (&lle->challenge.value));
12221 &lle->challenge.value,
12222 lle,
12226 dvl.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN);
12227 dvl.header.size = htons (sizeof(dvl));
12228 dvl.num_hops = htons (0);
12229 dvl.bidirectional = htons (0);
12230 dvl.non_network_delay = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO);
12231 dvl.monotonic_time =
12233 // We will set the below again later
12234 memset (&dvl.init_sig, 0, sizeof dvl.init_sig);
12235 dvl.challenge = lle->challenge;
12236 dvl.initiator = *my_identity;
12237 {
12238 struct DvInitPS dvip = {
12239 .purpose.purpose = htonl (
12241 .purpose.size = htonl (sizeof(dvip)),
12242 .monotonic_time = dvl.monotonic_time,
12243 .challenge = lle->challenge
12244 };
12245 struct SignDvInitCls *sign_dv_init_cls;
12246
12247 sign_dv_init_cls = GNUNET_new (struct SignDvInitCls);
12248 sign_dv_init_cls->dvl = dvl;
12249 sign_dv_init_cls->lle = lle;
12250 sign_dv_init_cls->qqc = qqc;
12251 sign_dv_init_cls->pr = GNUNET_new (struct PilsRequest);
12254 sign_dv_init_cls->pr);
12255 sign_dv_init_cls->pr->op =
12257 &dvip.purpose,
12259 sign_dv_init_cls);
12260 }
12261}

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_random_block(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN, GNUNET_new, GNUNET_PILS_get_identity(), GNUNET_PILS_sign_by_peer_identity(), GNUNET_SCHEDULER_add_delayed(), GNUNET_sh2s(), GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR, GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_absolute_get_monotonic(), GNUNET_TIME_absolute_hton(), GNUNET_TIME_relative_hton(), GNUNET_TIME_relative_multiply(), GNUNET_TIME_UNIT_ZERO, GNUNET_YES, GST_cfg, TransportDVLearnMessage::header, TransportDVLearnMessage::init_sig, TransportDVLearnMessage::initiator, QueueQualityContext::k, SignDvInitCls::lle, lle_head, lle_tail, MAX_DV_LEARN_PENDING, TransportDVLearnMessage::monotonic_time, my_identity, 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 12107 of file gnunet-service-transport.c.

12110{
12111 const struct GNUNET_PeerIdentity *my_identity;
12112 struct SignDvInitCls *sign_dv_init_cls = cls;
12113 struct TransportDVLearnMessage dvl = sign_dv_init_cls->dvl;
12114 struct LearnLaunchEntry *lle = sign_dv_init_cls->lle;
12115 struct QueueQualityContext qqc = sign_dv_init_cls->qqc;
12116
12119
12120 sign_dv_init_cls->pr->op = NULL;
12123 sign_dv_init_cls->pr);
12124 GNUNET_free (sign_dv_init_cls->pr);
12125
12126 dvl.init_sig = *sig;
12127 dvl.initiator = *my_identity;
12128 dvl.challenge = lle->challenge;
12129
12130 qqc.quality_count = 0;
12132 qqc.num_queues = 0;
12133 qqc.q = NULL;
12136 &qqc);
12137 GNUNET_assert (NULL != qqc.q);
12138
12139 /* Do this as close to transmission time as possible! */
12141
12142 queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
12143 /* reschedule this job, randomizing the time it runs (but no
12144 actual backoff!) */
12145 if (NULL != dvlearn_task)
12150 NULL);
12151}

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_random_u32(), GNUNET_free, GNUNET_PILS_get_identity(), GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_cancel(), GNUNET_TIME_absolute_get(), GNUNET_TIME_randomize(), TransportDVLearnMessage::init_sig, TransportDVLearnMessage::initiator, QueueQualityContext::k, LearnLaunchEntry::launch_time, SignDvInitCls::lle, my_identity, neighbours, QueueQualityContext::num_queues, PilsRequest::op, pils, 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 12299 of file gnunet-service-transport.c.

12302{
12303 struct Queue *q = cls;
12304 struct ValidationState *vs = value;
12305 char *address_without_port_vs;
12306 char *address_without_port_q;
12307 int success = GNUNET_YES;
12308
12309 // TODO Check if this is really necessary.
12310 address_without_port_vs = get_address_without_port (vs->address);
12311 address_without_port_q = get_address_without_port (q->address);
12312
12314 "Check validation request pending for `%s' at `%s'/`%s' (vs)/(q)\n",
12315 GNUNET_i2s (pid),
12316 address_without_port_vs,
12317 address_without_port_q);
12318 (void) pid;
12319 if ((GNUNET_YES == vs->awaiting_queue) &&
12320 (0 == strcmp (address_without_port_vs, address_without_port_q)))
12321 {
12322
12323 vs->awaiting_queue = GNUNET_NO;
12325 success = GNUNET_NO;
12326 }
12327
12328 GNUNET_free (address_without_port_vs);
12329 GNUNET_free (address_without_port_q);
12330 return success;
12331}

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

12346{
12347 struct Neighbour *n = cls;
12348 struct GNUNET_TIME_AbsoluteNBO *mtbe;
12349
12350 (void) emsg;
12351 if (NULL == record)
12352 {
12353 /* we're done with #neighbour_dv_monotime_cb() invocations,
12354 continue normal processing */
12355 n->get = NULL;
12357 return;
12358 }
12359 if (0 == record->value_size)
12360 {
12362 GNUNET_break (0);
12363 return;
12364 }
12365 mtbe = record->value;
12370}

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

12377{
12378 struct Queue *queue = cls;
12379 struct sockaddr_in v4;
12380 const char *slash;
12381 char *address_uri;
12382 char *prefix;
12383 char *uri_without_port;
12384 char *address_uri_without_port;
12385
12386 slash = strrchr (uri, '/');
12387 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
12388 GNUNET_assert (NULL != slash);
12389 slash++;
12390 GNUNET_asprintf (&address_uri,
12391 "%s-%s",
12392 prefix,
12393 slash);
12394
12396 "1 not global natted_address %u %s %s %s\n",
12397 queue->is_global_natted,
12398 uri,
12399 queue->address,
12400 slash);
12401
12402 uri_without_port = get_address_without_port (address_uri);
12403 if (1 != inet_pton (AF_INET, uri_without_port, &v4.sin_addr))
12404 {
12406 GNUNET_free (address_uri);
12407 GNUNET_free (uri_without_port);
12408 return;
12409 }
12410
12412 "2 not global natted_address %u %s %s\n",
12413 queue->is_global_natted,
12414 uri,
12415 queue->address);
12416
12417 if (GNUNET_NO == queue->is_global_natted)
12418 {
12420 GNUNET_free (address_uri);
12421 GNUNET_free (uri_without_port);
12422 return;
12423 }
12424
12426 "3 not global natted_address %u %s %s\n",
12427 queue->is_global_natted,
12428 uri,
12429 queue->address);
12430
12431 if (0 == strcmp (uri_without_port, address_uri))
12432 {
12434 GNUNET_free (address_uri);
12435 GNUNET_free (uri_without_port);
12436 return;
12437 }
12438
12440 "4 not global natted_address %u %s %s\n",
12441 queue->is_global_natted,
12442 uri,
12443 queue->address);
12444
12445 address_uri_without_port = get_address_without_port (queue->address);
12446 if (0 == strcmp (uri_without_port, address_uri_without_port))
12447 {
12448 queue->is_global_natted = GNUNET_NO;
12449 }
12450
12452 "not global natted_address %u %s %s %s %s %s %u\n",
12453 queue->is_global_natted,
12454 uri,
12455 queue->address,
12456 uri_without_port,
12457 address_uri_without_port,
12458 prefix,
12459 GNUNET_NO);
12461 GNUNET_free (address_uri);
12462 GNUNET_free (address_uri_without_port);
12463 GNUNET_free (uri_without_port);
12464}

References get_address_without_port(), GNUNET_asprintf(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_NO, GNUNET_strndup, prefix, queue(), and uri.

Referenced by check_for_global_natted().

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

◆ contains_address()

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

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

12485{
12486 struct TransportGlobalNattedAddressClosure *tgna_cls = cls;
12487 struct TransportGlobalNattedAddress *tgna = value;
12488 char *addr = (char *) &tgna[1];
12489
12491 "Checking tgna %p with addr %s and length %u compare length %lu\n",
12492 tgna,
12493 addr,
12494 ntohl (tgna->address_length),
12495 strlen (tgna_cls->addr));
12496 if (strlen (tgna_cls->addr) == ntohl (tgna->address_length)
12497 && 0 == strncmp (addr, tgna_cls->addr, ntohl (tgna->address_length)))
12498 {
12499 tgna_cls->tgna = tgna;
12500 return GNUNET_NO;
12501 }
12502 return GNUNET_YES;
12503}

References TransportGlobalNattedAddressClosure::addr, TransportGlobalNattedAddress::address_length, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_YES, TransportGlobalNattedAddressClosure::tgna, and value.

Referenced by check_for_global_natted().

Here is the caller graph for this function:

◆ check_for_global_natted_error_cb()

static void check_for_global_natted_error_cb ( void *  cls)
static

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

12508{
12510 "Error in PEERSTORE monitoring for checking global natted\n");
12511}

References GNUNET_ERROR_TYPE_WARNING, and GNUNET_log.

Referenced by handle_add_queue_message().

Here is the caller graph for this function:

◆ check_for_global_natted_sync_cb()

static void check_for_global_natted_sync_cb ( void *  cls)
static

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

12516{
12518 "Done with initial PEERSTORE iteration during monitoring for checking global natted\n");
12519}

References GNUNET_ERROR_TYPE_WARNING, and GNUNET_log.

Referenced by handle_add_queue_message().

Here is the caller graph for this function:

◆ check_for_global_natted()

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

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

12526{
12527 struct Queue *queue = cls;
12528 struct Neighbour *neighbour = queue->neighbour;
12530 struct GNUNET_MessageHeader *hello;
12532 size_t address_len_without_port;
12533
12534 if (NULL != emsg)
12535 {
12537 "Got failure from PEERSTORE: %s\n",
12538 emsg);
12539 return;
12540 }
12541 if (0 == record->value_size)
12542 {
12544 GNUNET_break (0);
12545 return;
12546 }
12547 queue->is_global_natted = GNUNET_YES;
12548 hello = record->value;
12549 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
12551 "before not global natted %u\n",
12552 queue->is_global_natted);
12555 queue);
12557 "after not global natted %u\n",
12558 queue->is_global_natted);
12559 GNUNET_HELLO_parser_free (parser);
12560
12561 tgna_cls.addr = get_address_without_port (queue->address);
12562 address_len_without_port = strlen (tgna_cls.addr);
12563 /*{
12564 char buf[address_len_without_port + 1];
12565
12566 GNUNET_memcpy (&buf, addr, address_len_without_port);
12567 buf[address_len_without_port] = '\0';
12568 GNUNET_free (addr);
12569 GNUNET_memcpy (tgna_cls.addr, buf, address_len_without_port + 1);
12570 }*/
12571 tgna_cls.tgna = NULL;
12573 &neighbour->pid,
12575 &tgna_cls);
12576 if (NULL != tgna_cls.tgna)
12578 " tgna_cls.tgna tgna %p %lu %u %u\n",
12579 tgna_cls.tgna,
12580 neighbour->size_of_global_addresses,
12581 ntohl (tgna_cls.tgna->address_length),
12582 neighbour->number_of_addresses);
12583 if (NULL == tgna_cls.tgna && GNUNET_YES == queue->is_global_natted)
12584 {
12585 struct TransportGlobalNattedAddress *tgna;
12586
12587 tgna = GNUNET_malloc (sizeof (struct TransportGlobalNattedAddress)
12588 + address_len_without_port);
12589 tgna->address_length = htonl (address_len_without_port);
12590 GNUNET_memcpy (&tgna[1], tgna_cls.addr, address_len_without_port);
12592 &neighbour->pid,
12593 tgna,
12595 neighbour->number_of_addresses++;
12596 neighbour->size_of_global_addresses += address_len_without_port + 1;
12598 "Created tgna %p with address %s and length %lu\n",
12599 tgna,
12600 tgna_cls.addr,
12601 address_len_without_port + 1);
12602 }
12603 else if (NULL != tgna_cls.tgna && GNUNET_NO == queue->is_global_natted)
12604 {
12606 &neighbour->pid,
12607 tgna_cls.tgna);
12608 GNUNET_assert (neighbour->size_of_global_addresses >= ntohl (tgna_cls.tgna->
12610 );
12611 neighbour->size_of_global_addresses -= ntohl (tgna_cls.tgna->address_length)
12612 ;
12613 GNUNET_assert (0 < neighbour->number_of_addresses);
12614 neighbour->number_of_addresses--;
12616 "removed tgna %p\n",
12617 tgna_cls.tgna);
12618 GNUNET_free (tgna_cls.tgna);
12619 }
12621 GNUNET_free (tgna_cls.addr);
12622}

References TransportGlobalNattedAddressClosure::addr, TransportGlobalNattedAddress::address_length, contains_address(), get_address_without_port(), GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE, GNUNET_CONTAINER_multipeermap_get_multiple(), GNUNET_CONTAINER_multipeermap_put(), GNUNET_CONTAINER_multipeermap_remove(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_HELLO_parser_free(), GNUNET_HELLO_parser_from_msg(), GNUNET_HELLO_parser_iterate(), GNUNET_log, GNUNET_malloc, GNUNET_memcpy, GNUNET_NO, GNUNET_PEERSTORE_monitor_next(), GNUNET_YES, iterate_address_and_compare_cb(), Neighbour::natted_addresses, Neighbour::number_of_addresses, Neighbour::pid, queue(), record(), Neighbour::size_of_global_addresses, and TransportGlobalNattedAddressClosure::tgna.

Referenced by handle_add_queue_message().

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

◆ handle_add_queue_message()

static void handle_add_queue_message ( void *  cls,
const struct GNUNET_TRANSPORT_AddQueueMessage aqm 
)
static

New queue became available.

Process the request.

Parameters
clsthe client
aqmthe send message that was sent

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

12634{
12635 struct TransportClient *tc = cls;
12636 struct Queue *queue;
12637 struct Neighbour *neighbour;
12638 const char *addr;
12639 uint16_t addr_len;
12640
12641 if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
12642 {
12643 /* MTU so small as to be useless for transmissions,
12644 required for #fragment_message()! */
12645 GNUNET_break_op (0);
12647 return;
12648 }
12649 /* This may simply be a queue update */
12650 for (queue = tc->details.communicator.queue_head;
12651 NULL != queue;
12652 queue = queue->next_client)
12653 {
12654 if (queue->qid != ntohl (aqm->qid))
12655 continue;
12656 break;
12657 }
12658
12659 if (NULL != queue)
12660 {
12661 neighbour = queue->neighbour;
12662 }
12663 else
12664 {
12665 struct GNUNET_TIME_Absolute validated_until = GNUNET_TIME_UNIT_ZERO_ABS;
12666
12667 neighbour = lookup_neighbour (&aqm->receiver);
12668 if (NULL == neighbour)
12669 {
12670 neighbour = GNUNET_new (struct Neighbour);
12672 GNUNET_YES);
12673 neighbour->pid = aqm->receiver;
12676 neighbours,
12677 &neighbour->pid,
12678 neighbour,
12680 neighbour->get =
12682 "transport",
12683 &neighbour->pid,
12686 neighbour);
12687 }
12688 addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
12689 addr = (const char *) &aqm[1];
12691 "New queue %s to %s available with QID %u and q_len %" PRIu64
12692 " and mtu %u\n",
12693 addr,
12694 GNUNET_i2s (&aqm->receiver),
12695 ntohl (aqm->qid),
12696 GNUNET_ntohll (aqm->q_len),
12697 ntohl (aqm->mtu));
12698 queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
12699 queue->tc = tc;
12700 for (struct Queue *q = neighbour->queue_head; NULL != q; q = q->
12701 next_neighbour)
12702 validated_until = GNUNET_TIME_absolute_max (validated_until, q->
12703 validated_until);
12704 if (0 == GNUNET_TIME_absolute_get_remaining (validated_until).rel_value_us)
12705 {
12707 "New queue with QID %u inherit validated until\n",
12708 ntohl (aqm->qid));
12709 queue->validated_until = validated_until;
12710 }
12711 queue->address = (const char *) &queue[1];
12712 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
12713 queue->qid = ntohl (aqm->qid);
12714 queue->neighbour = neighbour;
12716 queue->unlimited_length = GNUNET_YES;
12717 queue->q_capacity = GNUNET_ntohll (aqm->q_len);
12718 memcpy (&queue[1], addr, addr_len);
12719 /* notify monitors about new queue */
12720 {
12721 struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
12722
12723 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
12724 }
12726 neighbour->queue_head,
12727 neighbour->queue_tail,
12728 queue);
12730 tc->details.communicator.queue_head,
12731 tc->details.communicator.queue_tail,
12732 queue);
12733
12734 }
12735 queue->mtu = ntohl (aqm->mtu);
12736 queue->nt = ntohl (aqm->nt);
12737 queue->cs = ntohl (aqm->cs);
12738 queue->idle = GNUNET_YES;
12739
12740 {
12741 struct sockaddr_in v4;
12742 char *addr_without = get_address_without_port (queue->address);
12743 if (1 == inet_pton (AF_INET, addr_without, &v4.sin_addr))
12744 {
12746 "start not global natted\n");
12748 GNUNET_YES,
12749 "peerstore",
12750 &neighbour->pid,
12752 &
12754 NULL,
12755 &
12757 NULL,
12759 queue);
12760 }
12761 GNUNET_free (addr_without);
12762 }
12763 /* check if valdiations are waiting for the queue */
12765 &aqm->receiver))
12766 {
12769 &aqm->
12770 receiver,
12771 &
12773 queue))
12774 start_address_validation (&aqm->receiver, queue->address);
12775 }
12776 else
12777 start_address_validation (&aqm->receiver, queue->address);
12778 /* look for traffic for this queue */
12779 // TODO Check whether this makes any sense at all.
12780 /*schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
12781 queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);*/
12782 /* might be our first queue, try launching DV learning */
12783 if (NULL == dvlearn_task)
12786}

References check_for_global_natted(), check_for_global_natted_error_cb(), check_for_global_natted_sync_cb(), check_validation_request_pending(), GNUNET_TRANSPORT_AddQueueMessage::cs, dvlearn_task, Neighbour::get, get_address_without_port(), GNUNET_assert, GNUNET_break_op, GNUNET_CONTAINER_MDLL_insert, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multipeermap_contains(), GNUNET_CONTAINER_multipeermap_create(), GNUNET_CONTAINER_multipeermap_get_multiple(), GNUNET_CONTAINER_multipeermap_put(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_malloc, GNUNET_new, GNUNET_ntohll(), GNUNET_OK, GNUNET_PEERSTORE_HELLO_KEY, GNUNET_PEERSTORE_iteration_start(), GNUNET_PEERSTORE_monitor_start(), GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME, GNUNET_SCHEDULER_add_now(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_SYSERR, GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_absolute_max(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED, GNUNET_YES, GST_cfg, GNUNET_TRANSPORT_AddQueueMessage::header, lookup_neighbour(), me, GNUNET_TRANSPORT_AddQueueMessage::mtu, Neighbour::natted_addresses, neighbour_dv_monotime_cb(), neighbours, notify_monitors(), GNUNET_TRANSPORT_AddQueueMessage::nt, peerstore, Neighbour::pid, q, GNUNET_TRANSPORT_AddQueueMessage::q_len, GNUNET_TRANSPORT_AddQueueMessage::qid, queue(), Neighbour::queue_head, Neighbour::queue_tail, receiver(), GNUNET_TRANSPORT_AddQueueMessage::receiver, GNUNET_TIME_Relative::rel_value_us, GNUNET_MessageHeader::size, start_address_validation(), start_dv_learn(), tc, and validation_map.

Here is the call graph for this function:

◆ handle_update_queue_message()

static void handle_update_queue_message ( void *  cls,
const struct GNUNET_TRANSPORT_UpdateQueueMessage msg 
)
static

Handle updates to queues.

Parameters
clsthe transport client.
msgMessage struct.

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

12799{
12800 struct TransportClient *tc = cls;
12801 struct Queue *target_queue = NULL;
12802
12804 "Received queue update message for %u with q_len %llu and mtu %u\n",
12805 ntohl (msg->qid),
12806 (unsigned long long) GNUNET_ntohll (msg->q_len),
12807 ntohl (msg->mtu));
12808 for (target_queue = tc->details.communicator.queue_head;
12809 NULL != target_queue;
12810 target_queue = target_queue->next_client)
12811 {
12812 if (ntohl (msg->qid) == target_queue->qid)
12813 break;
12814 }
12815 if (NULL == target_queue)
12816 {
12818 "Queue to update no longer exists! Discarding update.\n");
12819 return;
12820 }
12821
12822 target_queue->nt = msg->nt;
12823 target_queue->mtu = ntohl (msg->mtu);
12824 target_queue->cs = msg->cs;
12825 target_queue->priority = ntohl (msg->priority);
12826 /* The update message indicates how many messages
12827 * the queue should be able to handle.
12828 */
12830 target_queue->unlimited_length = GNUNET_YES;
12831 else
12832 target_queue->unlimited_length = GNUNET_NO;
12833 target_queue->q_capacity += GNUNET_ntohll (msg->q_len);
12834 if (0 < target_queue->q_capacity)
12836 target_queue,
12839}

References Queue::cs, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_NO, GNUNET_ntohll(), GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_SERVICE_client_continue(), GNUNET_TIME_UNIT_ZERO, GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED, GNUNET_YES, msg, Queue::mtu, Queue::next_client, Queue::nt, Queue::priority, Queue::q_capacity, Queue::qid, schedule_transmit_on_queue(), tc, and Queue::unlimited_length.

Here is the call graph for this function:

◆ handle_queue_create_ok()

static void handle_queue_create_ok ( void *  cls,
const struct GNUNET_TRANSPORT_CreateQueueResponse cqr 
)
static

Communicator tells us that our request to create a queue "worked", that is setting up the queue is now in process.

Parameters
clsthe struct TransportClient
cqrconfirmation message

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

12852{
12853 struct TransportClient *tc = cls;
12854
12855 if (CT_COMMUNICATOR != tc->type)
12856 {
12857 GNUNET_break (0);
12859 return;
12860 }
12862 "# Suggestions succeeded at communicator",
12863 1,
12864 GNUNET_NO);
12866 "Request #%u for communicator to create queue succeeded\n",
12867 (unsigned int) ntohs (cqr->request_id));
12869}

References CT_COMMUNICATOR, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_STATISTICS_update(), GST_stats, GNUNET_TRANSPORT_CreateQueueResponse::request_id, and tc.

Here is the call graph for this function:

◆ handle_queue_create_fail()

static void handle_queue_create_fail ( void *  cls,
const struct GNUNET_TRANSPORT_CreateQueueResponse cqr 
)
static

Communicator tells us that our request to create a queue failed.

This usually indicates that the provided address is simply invalid or that the communicator's resources are exhausted.

Parameters
clsthe struct TransportClient
cqrfailure message

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

12884{
12885 struct TransportClient *tc = cls;
12886
12887 if (CT_COMMUNICATOR != tc->type)
12888 {
12889 GNUNET_break (0);
12891 return;
12892 }
12894 "Request #%u for communicator to create queue failed\n",
12895 (unsigned int) ntohl (cqr->request_id));
12897 "# Suggestions failed in queue creation at communicator",
12898 1,
12899 GNUNET_NO);
12901}

References CT_COMMUNICATOR, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_STATISTICS_update(), GST_stats, GNUNET_TRANSPORT_CreateQueueResponse::request_id, and tc.

Here is the call graph for this function:

◆ handle_suggest_cancel()

static void handle_suggest_cancel ( void *  cls,
const struct ExpressPreferenceMessage msg 
)
static

We have received a struct ExpressPreferenceMessage from an application client.

Parameters
clshandle to the client
msgthe start message

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

12913{
12914 struct TransportClient *tc = cls;
12915 struct PeerRequest *pr;
12916
12917 if (CT_APPLICATION != tc->type)
12918 {
12919 GNUNET_break (0);
12921 return;
12922 }
12923 pr = GNUNET_CONTAINER_multipeermap_get (tc->details.application.requests,
12924 &msg->peer);
12925 if (NULL == pr)
12926 {
12927 GNUNET_break (0);
12929 return;
12930 }
12931 (void) stop_peer_request (tc, &pr->pid, pr);
12933}

References CT_APPLICATION, GNUNET_break, GNUNET_CONTAINER_multipeermap_get(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), msg, PeerRequest::pr, stop_peer_request(), and tc.

Here is the call graph for this function:

◆ hello_for_client_cb()

static void hello_for_client_cb ( void *  cls,
const struct GNUNET_PeerIdentity pid,
const char *  uri 
)
static

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

12940{
12941 struct Queue *q;
12942 int pfx_len;
12943 const char *eou;
12944 char *address;
12945 (void) cls;
12946
12947 eou = strstr (uri,
12948 "://");
12949 pfx_len = eou - uri;
12950 eou += 3;
12952 "%.*s-%s",
12953 pfx_len,
12954 uri,
12955 eou);
12956
12958 "hello for client %s\n",
12959 address);
12960
12961 q = find_queue (pid, address);
12962 if (NULL == q)
12963 {
12965 }
12966 else
12969}

References address, find_queue(), GNUNET_asprintf(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, pid, q, start_address_validation(), suggest_to_connect(), and uri.

Referenced by handle_hello_for_client().

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

◆ handle_hello_for_client()

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

Function called by PEERSTORE for each matching record.

Parameters
clsclosure, a struct PeerRequest
recordpeerstore record information
emsgerror message, or NULL if no errors

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

12983{
12984 const struct GNUNET_PeerIdentity *my_identity;
12985 struct PeerRequest *pr = cls;
12987 struct GNUNET_MessageHeader *hello;
12988
12989 if (NULL != emsg)
12990 {
12992 "Got failure from PEERSTORE: %s\n",
12993 emsg);
12994 return;
12995 }
12997 if (NULL == my_identity)
12998 {
13000 "No identity given yet!\n");
13001 return;
13002 }
13003 hello = record->value;
13004 if (0 == GNUNET_memcmp (&record->peer, my_identity))
13005 {
13007 return;
13008 }
13009 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
13010 if (NULL == parser)
13011 {
13013 "HELLO cannot be parsed!\n");
13014 return;
13015 }
13017 "HELLO for `%s' could be parsed, iterating addresses...!\n",
13021 NULL);
13022 GNUNET_HELLO_parser_free (parser);
13023}

References GNUNET_ERROR_TYPE_WARNING, GNUNET_HELLO_parser_free(), GNUNET_HELLO_parser_from_msg(), GNUNET_HELLO_parser_get_id(), GNUNET_HELLO_parser_iterate(), GNUNET_i2s(), GNUNET_log, GNUNET_memcmp, GNUNET_PEERSTORE_monitor_next(), GNUNET_PILS_get_identity(), hello_for_client_cb(), my_identity, PeerRequest::nc, pils, PeerRequest::pr, and record().

Referenced by handle_suggest().

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

◆ hello_for_client_error_cb()

static void hello_for_client_error_cb ( void *  cls)
static

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

13028{
13030 "Error in PEERSTORE monitoring\n");
13031}

References GNUNET_ERROR_TYPE_WARNING, and GNUNET_log.

Referenced by handle_suggest().

Here is the caller graph for this function:

◆ hello_for_client_sync_cb()

static void hello_for_client_sync_cb ( void *  cls)
static

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

13036{
13038 "Done with initial PEERSTORE iteration during monitoring\n");
13039}

References GNUNET_ERROR_TYPE_WARNING, and GNUNET_log.

Referenced by handle_suggest().

Here is the caller graph for this function:

◆ handle_suggest()

static void handle_suggest ( void *  cls,
const struct ExpressPreferenceMessage msg 
)
static

We have received a struct ExpressPreferenceMessage from an application client.

Parameters
clshandle to the client
msgthe start message

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

13051{
13052 struct TransportClient *tc = cls;
13053 const struct GNUNET_PeerIdentity *my_identity;
13054 struct PeerRequest *pr;
13055
13056 if (CT_NONE == tc->type)
13057 {
13058 tc->type = CT_APPLICATION;
13059 tc->details.application.requests =
13061 }
13062 if (CT_APPLICATION != tc->type)
13063 {
13064 GNUNET_break (0);
13066 return;
13067 }
13069 if (NULL == my_identity)
13070 {
13072 "Still waiting for own identity!\n");
13074 return;
13075 }
13077 "Client suggested we talk to %s with preference %d at rate %u\n",
13078 GNUNET_i2s (&msg->peer),
13079 (int) ntohl (msg->pk),
13080 (int) ntohl (msg->bw.value__));
13081 if (0 == GNUNET_memcmp (my_identity, &msg->peer))
13082 {
13084 "Client suggested connection to ourselves, ignoring...\n");
13086 return;
13087 }
13088 pr = GNUNET_new (struct PeerRequest);
13089 pr->tc = tc;
13090 pr->pid = msg->peer;
13091 pr->bw = msg->bw;
13092 pr->pk = ntohl (msg->pk);
13094 tc->details.application.requests,
13095 &pr->pid,
13096 pr,
13098 {
13099 GNUNET_break (0);
13100 GNUNET_free (pr);
13102 return;
13103 }
13104 pr->nc =
13106 GNUNET_YES,
13107 "peerstore",
13108 NULL,
13111 NULL,
13113 NULL,
13115 pr);
13117}

References CT_APPLICATION, CT_NONE, GNUNET_break, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multipeermap_create(), GNUNET_CONTAINER_multipeermap_put(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_memcmp, GNUNET_new, GNUNET_PEERSTORE_HELLO_KEY, GNUNET_PEERSTORE_monitor_start(), GNUNET_PILS_get_identity(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_YES, GST_cfg, handle_hello_for_client(), hello_for_client_error_cb(), hello_for_client_sync_cb(), msg, my_identity, pils, PeerRequest::pr, and tc.

Here is the call graph for this function:

◆ check_request_hello_validation()

static int check_request_hello_validation ( void *  cls,
const struct RequestHelloValidationMessage m 
)
static

Check GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION messages.

Parameters
clsa struct TransportClient *
mmessage to verify
Returns
GNUNET_OK on success

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

13131{
13132 (void) cls;
13134 return GNUNET_OK;
13135}

References GNUNET_MQ_check_zero_termination, GNUNET_OK, and m.

◆ handle_request_hello_validation()

static void handle_request_hello_validation ( void *  cls,
const struct RequestHelloValidationMessage m 
)
static

A client encountered an address of another peer.

Consider validating it, and if validation succeeds, persist it to PEERSTORE.

Parameters
clsa struct TransportClient *
mmessage to verify

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

13148{
13149 struct TransportClient *tc = cls;
13150 struct Queue *q;
13151
13152 q = find_queue (&m->peer, (const char *) &m[1]);
13153 if (NULL == q)
13154 {
13155 suggest_to_connect (&m->peer, (const char *) &m[1]);
13156 }
13157 else
13158 start_address_validation (&m->peer, (const char *) &m[1]);
13160}

References find_queue(), GNUNET_SERVICE_client_continue(), m, q, start_address_validation(), suggest_to_connect(), and tc.

Here is the call graph for this function:

◆ free_neighbour_cb()

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

Free neighbour entry.

Parameters
clsNULL
pidunused
valuea struct Neighbour
Returns
GNUNET_OK (always)

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

13175{
13176 struct Neighbour *neighbour = value;
13177
13178 (void) cls;
13179 (void) pid;
13180 GNUNET_break (0); // should this ever happen?
13181 free_neighbour (neighbour, GNUNET_YES);
13182
13183 return GNUNET_OK;
13184}

References free_neighbour(), GNUNET_break, GNUNET_OK, GNUNET_YES, pid, and value.

Referenced by do_shutdown().

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

◆ free_dv_routes_cb()

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

Free DV route entry.

Parameters
clsNULL
pidunused
valuea struct DistanceVector
Returns
GNUNET_OK (always)

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

13199{
13200 struct DistanceVector *dv = value;
13201
13202 (void) cls;
13203 (void) pid;
13204 free_dv_route (dv);
13205
13206 return GNUNET_OK;
13207}

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

Referenced by do_shutdown().

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

◆ free_validation_state_cb()

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

Free validation state.

Parameters
clsNULL
pidunused
valuea struct ValidationState
Returns
GNUNET_OK (always)

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

13222{
13223 struct ValidationState *vs = value;
13224
13225 (void) cls;
13226 (void) pid;
13228 return GNUNET_OK;
13229}

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

Referenced by do_shutdown().

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

◆ free_pending_ack_cb()

static int free_pending_ack_cb ( void *  cls,
const struct GNUNET_Uuid key,
void *  value 
)
static

Free pending acknowledgement.

Parameters
clsNULL
keyunused
valuea struct PendingAcknowledgement
Returns
GNUNET_OK (always)

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

13242{
13243 struct PendingAcknowledgement *pa = value;
13244
13245 (void) cls;
13246 (void) key;
13248 return GNUNET_OK;
13249}

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

Referenced by do_shutdown().

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

◆ free_ack_cummulator_cb()

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

Free acknowledgement cummulator.

Parameters
clsNULL
pidunused
valuea struct AcknowledgementCummulator
Returns
GNUNET_OK (always)

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

13264{
13265 struct AcknowledgementCummulator *ac = value;
13266
13267 (void) cls;
13268 (void) pid;
13270 GNUNET_free (ac);
13271 return GNUNET_OK;
13272}

References GNUNET_free, GNUNET_OK, GNUNET_SCHEDULER_cancel(), pid, AcknowledgementCummulator::task, and value.

Referenced by do_shutdown().

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

◆ get_client_type_name()

static const char * get_client_type_name ( enum ClientType  type)
static

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

13399{
13400 switch (type)
13401 {
13402 case CT_CORE:
13403 return "CORE";
13404 case CT_MONITOR:
13405 return "MONITOR";
13406 case CT_COMMUNICATOR:
13407 return "COMMUNICATOR";
13408 case CT_APPLICATION:
13409 return "APPLICATION";
13410 default:
13411 return "UNKNOWN";
13412 }
13413}

References CT_APPLICATION, CT_COMMUNICATOR, CT_CORE, CT_MONITOR, and type.

Referenced by shutdown_task().

Here is the caller graph for this function:

◆ shutdown_task()

static void shutdown_task ( void *  cls)
static

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

13418{
13420
13422 "Shutdown task executed\n");
13423 if (NULL != clients_head)
13424 {
13425 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
13426 {
13428 "Client still connected: %s\n",
13429 get_client_type_name (tc->type));
13430 }
13431 }
13432 else
13433 do_shutdown (cls);
13434
13435}

References clients_head, do_shutdown, get_client_type_name(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_YES, in_shutdown, and tc.

Here is the call graph for this function:

◆ update_hello_from_pid_change_cb()

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

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

13445{
13446 struct UpdateHelloFromPidCtx *pc = cls;
13447
13448 if (GNUNET_OK != success)
13449 {
13451 "Failed to store our new hello with peerstore\n");
13452 }
13453 GNUNET_free (pc);
13455 "Stored our new hello with peerstore\n");
13456}

References GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_OK, and pc.

Referenced by pils_pid_change_cb().

Here is the caller graph for this function:

◆ print_address_list()

void print_address_list ( void *  cls,
const struct GNUNET_PeerIdentity pid,
const char *  uri 
)

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

13463{
13465 "%s\n", uri);
13466}

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, and uri.

Referenced by pils_pid_change_cb().

Here is the caller graph for this function:

◆ pils_pid_change_cb()

static void pils_pid_change_cb ( void *  cls,
const struct GNUNET_HELLO_Parser parser,
const struct GNUNET_HashCode hash 
)
static

Callback called when pils service updates us with our new peer identity.

Parameters
clsclosure given to GNUNET_PILS_connect
parserthe new HELLO from which the PID can be extracted
hashThe hash of addresses the peer id is based on. This hash is also returned by #GNUNET_PILS_feed_address.

FIXME we may want to have a sanity check here that verifies that our address list in the builder is the same as the one in the parser (and hence derived from the correct set). If it is NOT, then it is very likely that PILS is behind and will send another update shortly. In this case, we may want to hold off and not generate the new HELLO.

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

13482{
13483 const struct GNUNET_PeerIdentity *my_identity;
13484 struct GNUNET_MQ_Envelope *env;
13485 const struct GNUNET_MessageHeader *msg;
13486 struct UpdateHelloFromPidCtx *sc;
13487 struct GNUNET_HELLO_Builder *nbuilder;
13488 struct GNUNET_PeerIdentity npid;
13489
13492
13493 if (NULL == GST_my_hello)
13496 "My current identity is `%s'\n",
13508 nbuilder = GNUNET_HELLO_builder_from_parser (parser,
13509 &npid);
13510 if (GNUNET_NO ==
13512 {
13514 "New PID from PILS is derived from address list inconsistent with ours. Ignoring...\n");
13516 "Proposed address list:\n");
13519 "Current address list:\n");
13521 GNUNET_HELLO_builder_free (nbuilder);
13522 return;
13523 }
13525 GST_my_hello = nbuilder;
13527 "My new identity is `%s'\n",
13533 msg,
13535 sc);
13536 GNUNET_free (env);
13537}

References env, GNUNET_assert, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_HELLO_builder_address_list_cmp(), GNUNET_HELLO_builder_free(), GNUNET_HELLO_builder_from_parser(), GNUNET_HELLO_builder_iterate(), GNUNET_HELLO_builder_new(), GNUNET_HELLO_parser_to_env(), GNUNET_i2s_full(), GNUNET_log, GNUNET_MQ_env_get_msg(), GNUNET_new, GNUNET_NO, GNUNET_PEERSTORE_hello_add(), GNUNET_PILS_get_identity(), GST_my_hello, msg, my_identity, peerstore, pils, print_address_list(), sc, and update_hello_from_pid_change_cb().

Referenced by run().

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

◆ run()

static void run ( void *  cls,
const struct GNUNET_CONFIGURATION_Handle c,
struct GNUNET_SERVICE_Handle service 
)
static

Initiate transport service.

Parameters
clsclosure
cconfiguration to use
servicethe initialized service

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

13551{
13552 (void) cls;
13553 (void) service;
13554 /* setup globals */
13557 GST_cfg = c;
13565 GNUNET_YES);
13570 // TODO check for all uses of GST_my_hello that it is not used uninitialized
13572 "transport",
13573 "USE_BURST_NAT");
13574 if (GNUNET_SYSERR == use_burst)
13576 "Could not configure burst nat use. Default to no.\n");
13582 "transport",
13583 0,
13584 0,
13585 NULL,
13586 0,
13587 NULL,
13588 NULL,
13589 NULL);
13590 if (NULL == peerstore)
13591 {
13592 GNUNET_break (0);
13594 return;
13595 }
13598 NULL); // FIXME we need to wait for
13599 // our first peer id before
13600 // we can start the service
13601 // completely - PILS in turn
13602 // waits for the first
13603 // addresses from the
13604 // communicators in order to
13605 // be able to generate a
13606 // peer id
13607 if (NULL == pils)
13608 {
13609 GNUNET_break (0);
13611 return;
13612 }
13613}

References ack_cummulators, backtalkers, dv_routes, dvlearn_map, GNUNET_break, GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CONTAINER_heap_create(), GNUNET_CONTAINER_HEAP_ORDER_MIN, GNUNET_CONTAINER_multihashmap_create(), GNUNET_CONTAINER_multipeermap_create(), GNUNET_CONTAINER_multishortmap_create(), GNUNET_CONTAINER_multiuuidmap_create(), GNUNET_ERROR_TYPE_WARNING, GNUNET_HELLO_builder_new(), GNUNET_log, GNUNET_NAT_register(), GNUNET_NO, GNUNET_PEERSTORE_connect(), GNUNET_PILS_connect(), GNUNET_SCHEDULER_add_shutdown(), GNUNET_SCHEDULER_shutdown(), GNUNET_STATISTICS_create(), GNUNET_SYSERR, GNUNET_TIME_absolute_get_monotonic(), GNUNET_YES, GST_cfg, GST_my_hello, GST_stats, hello_mono_time, in_shutdown, links, MAX_DV_LEARN_PENDING, neighbours, nh, peerstore, pending_acks, pils, pils_pid_change_cb(), revalidation_map, service, shutdown_task, use_burst, validation_heap, and validation_map.

Here is the call graph for this function:

◆ GNUNET_SERVICE_MAIN()

GNUNET_SERVICE_MAIN ( GNUNET_OS_project_data_gnunet()  ,
"transport"  ,
GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN  ,
run,
client_connect_cb,
client_disconnect_cb,
NULL  ,
GNUNET_MQ_hd_fixed_size(suggest, GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST, struct ExpressPreferenceMessage, NULL)  ,
GNUNET_MQ_hd_fixed_size(suggest_cancel, GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST_CANCEL, struct ExpressPreferenceMessage, NULL)  ,
GNUNET_MQ_hd_var_size(request_hello_validation, GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION, struct RequestHelloValidationMessage, NULL)  ,
GNUNET_MQ_hd_fixed_size(client_start, GNUNET_MESSAGE_TYPE_TRANSPORT_START, struct StartMessage, NULL)  ,
GNUNET_MQ_hd_var_size(client_send, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, struct OutboundMessage, NULL)  ,
GNUNET_MQ_hd_fixed_size(client_recv_ok, GNUNET_MESSAGE_TYPE_TRANSPORT_RECV_OK, struct RecvOkMessage, NULL)  ,
GNUNET_MQ_hd_var_size(communicator_available, GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR, struct GNUNET_TRANSPORT_CommunicatorAvailableMessage, NULL)  ,
GNUNET_MQ_hd_var_size(communicator_backchannel, GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL, struct GNUNET_TRANSPORT_CommunicatorBackchannel, NULL)  ,
GNUNET_MQ_hd_var_size(add_address, GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS, struct GNUNET_TRANSPORT_AddAddressMessage, NULL)  ,
GNUNET_MQ_hd_fixed_size(del_address, GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS, struct GNUNET_TRANSPORT_DelAddressMessage, NULL)  ,
GNUNET_MQ_hd_var_size(incoming_msg, GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG, struct GNUNET_TRANSPORT_IncomingMessage, NULL)  ,
GNUNET_MQ_hd_fixed_size(queue_create_ok, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK, struct GNUNET_TRANSPORT_CreateQueueResponse, NULL)  ,
GNUNET_MQ_hd_fixed_size(queue_create_fail, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL, struct GNUNET_TRANSPORT_CreateQueueResponse, NULL)  ,
GNUNET_MQ_hd_var_size(add_queue_message, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP, struct GNUNET_TRANSPORT_AddQueueMessage, NULL)  ,
GNUNET_MQ_hd_fixed_size(update_queue_message, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_UPDATE, struct GNUNET_TRANSPORT_UpdateQueueMessage, NULL)  ,
GNUNET_MQ_hd_fixed_size(del_queue_message, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN, struct GNUNET_TRANSPORT_DelQueueMessage, NULL)  ,
GNUNET_MQ_hd_fixed_size(send_message_ack, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK, struct GNUNET_TRANSPORT_SendMessageToAck, NULL)  ,
GNUNET_MQ_hd_fixed_size(burst_finished, GNUNET_MESSAGE_TYPE_TRANSPORT_BURST_FINISHED, struct GNUNET_TRANSPORT_BurstFinished, NULL)  ,
GNUNET_MQ_hd_fixed_size(monitor_start, GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START, struct GNUNET_TRANSPORT_MonitorStart, NULL)  ,
GNUNET_MQ_handler_end()   
)

Define "main" method using service macro.

Variable Documentation

◆ ring_buffer

struct RingBufferEntry* ring_buffer[RING_BUFFER_SIZE]
static

Ring buffer for a CORE message we did not deliver to CORE, because of missing virtual link to sender.

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

Referenced by handle_raw_message(), and send_msg_from_cache().

◆ ring_buffer_head

unsigned int ring_buffer_head
static

Head of the ring buffer.

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

Referenced by handle_raw_message(), and send_msg_from_cache().

◆ is_ring_buffer_full

unsigned int is_ring_buffer_full
static

Is the ring buffer filled up to RING_BUFFER_SIZE.

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

Referenced by handle_raw_message(), and send_msg_from_cache().

◆ ring_buffer_dv

struct PendingMessage* ring_buffer_dv[RING_BUFFER_SIZE]
static

Ring buffer for a forwarded DVBox message we did not deliver to the next hop, because of missing virtual link that hop.

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

Referenced by forward_dv_box(), and send_msg_from_cache().

◆ ring_buffer_dv_head

unsigned int ring_buffer_dv_head
static

Head of the ring buffer.

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

Referenced by forward_dv_box(), and send_msg_from_cache().

◆ is_ring_buffer_dv_full

unsigned int is_ring_buffer_dv_full
static

Is the ring buffer filled up to RING_BUFFER_SIZE.

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

Referenced by forward_dv_box(), and send_msg_from_cache().

◆ clients_head

◆ clients_tail

struct TransportClient* clients_tail
static

Tail of linked list of all clients to this service.

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

Referenced by client_connect_cb(), and client_disconnect_cb().

◆ GST_stats

◆ GST_cfg

◆ GST_my_hello

◆ neighbours

struct GNUNET_CONTAINER_MultiPeerMap* neighbours
static

Map from PIDs to struct Neighbour entries.

A peer is a neighbour if we have an MQ to it from some communicator.

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

Referenced by do_shutdown(), free_neighbour(), handle_add_queue_message(), handle_dv_learn(), handle_monitor_start(), lookup_neighbour(), run(), sign_dv_init_cb(), and start_dv_learn().

◆ backtalkers

struct GNUNET_CONTAINER_MultiPeerMap* backtalkers
static

Map from PIDs to struct Backtalker entries.

A peer is a backtalker if it recently send us backchannel messages.

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

Referenced by decaps_dv_box_cb(), do_shutdown(), free_backtalker(), and run().

◆ ack_cummulators

struct GNUNET_CONTAINER_MultiPeerMap* ack_cummulators
static

Map from PIDs to struct AcknowledgementCummulators.

Here we track the cumulative ACKs for transmission.

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

Referenced by cummulative_ack(), destroy_ack_cummulator(), do_shutdown(), and run().

◆ pending_acks

struct GNUNET_CONTAINER_MultiUuidmap* pending_acks
static

Map of pending acknowledgements, mapping struct AcknowledgementUUID to a struct PendingAcknowledgement.

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

Referenced by do_shutdown(), free_pending_acknowledgement(), handle_reliability_ack(), prepare_pending_acknowledgement(), and run().

◆ dv_routes

struct GNUNET_CONTAINER_MultiPeerMap* dv_routes
static

Map from PIDs to struct DistanceVector entries describing known paths to the peer.

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

Referenced by do_shutdown(), free_dv_route(), learn_dv_path(), route_control_message_without_fc(), and run().

◆ validation_map

struct GNUNET_CONTAINER_MultiPeerMap* validation_map
static

Map from PIDs to struct ValidationState entries describing addresses we are aware of and their validity state.

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

Referenced by do_shutdown(), free_validation_state(), handle_add_queue_message(), handle_validation_response(), run(), and start_address_validation().

◆ revalidation_map

struct GNUNET_CONTAINER_MultiHashMap* revalidation_map
static

Map from addresses to struct ValidationState entries describing addresses we are aware of and their validity state.

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

Referenced by do_shutdown(), free_validation_state(), handle_validation_response(), run(), and validation_transmit_on_queue().

◆ links

◆ dvlearn_map

struct GNUNET_CONTAINER_MultiShortmap* dvlearn_map
static

Map from challenges to struct LearnLaunchEntry values.

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

Referenced by do_shutdown(), run(), and start_dv_learn().

◆ lle_head

struct LearnLaunchEntry* lle_head = NULL
static

Head of a DLL sorted by launch time.

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

Referenced by do_shutdown(), and start_dv_learn().

◆ lle_tail

struct LearnLaunchEntry* lle_tail = NULL
static

Tail of a DLL sorted by launch time.

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

Referenced by do_shutdown(), and start_dv_learn().

◆ validation_heap

struct GNUNET_CONTAINER_Heap* validation_heap
static

MIN Heap sorted by "next_challenge" to struct ValidationState entries sorting addresses we are aware of by when we should next try to (re)validate (or expire) them.

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

Referenced by do_shutdown(), run(), update_next_challenge_time(), and validation_start_cb().

◆ nh

struct GNUNET_NAT_Handle* nh

Handle for connect to the NAT service.

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

Referenced by do_shutdown(), handle_flow_control(), and run().

◆ peerstore

◆ pils

◆ pils_requests_head

◆ pils_requests_tail

◆ dvlearn_task

struct GNUNET_SCHEDULER_Task* dvlearn_task
static

Task run to initiate DV learning.

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

Referenced by do_shutdown(), handle_add_queue_message(), sign_dv_init_cb(), and start_dv_learn().

◆ validation_task

struct GNUNET_SCHEDULER_Task* validation_task
static

Task to run address validation.

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

Referenced by do_shutdown(), update_next_challenge_time(), and validation_start_cb().

◆ pils_feed_task

struct GNUNET_SCHEDULER_Task* pils_feed_task
static

Task to feed addresses to PILS.

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

Referenced by do_shutdown(), feed_addresses_to_pils(), handle_add_address(), and handle_del_address().

◆ ir_head

struct IncomingRequest* ir_head
static

List of incoming connections where we are trying to get a connection back established.

Length kept in ir_total.

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

Referenced by do_shutdown(), free_incoming_request(), and sign_t_validation_cb().

◆ ir_tail

struct IncomingRequest* ir_tail
static

Tail of DLL starting at ir_head.

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

Referenced by free_incoming_request(), and sign_t_validation_cb().

◆ ir_total

unsigned int ir_total
static

Length of the DLL starting at ir_head.

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

Referenced by do_shutdown(), free_incoming_request(), and sign_t_validation_cb().

◆ logging_uuid_gen

unsigned long long logging_uuid_gen
static

Generator of logging_uuid in struct PendingMessage.

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

Referenced by extract_box_cb(), forward_dv_box(), fragment_message(), handle_client_send(), and reliability_box_message().

◆ burst_running

enum GNUNET_GenericReturnValue burst_running
static

Is there a burst running?

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

Referenced by burst_timeout(), do_shutdown(), handle_burst_finished(), queue_burst(), and start_burst().

◆ hello_mono_time

struct GNUNET_TIME_Absolute hello_mono_time
static

Monotonic time we use for HELLOs generated at this time.

TODO: we should increase this value from time to time (i.e. whenever a struct AddressListEntry actually expires), but IF we do this, we must also update all (remaining) addresses in the PEERSTORE at that time! (So for now only increased when the peer is restarted, which hopefully roughly matches whenever our addresses change.)

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

Referenced by run(), and store_pi().

◆ in_shutdown

int in_shutdown
static

Indication if we have received a shutdown signal and are in the process of cleaning up.

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

Referenced by client_disconnect_cb(), run(), and shutdown_task().

◆ burst_task

struct GNUNET_SCHEDULER_Task* burst_task
static

The task to start the burst.

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

Referenced by do_shutdown(), queue_burst(), and start_burst().

◆ burst_timeout_task

struct GNUNET_SCHEDULER_Task* burst_timeout_task

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

Referenced by do_shutdown(), and start_burst().

◆ use_burst

enum GNUNET_GenericReturnValue use_burst

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

Referenced by queue_burst(), and run().