GNUnet 0.26.2-114-g7c6b613e3
 
Loading...
Searching...
No Matches
gnunet-service-transport.c File Reference

main for gnunet-service-transport More...

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

Go to the source code of this file.

Data Structures

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

Macros

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

Typedefs

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

Enumerations

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

Functions

static unsigned int get_age ()
 Get an offset into the transmission history buffer for struct PerformanceData.
 
static void free_incoming_request (struct IncomingRequest *ir)
 Release ir data structure.
 
static void free_pending_acknowledgement (struct PendingAcknowledgement *pa)
 Release pa data structure.
 
static void free_fragment_tree (struct PendingMessage *root)
 Free fragment tree below root, excluding root itself.
 
static void free_pending_message (struct PendingMessage *pm)
 Release memory associated with pm and remove pm from associated data structures.
 
static void free_reassembly_context (struct ReassemblyContext *rc)
 Free rc.
 
static void reassembly_cleanup_task (void *cls)
 Task run to clean up reassembly context of a neighbour that have expired.
 
static int free_reassembly_cb (void *cls, uint32_t key, void *value)
 function called to free_reassembly_context().
 
static void free_virtual_link (struct VirtualLink *vl)
 Free virtual link.
 
static void free_validation_state (struct ValidationState *vs)
 Free validation state.
 
static struct Neighbourlookup_neighbour (const struct GNUNET_PeerIdentity *pid)
 Lookup neighbour for peer pid.
 
static struct VirtualLinklookup_virtual_link (const struct GNUNET_PeerIdentity *pid)
 Lookup virtual link for peer pid.
 
static void free_distance_vector_hop (struct DistanceVectorHop *dvh)
 Free a dvh.
 
static void check_link_down (void *cls)
 Task run to check whether the hops of the cls still are validated, or if we need to core about disconnection.
 
static void cores_send_disconnect_info (const struct GNUNET_PeerIdentity *pid)
 Send message to CORE clients that we lost a connection.
 
static void free_dv_route (struct DistanceVector *dv)
 Free entry in dv_routes.
 
static void notify_monitor (struct TransportClient *tc, const struct GNUNET_PeerIdentity *peer, const char *address, enum GNUNET_NetworkType nt, const struct MonitorEvent *me)
 Notify monitor tc about an event.
 
static void notify_monitors (const struct GNUNET_PeerIdentity *peer, const char *address, enum GNUNET_NetworkType nt, const struct MonitorEvent *me)
 Send information in me about a peer's status with respect to some address to all monitors that care.
 
static void * client_connect_cb (void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
 Called whenever a client connects.
 
static enum GNUNET_GenericReturnValue remove_global_addresses (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 
static void free_neighbour (struct Neighbour *neighbour, enum GNUNET_GenericReturnValue drop_link)
 Release memory used by neighbour.
 
static void core_send_connect_info (struct TransportClient *tc, const struct GNUNET_PeerIdentity *pid)
 Send message to CORE clients that we lost a connection.
 
static void cores_send_connect_info (const struct GNUNET_PeerIdentity *pid)
 Send message to CORE clients that we gained a connection.
 
static void transmit_on_queue (void *cls)
 We believe we are ready to transmit a message on a queue.
 
static unsigned int check_for_queue_with_higher_prio (struct Queue *queue, struct Queue *queue_head)
 Check if the communicator has another queue with higher prio ready for sending.
 
static void schedule_transmit_on_queue (struct GNUNET_TIME_Relative delay, struct Queue *queue, enum GNUNET_SCHEDULER_Priority p)
 Called whenever something changed that might effect when we try to do the next transmission on queue using transmit_on_queue().
 
static void free_queue (struct Queue *queue)
 Free queue.
 
static void free_address_list_entry (struct AddressListEntry *ale)
 Free ale.
 
static int stop_peer_request (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Stop the peer request in value.
 
static void do_shutdown (void *cls)
 Function called when the service shuts down.
 
static void client_disconnect_cb (void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
 Called whenever a client is disconnected.
 
static int notify_client_connect_info (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Iterator telling new CORE client about all existing connections to peers.
 
static void finish_cmc_handling_with_continue (struct CommunicatorMessageContext *cmc, unsigned int free_cmc)
 Send ACK to communicator (if requested) and free cmc.
 
static enum GNUNET_GenericReturnValue resume_communicators (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 
static void handle_client_start (void *cls, const struct StartMessage *start)
 Initialize a "CORE" client.
 
static int check_client_send (void *cls, const struct OutboundMessage *obm)
 Client asked for transmission to a peer.
 
static void client_send_response (struct PendingMessage *pm)
 Send a response to the pm that we have processed a "send" request.
 
static unsigned int pick_random_dv_hops (const struct DistanceVector *dv, enum RouteMessageOptions options, struct DistanceVectorHop **hops_array, unsigned int hops_array_length)
 Pick hops_array_length random DV paths satisfying options.
 
static int check_communicator_available (void *cls, const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
 Communicator started.
 
static void finish_cmc_handling (struct CommunicatorMessageContext *cmc)
 
static void handle_client_recv_ok (void *cls, const struct RecvOkMessage *rom)
 Client confirms that it is done handling message(s) to a particular peer.
 
static void handle_communicator_available (void *cls, const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
 Communicator started.
 
static int check_communicator_backchannel (void *cls, const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
 Communicator requests backchannel transmission.
 
static void sign_dv_cb (void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
 
static void sign_ephemeral (struct DistanceVector *dv)
 Sign ephemeral keys in our dv are current.
 
static void free_queue_entry (struct QueueEntry *qe, struct TransportClient *tc)
 
static void free_timedout_queue_entry (void *cls)
 
static void queue_send_msg (struct Queue *queue, struct PendingMessage *pm, const void *payload, size_t payload_size)
 Send the message payload on queue.
 
static struct GNUNET_TIME_Relative route_via_neighbour (const struct Neighbour *n, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
 Pick a queue of n under constraints options and schedule transmission of hdr.
 
static void dv_setup_key_state_from_km (const struct GNUNET_ShortHashCode *km, const struct GNUNET_ShortHashCode *iv, struct DVKeyState *key)
 Given the key material in km and the initialization vector iv, setup the key material for the backchannel in key.
 
static void dv_hmac (const struct DVKeyState *key, struct GNUNET_HashCode *hmac, const void *data, size_t data_size)
 Do HMAC calculation for backchannel messages over data using key material from key.
 
static void dv_encrypt (struct DVKeyState *key, const void *in, void *dst, size_t in_size)
 Perform backchannel encryption using symmetric secret in key to encrypt data from in to dst.
 
static enum GNUNET_GenericReturnValue dv_decrypt (struct DVKeyState *key, void *out, const void *ciph, size_t out_size)
 Perform backchannel encryption using symmetric secret in key to encrypt data from in to dst.
 
static void dv_key_clean (struct DVKeyState *key)
 Clean up key material in key.
 
static struct GNUNET_TIME_Relative encapsulate_for_dv (struct DistanceVector *dv, unsigned int num_dvhs, struct DistanceVectorHop **dvhs, const struct GNUNET_MessageHeader *hdr, DVMessageHandler use, void *use_cls, enum RouteMessageOptions options, enum GNUNET_GenericReturnValue without_fc)
 Pick a path of dv under constraints options and schedule transmission of hdr.
 
static void send_dv_to_neighbour (void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
 Wrapper around route_via_neighbour() that matches the DVMessageHandler structure.
 
static struct GNUNET_TIME_Relative route_control_message_without_fc (struct VirtualLink *vl, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
 We need to transmit hdr to target.
 
static void consider_sending_fc (void *cls)
 Something changed on the virtual link with respect to flow control.
 
static void task_consider_sending_fc (void *cls)
 Something changed on the virtual link with respect to flow control.
 
static char * get_address_without_port (const char *address)
 Get the IP address without the port number.
 
static enum GNUNET_GenericReturnValue add_global_addresses (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 
static struct GNUNET_TIME_Relative calculate_rtt (struct DistanceVector *dv)
 
static void check_vl_transmission (struct VirtualLink *vl)
 There is a message at the head of the pending messages for vl which may be ready for transmission.
 
static void handle_client_send (void *cls, const struct OutboundMessage *obm)
 Client asked for transmission to a peer.
 
static void handle_communicator_backchannel (void *cls, const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
 Communicator requests backchannel transmission.
 
static int check_add_address (void *cls, const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
 Address of our peer added.
 
static void store_pi (void *cls)
 Ask peerstore to store our address.
 
static void shc_cont (void *cls, int success)
 
static void pils_sign_hello_cb (void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
 Get HELLO signature and create message to store in PEERSTORE.
 
static void peerstore_store_own_cb (void *cls, int success)
 Function called when peerstore is done storing our address.
 
static void pils_sign_addr_cb (void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
 
void pils_sign_address (struct AddressListEntry *ale, struct GNUNET_TIME_Absolute mono_time)
 Build address record by signing raw information with private key of the peer identity.
 
static struct AddressListEntrycreate_address_entry (struct TransportClient *tc, struct GNUNET_TIME_Relative expiration, enum GNUNET_NetworkType nt, const char *address, uint32_t aid, size_t slen)
 
static void feed_addresses_to_pils (void *cls)
 
static void handle_add_address (void *cls, const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
 Address of our peer added.
 
static void handle_del_address (void *cls, const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
 Address of our peer deleted.
 
static void demultiplex_with_cmc (struct CommunicatorMessageContext *cmc)
 Given an inbound message msg from a communicator cmc, demultiplex it based on the type calling the right handler.
 
static void core_env_sent_cb (void *cls)
 Function called when we are done giving a message of a certain size to CORE and should thus decrement the number of bytes of RAM reserved for that peer's MQ.
 
static void finish_handling_raw_message (struct VirtualLink *vl, const struct GNUNET_MessageHeader *mh, struct CommunicatorMessageContext *cmc, unsigned int free_cmc)
 
static void handle_raw_message (void *cls, const struct GNUNET_MessageHeader *mh)
 Communicator gave us an unencapsulated message to pass as-is to CORE.
 
static int check_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
 Communicator gave us a fragment box.
 
static void destroy_ack_cummulator (void *cls)
 Clean up an idle cumulative acknowledgement data structure.
 
static void transmit_cummulative_ack_cb (void *cls)
 Do the transmission of a cumulative acknowledgement now.
 
static void cummulative_ack (const struct GNUNET_PeerIdentity *pid, const struct AcknowledgementUUIDP *ack_uuid, struct GNUNET_TIME_Absolute max_delay)
 Transmit an acknowledgement for ack_uuid to pid delaying transmission by at most ack_delay.
 
static int find_by_message_uuid (void *cls, uint32_t key, void *value)
 Iterator called to find a reassembly context by the message UUID in the multihashmap32.
 
static void handle_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
 Communicator gave us a fragment.
 
static int check_reliability_box (void *cls, const struct TransportReliabilityBoxMessage *rb)
 Communicator gave us a reliability box.
 
static void handle_reliability_box (void *cls, const struct TransportReliabilityBoxMessage *rb)
 Communicator gave us a reliability box.
 
static void update_pd_age (struct PerformanceData *pd, unsigned int age)
 Check if we have advanced to another age since the last time.
 
static void update_performance_data (struct PerformanceData *pd, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
 Update pd based on the latest rtt and the number of bytes that were confirmed to be successfully transmitted.
 
static void update_queue_performance (struct Queue *q, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
 We have successfully transmitted data via q, update metrics.
 
static void update_dvh_performance (struct DistanceVectorHop *dvh, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
 We have successfully transmitted data via dvh, update metrics.
 
static void completed_pending_message (struct PendingMessage *pm)
 We have completed transmission of pm, remove it from the transmission queues (and if it is a fragment, continue up the tree as necessary).
 
static void handle_acknowledged (struct PendingAcknowledgement *pa, struct GNUNET_TIME_Relative ack_delay)
 The pa was acknowledged, process the acknowledgement.
 
static int check_reliability_ack (void *cls, const struct TransportReliabilityAckMessage *ra)
 Communicator gave us a reliability ack.
 
static void handle_reliability_ack (void *cls, const struct TransportReliabilityAckMessage *ra)
 Communicator gave us a reliability ack.
 
static int check_backchannel_encapsulation (void *cls, const struct TransportBackchannelEncapsulationMessage *be)
 Communicator gave us a backchannel encapsulation.
 
static void handle_backchannel_encapsulation (void *cls, const struct TransportBackchannelEncapsulationMessage *be)
 Communicator gave us a backchannel encapsulation.
 
static void path_cleanup_cb (void *cls)
 Task called when we should check if any of the DV paths we have learned to a target are due for garbage collection.
 
static void send_msg_from_cache (struct VirtualLink *vl)
 
static void activate_core_visible_dv_path (struct DistanceVectorHop *hop)
 The hop is a validated path to the respective target peer and we should tell core about it – and schedule a job to revoke the state.
 
static int learn_dv_path (const struct GNUNET_PeerIdentity *path, unsigned int path_len, struct GNUNET_TIME_Relative network_latency, struct GNUNET_TIME_Absolute path_valid_until)
 We have learned a path through the network to some other peer, add it to our DV data structure (returning GNUNET_YES on success).
 
static int check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
 Communicator gave us a DV learn message.
 
static void sign_dhp_cp (void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
 
static void forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop, const struct TransportDVLearnMessage *msg, uint16_t bi_history, uint16_t nhops, const struct DVPathEntryP *hops, struct GNUNET_TIME_Absolute in_time)
 Build and forward a DV learn message to next_hop.
 
static int validate_dv_initiator_signature (struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time, const struct GNUNET_PeerIdentity *init, const struct GNUNET_CRYPTO_ChallengeNonceP *challenge, const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
 Check signature of type GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
 
static int dv_neighbour_selection (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Function called for each neighbour during handle_dv_learn.
 
static int dv_neighbour_transmission (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Function called for each neighbour during handle_dv_learn.
 
static unsigned int calculate_fork_degree (unsigned int hops_taken, unsigned int neighbour_count, unsigned int eligible_count)
 Computes the number of neighbours we should forward a DVInit message to given that it has so far taken hops_taken hops though the network and that the number of neighbours we have in total is neighbour_count, out of which eligible_count are not yet on the path.
 
static void neighbour_store_dvmono_cb (void *cls, int success)
 Function called when peerstore is done storing a DV monotonic time.
 
static struct GNUNET_TIME_Relative get_network_latency (const struct TransportDVLearnMessage *dvl)
 
static void handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
 Communicator gave us a DV learn message.
 
static int check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
 Communicator gave us a DV box.
 
static void forward_dv_box (struct Neighbour *next_hop, struct TransportDVBoxMessage *hdr, uint16_t total_hops, uint16_t num_hops, const struct GNUNET_PeerIdentity *hops, const void *enc_payload, uint16_t enc_payload_size)
 Create a DV Box message and queue it for transmission to next_hop.
 
static void free_backtalker (struct Backtalker *b)
 Free data structures associated with b.
 
static int free_backtalker_cb (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Callback to free backtalker records.
 
static void backtalker_timeout_cb (void *cls)
 Function called when it is time to clean up a backtalker.
 
static void backtalker_monotime_cb (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
 Function called with the monotonic time of a backtalker by PEERSTORE.
 
static void backtalker_monotime_store_cb (void *cls, int success)
 Function called by PEERSTORE when the store operation of a backtalker's monotonic time is complete.
 
static void update_backtalker_monotime (struct Backtalker *b)
 The backtalker b monotonic time changed.
 
static void decaps_dv_box_cb (void *cls, const struct GNUNET_ShortHashCode *km)
 
static void handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
 Communicator gave us a DV box.
 
static int check_incoming_msg (void *cls, const struct GNUNET_TRANSPORT_IncomingMessage *im)
 Client notified us about transmission from a peer.
 
static int check_known_address (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Test if the validation state in value matches the address from cls.
 
static void validation_start_cb (void *cls)
 Task run periodically to validate some address based on validation_heap.
 
static void update_next_challenge_time (struct ValidationState *vs, struct GNUNET_TIME_Absolute new_time)
 Set the time for next_challenge of vs to new_time.
 
static void start_address_validation (const struct GNUNET_PeerIdentity *pid, const char *address)
 Start address validation.
 
static struct Queuefind_queue (const struct GNUNET_PeerIdentity *pid, const char *address)
 Find the queue matching pid and address.
 
static void suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address)
 Signature of a function called with a communicator address of a peer pid that an application wants us to connect to.
 
static void hello_for_incoming_cb (void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
 
static void handle_hello_for_incoming (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
 Function called by PEERSTORE for each matching record.
 
static void hello_for_incoming_error_cb (void *cls)
 
static void hello_for_incoming_sync_cb (void *cls)
 
static void sign_t_validation_cb (void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
 
static void handle_validation_challenge (void *cls, const struct TransportValidationChallengeMessage *tvc)
 Communicator gave us a transport address validation challenge.
 
static int check_known_challenge (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Test if the validation state in value matches the challenge from cls.
 
static void peerstore_store_validation_cb (void *cls, int success)
 Function called when peerstore is done storing a validated address.
 
static void validation_transmit_on_queue (struct Queue *q, struct ValidationState *vs)
 The queue q (which matches the peer and address in vs) is ready for queueing.
 
static void revalidation_start_cb (void *cls)
 
static enum GNUNET_GenericReturnValue revalidate_map_it (void *cls, const struct GNUNET_HashCode *key, void *value)
 
static void handle_validation_response (void *cls, const struct TransportValidationResponseMessage *tvr)
 Communicator gave us a transport address validation response.
 
static void handle_incoming_msg (void *cls, const struct GNUNET_TRANSPORT_IncomingMessage *im)
 Incoming message.
 
static int check_flow_control (void *cls, const struct TransportFlowControlMessage *fc)
 Communicator gave us a transport address validation response.
 
static void iterate_address_start_burst (void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
 
static void check_for_burst_address (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
 
static void burst_timeout (void *cls)
 
static void start_burst (void *cls)
 
static void queue_burst (void *cls)
 
static void handle_flow_control (void *cls, const struct TransportFlowControlMessage *fc)
 Communicator gave us a transport address validation response.
 
static int check_add_queue_message (void *cls, const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
 New queue became available.
 
static void set_pending_message_uuid (struct PendingMessage *pm)
 If necessary, generates the UUID for a pm.
 
static struct PendingAcknowledgementprepare_pending_acknowledgement (struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
 Setup data structure waiting for acknowledgements.
 
static struct PendingMessagefragment_message (struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
 Fragment the given pm to the given mtu.
 
static struct PendingMessagereliability_box_message (struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
 Reliability-box the given pm.
 
static void reorder_root_pm (struct PendingMessage *pm, struct GNUNET_TIME_Absolute next_attempt)
 
static unsigned int check_next_attempt_tree (struct PendingMessage *pm, struct PendingMessage *root)
 
static void harmonize_flight_round (struct PendingMessage *pm)
 
static void update_pm_next_attempt (struct PendingMessage *pm, struct GNUNET_TIME_Absolute next_attempt)
 Change the value of the next_attempt field of pm to next_attempt and re-order pm in the transmission list as required by the new timestamp.
 
static void select_best_pending_from_link (struct PendingMessageScoreContext *sc, struct Queue *queue, struct VirtualLink *vl, struct DistanceVectorHop *dvh, size_t overhead)
 Select the best pending message from vl for transmission via queue.
 
static void extract_box_cb (void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
 Function to call to further operate on the now DV encapsulated message hdr, forwarding it via next_hop under respect of options.
 
static void handle_del_queue_message (void *cls, const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
 Queue to a peer went down.
 
static void handle_send_message_ack (void *cls, const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
 Message was transmitted.
 
static void handle_burst_finished (void *cls, const struct GNUNET_TRANSPORT_BurstFinished *bf)
 The burst finished.
 
static int notify_client_queues (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Iterator telling new MONITOR client about all existing queues to peers.
 
static void handle_monitor_start (void *cls, const struct GNUNET_TRANSPORT_MonitorStart *start)
 Initialize a monitor client.
 
static struct TransportClientlookup_communicator (const char *prefix)
 Find transport client providing communication service for the protocol prefix.
 
static int check_connection_quality (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Check whether any queue to the given neighbour is of a good "quality" and if so, increment the counter.
 
static void start_dv_learn (void *cls)
 Task run when we CONSIDER initiating a DV learn process.
 
static void sign_dv_init_cb (void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
 
static int check_validation_request_pending (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 A new queue has been created, check if any address validation requests have been waiting for it.
 
static void neighbour_dv_monotime_cb (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
 Function called with the monotonic time of a DV initiator by PEERSTORE.
 
static void iterate_address_and_compare_cb (void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
 
static enum GNUNET_GenericReturnValue contains_address (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 
static void check_for_global_natted_error_cb (void *cls)
 
static void check_for_global_natted_sync_cb (void *cls)
 
static void check_for_global_natted (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
 
static void handle_add_queue_message (void *cls, const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
 New queue became available.
 
static void handle_update_queue_message (void *cls, const struct GNUNET_TRANSPORT_UpdateQueueMessage *msg)
 Handle updates to queues.
 
static void handle_queue_create_ok (void *cls, const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
 Communicator tells us that our request to create a queue "worked", that is setting up the queue is now in process.
 
static void handle_queue_create_fail (void *cls, const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
 Communicator tells us that our request to create a queue failed.
 
static void handle_suggest_cancel (void *cls, const struct ExpressPreferenceMessage *msg)
 We have received a struct ExpressPreferenceMessage from an application client.
 
static void hello_for_client_cb (void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
 
static void handle_hello_for_client (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
 Function called by PEERSTORE for each matching record.
 
static void hello_for_client_error_cb (void *cls)
 
static void hello_for_client_sync_cb (void *cls)
 
static void handle_suggest (void *cls, const struct ExpressPreferenceMessage *msg)
 We have received a struct ExpressPreferenceMessage from an application client.
 
static int check_request_hello_validation (void *cls, const struct RequestHelloValidationMessage *m)
 Check GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION messages.
 
static void handle_request_hello_validation (void *cls, const struct RequestHelloValidationMessage *m)
 A client encountered an address of another peer.
 
static int free_neighbour_cb (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Free neighbour entry.
 
static int free_dv_routes_cb (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Free DV route entry.
 
static int free_validation_state_cb (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Free validation state.
 
static int free_pending_ack_cb (void *cls, const struct GNUNET_Uuid *key, void *value)
 Free pending acknowledgement.
 
static int free_ack_cummulator_cb (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 Free acknowledgement cummulator.
 
static 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
821 struct GNUNET_HashCode hmac;
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] =
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
5037 if (0 == (options & RMO_REDUNDANT))
5038 sel2 = candidates; /* picks none! */
5039 else
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
5069struct DVKeyState
5070{
5074 gcry_cipher_hd_t cipher;
5075
5079 struct
5080 {
5085
5089 char aes_key[256 / 8];
5090
5094 char aes_ctr[128 / 8];
5095 } material;
5096};
5097
5098
5107static void
5109 const struct GNUNET_ShortHashCode *iv,
5110 struct DVKeyState *key)
5111{
5112 /* must match what we defive from decapsulated key */
5115 &key->material,
5116 sizeof(key->material),
5117 km,
5118 GNUNET_CRYPTO_kdf_arg_string ("gnunet-transport-dv-key"),
5122 "Deriving backchannel key based on KM %s and IV %s\n",
5123 GNUNET_sh2s (km),
5124 GNUNET_sh2s (iv));
5125 GNUNET_assert (0 == gcry_cipher_open (&key->cipher,
5126 GCRY_CIPHER_AES256 /* low level: go for speed */
5127 ,
5128 GCRY_CIPHER_MODE_CTR,
5129 0 /* flags */));
5130 GNUNET_assert (0 == gcry_cipher_setkey (key->cipher,
5131 &key->material.aes_key,
5132 sizeof(key->material.aes_key)));
5133 gcry_cipher_setctr (key->cipher,
5134 &key->material.aes_ctr,
5135 sizeof(key->material.aes_ctr));
5136}
5137
5138
5148static void
5149dv_hmac (const struct DVKeyState *key,
5150 struct GNUNET_HashCode *hmac,
5151 const void *data,
5152 size_t data_size)
5153{
5154 GNUNET_CRYPTO_hmac (&key->material.hmac_key, data, data_size, hmac);
5155}
5156
5157
5167static void
5168dv_encrypt (struct DVKeyState *key, const void *in, void *dst, size_t in_size)
5169{
5170 GNUNET_assert (0 ==
5171 gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size));
5172}
5173
5174
5185static enum GNUNET_GenericReturnValue
5186dv_decrypt (struct DVKeyState *key,
5187 void *out,
5188 const void *ciph,
5189 size_t out_size)
5190{
5191 return (0 ==
5192 gcry_cipher_decrypt (key->cipher,
5193 out, out_size,
5194 ciph, out_size)) ? GNUNET_OK : GNUNET_SYSERR;
5195}
5196
5197
5203static void
5204dv_key_clean (struct DVKeyState *key)
5205{
5206 gcry_cipher_close (key->cipher);
5207 GNUNET_CRYPTO_zero_keys (&key->material, sizeof(key->material));
5208}
5209
5210
5221typedef void (*DVMessageHandler) (void *cls,
5222 struct Neighbour *next_hop,
5223 const struct GNUNET_MessageHeader *hdr,
5225
5240static struct GNUNET_TIME_Relative
5242 unsigned int num_dvhs,
5243 struct DistanceVectorHop **dvhs,
5244 const struct GNUNET_MessageHeader *hdr,
5245 DVMessageHandler use,
5246 void *use_cls,
5248 enum GNUNET_GenericReturnValue without_fc)
5249{
5250 const struct GNUNET_PeerIdentity *my_identity;
5251 struct TransportDVBoxMessage box_hdr;
5252 struct TransportDVBoxPayloadP payload_hdr;
5253 uint16_t enc_body_size = ntohs (hdr->size);
5254 char enc[sizeof(struct TransportDVBoxPayloadP) + enc_body_size] GNUNET_ALIGN;
5255 struct DVKeyState *key;
5256 struct GNUNET_TIME_Relative rtt;
5257 struct GNUNET_ShortHashCode km;
5258
5261
5262 key = GNUNET_new (struct DVKeyState);
5263 /* Encrypt payload */
5264 box_hdr.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX);
5265 box_hdr.total_hops = htons (0);
5266 box_hdr.without_fc = htons (without_fc);
5267 // update_ephemeral (dv);
5268 if (0 ==
5269 GNUNET_TIME_absolute_get_remaining (dv->ephemeral_validity).rel_value_us)
5270 {
5271 GNUNET_CRYPTO_eddsa_kem_encaps (&dv->target.public_key,
5272 &dv->ephemeral_key,
5273 &km);
5274 dv->km = GNUNET_new (struct GNUNET_ShortHashCode);
5275 GNUNET_memcpy (dv->km, &km, sizeof(struct GNUNET_ShortHashCode));
5276 sign_ephemeral (dv);
5277 }
5278 box_hdr.ephemeral_key = dv->ephemeral_key;
5279 payload_hdr.sender_sig = dv->sender_sig;
5280
5282 &box_hdr.iv,
5283 sizeof(box_hdr.iv));
5284 // We are creating this key, so this must work.
5285 // FIXME: Possibly also add return values here. We are processing
5286 // Input from other peers...
5287 dv_setup_key_state_from_km (dv->km, &box_hdr.iv, key);
5288 payload_hdr.sender = *my_identity;
5289 payload_hdr.monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
5290 dv_encrypt (key, &payload_hdr, enc, sizeof(payload_hdr));
5291 dv_encrypt (key,
5292 hdr,
5293 &enc[sizeof(struct TransportDVBoxPayloadP)],
5294 enc_body_size);
5295 dv_hmac (key, &box_hdr.hmac, enc, sizeof(enc));
5296 dv_key_clean (key);
5298 /* For each selected path, take the pre-computed header and body
5299 and add the path in the middle of the message; then send it. */
5300 for (unsigned int i = 0; i < num_dvhs; i++)
5301 {
5302 struct DistanceVectorHop *dvh = dvhs[i];
5303 unsigned int num_hops = dvh->distance + 1;
5304 char buf[sizeof(struct TransportDVBoxMessage)
5305 + sizeof(struct GNUNET_PeerIdentity) * num_hops
5306 + sizeof(struct TransportDVBoxPayloadP)
5307 + enc_body_size] GNUNET_ALIGN;
5308 struct GNUNET_PeerIdentity *dhops;
5309
5310 box_hdr.header.size = htons (sizeof(buf));
5311 box_hdr.orig_size = htons (sizeof(buf));
5312 box_hdr.num_hops = htons (num_hops);
5313 memcpy (buf, &box_hdr, sizeof(box_hdr));
5314 dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
5315 memcpy (dhops,
5316 dvh->path,
5317 dvh->distance * sizeof(struct GNUNET_PeerIdentity));
5318 dhops[dvh->distance] = dv->target;
5319 if (GNUNET_EXTRA_LOGGING > 0)
5320 {
5321 char *path;
5322
5324 for (unsigned int j = 0; j < num_hops; j++)
5325 {
5326 char *tmp;
5327
5328 GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
5329 GNUNET_free (path);
5330 path = tmp;
5331 }
5333 "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
5334 ntohs (hdr->type),
5335 GNUNET_i2s (&dv->target),
5336 i + 1,
5337 num_dvhs,
5338 path);
5339 GNUNET_free (path);
5340 }
5341 rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
5342 memcpy (&dhops[num_hops], enc, sizeof(enc));
5343 use (use_cls,
5344 dvh->next_hop,
5345 (const struct GNUNET_MessageHeader *) buf,
5346 options);
5347 GNUNET_free (key);
5348 }
5349 return rtt;
5350}
5351
5352
5362static void
5363send_dv_to_neighbour (void *cls,
5364 struct Neighbour *next_hop,
5365 const struct GNUNET_MessageHeader *hdr,
5367{
5368 (void) cls;
5369 (void) route_via_neighbour (next_hop, hdr, RMO_UNCONFIRMED_ALLOWED);
5370}
5371
5372
5384static struct GNUNET_TIME_Relative
5386// route_control_message_without_fc (const struct GNUNET_PeerIdentity *target,
5387 const struct GNUNET_MessageHeader *hdr,
5389{
5390 // struct VirtualLink *vl;
5391 struct Neighbour *n;
5392 struct DistanceVector *dv;
5393 struct GNUNET_TIME_Relative rtt1;
5394 struct GNUNET_TIME_Relative rtt2;
5395 const struct GNUNET_PeerIdentity *target = &vl->target;
5396
5398 "Trying to route message of type %u to %s without fc\n",
5399 ntohs (hdr->type),
5400 GNUNET_i2s (target));
5401
5402 // TODO Do this elsewhere. vl should be given as parameter to method.
5403 // vl = lookup_virtual_link (target);
5404 GNUNET_assert (NULL != vl && GNUNET_YES == vl->confirmed);
5405 if (NULL == vl)
5407 n = vl->n;
5408 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
5409 if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
5410 {
5411 /* if confirmed is required, and we do not have anything
5412 confirmed, drop respective options */
5413 if (NULL == n)
5414 n = lookup_neighbour (target);
5415 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
5417 }
5418 if ((NULL == n) && (NULL == dv))
5419 {
5421 "Cannot route message of type %u to %s: no route\n",
5422 ntohs (hdr->type),
5423 GNUNET_i2s (target));
5425 "# Messages dropped in routing: no acceptable method",
5426 1,
5427 GNUNET_NO);
5429 }
5431 "Routing message of type %u to %s with options %X\n",
5432 ntohs (hdr->type),
5433 GNUNET_i2s (target),
5434 (unsigned int) options);
5435 /* If both dv and n are possible and we must choose:
5436 flip a coin for the choice between the two; for now 50/50 */
5437 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
5438 {
5440 n = NULL;
5441 else
5442 dv = NULL;
5443 }
5444 if ((NULL != n) && (NULL != dv))
5445 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
5446 enough for redundancy, so clear the flag. */
5449 if (NULL != n)
5450 {
5452 "Try to route message of type %u to %s without fc via neighbour\n",
5453 ntohs (hdr->type),
5454 GNUNET_i2s (target));
5455 rtt1 = route_via_neighbour (n, hdr, options);
5456 }
5457 if (NULL != dv)
5458 {
5459 struct DistanceVectorHop *hops[2];
5460 unsigned int res;
5461
5463 options,
5464 hops,
5465 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
5466 if (0 == res)
5467 {
5469 "Failed to route message, could not determine DV path\n");
5470 return rtt1;
5471 }
5473 "encapsulate_for_dv 1\n");
5474 rtt2 = encapsulate_for_dv (dv,
5475 res,
5476 hops,
5477 hdr,
5479 NULL,
5481 GNUNET_YES);
5482 }
5483 return GNUNET_TIME_relative_min (rtt1, rtt2);
5484}
5485
5486
5487static void
5488consider_sending_fc (void *cls);
5489
5496static void
5497task_consider_sending_fc (void *cls)
5498{
5499 struct VirtualLink *vl = cls;
5500 vl->fc_retransmit_task = NULL;
5501 consider_sending_fc (cls);
5502}
5503
5504
5505static char *
5506get_address_without_port (const char *address);
5507
5508
5510{
5511 size_t off;
5512 char *tgnas;
5513};
5514
5515
5516static enum GNUNET_GenericReturnValue
5517add_global_addresses (void *cls,
5518 const struct GNUNET_PeerIdentity *pid,
5519 void *value)
5520{
5521 struct AddGlobalAddressesContext *ctx = cls;
5522 struct TransportGlobalNattedAddress *tgna = value;
5523 char *addr = (char *) &tgna[1];
5524
5526 "sending address %s length %u\n",
5527 addr,
5528 ntohl (tgna->address_length));
5529 GNUNET_memcpy (&(ctx->tgnas[ctx->off]), tgna, sizeof (struct
5531 + ntohl (tgna->address_length));
5532 ctx->off += sizeof(struct TransportGlobalNattedAddress) + ntohl (tgna->
5534
5535 return GNUNET_OK;
5536}
5537
5538
5539static struct GNUNET_TIME_Relative
5540calculate_rtt (struct DistanceVector *dv);
5541
5542
5549static void
5550consider_sending_fc (void *cls)
5551{
5552 struct VirtualLink *vl = cls;
5553 struct GNUNET_TIME_Absolute monotime;
5554 struct TransportFlowControlMessage *fc;
5556 struct GNUNET_TIME_Relative rtt;
5557 struct GNUNET_TIME_Relative rtt_average;
5558 struct Neighbour *n = vl->n;
5559
5560 if (NULL != n && 0 < n->number_of_addresses)
5561 {
5562 size_t addresses_size =
5563 n->number_of_addresses * sizeof (struct TransportGlobalNattedAddress) + n
5564 ->size_of_global_addresses;
5565 char *tgnas = GNUNET_malloc (addresses_size);
5567 ctx.off = 0;
5568 ctx.tgnas = tgnas;
5569
5571 + addresses_size);
5572 fc->header.size = htons (sizeof(struct TransportFlowControlMessage)
5573 + addresses_size);
5574 fc->size_of_addresses = htonl (n->size_of_global_addresses);
5575 fc->number_of_addresses = htonl (n->number_of_addresses);
5578 &ctx);
5581 }
5582 else
5583 {
5584 fc = GNUNET_malloc (sizeof (struct TransportFlowControlMessage));
5585 fc->header.size = htons (sizeof(struct TransportFlowControlMessage));
5586 }
5587
5589 /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
5590 it always! */
5591 /* For example, we should probably ONLY do this if a bit more than
5592 an RTT has passed, or if the window changed "significantly" since
5593 then. See vl->last_fc_rtt! NOTE: to do this properly, we also
5594 need an estimate for the bandwidth-delay-product for the entire
5595 VL, as that determines "significantly". We have the delay, but
5596 the bandwidth statistics need to be added for the VL!*/(void) duration;
5597
5598 if (NULL != vl->dv)
5599 rtt_average = calculate_rtt (vl->dv);
5600 else
5601 rtt_average = GNUNET_TIME_UNIT_FOREVER_REL;
5602 fc->rtt = GNUNET_TIME_relative_hton (rtt_average);
5604 "Sending FC seq %u to %s with new window %llu %lu %u\n",
5605 (unsigned int) vl->fc_seq_gen,
5606 GNUNET_i2s (&vl->target),
5607 (unsigned long long) vl->incoming_fc_window_size,
5608 (unsigned long) rtt_average.rel_value_us,
5609 vl->sync_ready);
5611 vl->last_fc_transmission = monotime;
5612 fc->sync_ready = vl->sync_ready;
5614 fc->seq = htonl (vl->fc_seq_gen++);
5615 fc->inbound_window_size = GNUNET_htonll (vl->incoming_fc_window_size
5618 fc->outbound_sent = GNUNET_htonll (vl->outbound_fc_window_size_used);
5619 fc->outbound_window_size = GNUNET_htonll (vl->outbound_fc_window_size);
5620 fc->sender_time = GNUNET_TIME_absolute_hton (monotime);
5622 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
5623 {
5626 "FC retransmission to %s failed, will retry in %s\n",
5627 GNUNET_i2s (&vl->target),
5630 }
5631 else
5632 {
5633 /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
5634 vl->last_fc_rtt = rtt;
5635 }
5636 if (NULL != vl->fc_retransmit_task)
5639 {
5641 vl->fc_retransmit_count = 0;
5642 }
5643 vl->fc_retransmit_task =
5645 vl->fc_retransmit_count++;
5646 GNUNET_free (fc);
5647}
5648
5649
5666static void
5668{
5669 struct Neighbour *n = vl->n;
5670 struct DistanceVector *dv = vl->dv;
5671 struct GNUNET_TIME_Absolute now;
5672 struct VirtualLink *vl_next_hop;
5673 int elig;
5674
5676 "check_vl_transmission to target %s\n",
5677 GNUNET_i2s (&vl->target));
5678 /* Check that we have an eligible pending message!
5679 (cheaper than having #transmit_on_queue() find out!) */
5680 elig = GNUNET_NO;
5681 for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
5682 pm = pm->next_vl)
5683 {
5685 "check_vl_transmission loop\n");
5686 if (NULL != pm->qe)
5687 continue; /* not eligible, is in a queue! */
5688 if (pm->bytes_msg + vl->outbound_fc_window_size_used >
5690 {
5692 "Stalled message %" PRIu64
5693 " transmission on VL %s due to flow control: %llu < %llu\n",
5694 pm->logging_uuid,
5695 GNUNET_i2s (&vl->target),
5696 (unsigned long long) vl->outbound_fc_window_size,
5697 (unsigned long long) (pm->bytes_msg
5700 return; /* We have a message, but flow control says "nope" */
5701 }
5703 "Target window on VL %s not stalled. Scheduling transmission on queue\n",
5704 GNUNET_i2s (&vl->target));
5705 /* Notify queues at direct neighbours that we are interested */
5706 now = GNUNET_TIME_absolute_get ();
5707 if (NULL != n)
5708 {
5709 for (struct Queue *queue = n->queue_head; NULL != queue;
5710 queue = queue->next_neighbour)
5711 {
5712 if ((GNUNET_YES == queue->idle) &&
5713 (queue->validated_until.abs_value_us > now.abs_value_us))
5714 {
5716 "Direct neighbour %s not stalled\n",
5717 GNUNET_i2s (&n->pid));
5719 queue,
5721 elig = GNUNET_YES;
5722 }
5723 else
5725 "Neighbour Queue QID: %u (%u) busy or invalid\n",
5726 queue->qid,
5727 queue->idle);
5728 }
5729 }
5730 /* Notify queues via DV that we are interested */
5731 if (NULL != dv)
5732 {
5733 /* Do DV with lower scheduler priority, which effectively means that
5734 IF a neighbour exists and is available, we prefer it. */
5735 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
5736 pos = pos->next_dv)
5737 {
5738 struct Neighbour *nh_iter = pos->next_hop;
5739
5740
5741 if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
5742 continue; /* skip this one: path not validated */
5743 else
5744 {
5745 vl_next_hop = lookup_virtual_link (&nh_iter->pid);
5746 GNUNET_assert (NULL != vl_next_hop);
5747 if (pm->bytes_msg + vl_next_hop->outbound_fc_window_size_used >
5748 vl_next_hop->outbound_fc_window_size)
5749 {
5751 "Stalled message %" PRIu64
5752 " transmission on next hop %s due to flow control: %llu < %llu\n",
5753 pm->logging_uuid,
5754 GNUNET_i2s (&vl_next_hop->target),
5755 (unsigned long
5756 long) vl_next_hop->outbound_fc_window_size,
5757 (unsigned long long) (pm->bytes_msg
5758 + vl_next_hop->
5759 outbound_fc_window_size_used));
5760 consider_sending_fc (vl_next_hop);
5761 continue; /* We have a message, but flow control says "nope" for the first hop of this path */
5762 }
5763 for (struct Queue *queue = nh_iter->queue_head; NULL != queue;
5764 queue = queue->next_neighbour)
5765 if ((GNUNET_YES == queue->idle) &&
5766 (queue->validated_until.abs_value_us > now.abs_value_us))
5767 {
5769 "Next hop neighbour %s not stalled\n",
5770 GNUNET_i2s (&nh_iter->pid));
5772 queue,
5774 elig = GNUNET_YES;
5775 }
5776 else
5778 "DV Queue QID: %u (%u) busy or invalid\n",
5779 queue->qid,
5780 queue->idle);
5781 }
5782 }
5783 }
5784 if (GNUNET_YES == elig)
5786 "Eligible message %" PRIu64 " of size %u to %s: %llu/%llu\n",
5787 pm->logging_uuid,
5788 pm->bytes_msg,
5789 GNUNET_i2s (&vl->target),
5790 (unsigned long long) vl->outbound_fc_window_size,
5791 (unsigned long long) (pm->bytes_msg
5793 break;
5794 }
5795}
5796
5797
5804static void
5805handle_client_send (void *cls, const struct OutboundMessage *obm)
5806{
5807 struct TransportClient *tc = cls;
5808 struct PendingMessage *pm;
5809 const struct GNUNET_MessageHeader *obmm;
5810 uint32_t bytes_msg;
5811 struct VirtualLink *vl;
5813
5814 GNUNET_assert (CT_CORE == tc->type);
5815 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
5816 bytes_msg = ntohs (obmm->size);
5817 pp = ntohl (obm->priority);
5818 vl = lookup_virtual_link (&obm->peer);
5819 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
5820 {
5822 "Don't have %s as a neighbour (anymore).\n",
5823 GNUNET_i2s (&obm->peer));
5824 /* Failure: don't have this peer as a neighbour (anymore).
5825 Might have gone down asynchronously, so this is NOT
5826 a protocol violation by CORE. Still count the event,
5827 as this should be rare. */
5830 "# messages dropped (neighbour unknown)",
5831 1,
5832 GNUNET_NO);
5833 return;
5834 }
5835
5836 pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
5838 "1 created pm %p storing vl %p\n",
5839 pm,
5840 vl);
5841 pm->logging_uuid = logging_uuid_gen++;
5842 pm->prefs = pp;
5843 pm->client = tc;
5844 pm->vl = vl;
5845 pm->bytes_msg = bytes_msg;
5846 memcpy (&pm[1], obmm, bytes_msg);
5848 "Sending message of type %u with %u bytes as <%" PRIu64
5849 "> to %s\n",
5850 ntohs (obmm->type),
5851 bytes_msg,
5852 pm->logging_uuid,
5853 GNUNET_i2s (&obm->peer));
5855 tc->details.core.pending_msg_head,
5856 tc->details.core.pending_msg_tail,
5857 pm);
5859 vl->pending_msg_head,
5860 vl->pending_msg_tail,
5861 pm);
5864}
5865
5866
5876static void
5878 void *cls,
5880{
5881 struct Neighbour *n;
5882 struct VirtualLink *vl;
5883 struct TransportClient *tc = cls;
5884 const struct GNUNET_MessageHeader *inbox =
5885 (const struct GNUNET_MessageHeader *) &cb[1];
5886 uint16_t isize = ntohs (inbox->size);
5887 const char *is = ((const char *) &cb[1]) + isize;
5888 size_t slen = strlen (is) + 1;
5889 char
5890 mbuf[slen + isize
5891 + sizeof(struct
5895
5896 /* 0-termination of 'is' was checked already in
5897 #check_communicator_backchannel() */
5899 "Preparing backchannel transmission to %s:%s of type %u and size %u\n",
5900 GNUNET_i2s (&cb->pid),
5901 is,
5902 ntohs (inbox->type),
5903 ntohs (inbox->size));
5904 /* encapsulate and encrypt message */
5905 be->header.type =
5907 be->header.size = htons (sizeof(mbuf));
5908 memcpy (&be[1], inbox, isize);
5909 memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
5910 + isize],
5911 is,
5912 strlen (is) + 1);
5913 // route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
5914 vl = lookup_virtual_link (&cb->pid);
5915 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
5916 {
5918 }
5919 else
5920 {
5921 /* Use route via neighbour */
5922 n = lookup_neighbour (&cb->pid);
5923 if (NULL != n)
5925 n,
5926 &be->header,
5927 RMO_NONE);
5928 }
5930}
5931
5932
5940static int
5941check_add_address (void *cls,
5942 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5943{
5944 struct TransportClient *tc = cls;
5945
5946 if (CT_COMMUNICATOR != tc->type)
5947 {
5948 GNUNET_break (0);
5949 return GNUNET_SYSERR;
5950 }
5952 return GNUNET_OK;
5953}
5954
5955
5961static void
5962store_pi (void *cls);
5963
5964
5969{
5970
5974 struct AddressListEntry *ale;
5975
5979 struct PilsRequest *req;
5980
5981
5985 struct GNUNET_TIME_Absolute et;
5986};
5987
5988
5989static void
5990shc_cont (void *cls, int success)
5991{
5992 struct PilsAddressSignContext *pc = cls;
5993
5994 GNUNET_assert (NULL == pc->req);
5995 if (GNUNET_OK != success)
5996 {
5998 "Failed to store our address `%s' with peerstore\n",
5999 pc->ale->address);
6000 if (NULL == pc->ale->st)
6001 {
6003 &store_pi,
6004 pc->ale);
6005 }
6006 }
6007 GNUNET_free (pc);
6008}
6009
6010
6014static void
6015pils_sign_hello_cb (void *cls,
6016 const struct GNUNET_PeerIdentity *pid,
6017 const struct GNUNET_CRYPTO_EddsaSignature *sig)
6018{
6019 struct PilsAddressSignContext *pc = cls;
6020 struct GNUNET_MQ_Envelope *env;
6021 const struct GNUNET_MessageHeader *msg;
6022
6023 pc->req->op = NULL;
6026 pc->req);
6027 GNUNET_free (pc->req);
6028 pc->req = NULL;
6031 pid,
6032 sig,
6033 pc->et);
6036 "store_pi 1\n");
6038 msg,
6039 shc_cont,
6040 pc);
6041 GNUNET_free (env);
6042}
6043
6044
6051static void
6052peerstore_store_own_cb (void *cls, int success)
6053{
6054 struct PilsAddressSignContext *pc = cls;
6055
6056 pc->ale->sc = NULL;
6057 if (GNUNET_YES != success)
6059 "Failed to store our own address `%s' in peerstore!\n",
6060 pc->ale->address);
6061 else
6063 "Successfully stored our own address `%s' in peerstore!\n",
6064 pc->ale->address);
6065 /* refresh period is 1/4 of expiration time, that should be plenty
6066 without being excessive. */
6067 if (NULL == pc->ale->st)
6068 {
6069 pc->ale->st =
6071 GNUNET_TIME_relative_divide (pc->ale->expiration,
6072 4ULL),
6073 &store_pi,
6074 pc->ale);
6075 }
6076
6077 /* Now we have to update our HELLO! */
6079 pc->req = GNUNET_new (struct PilsRequest);
6082 pc->req);
6083 pc->req->op = GNUNET_PILS_sign_hello (pils,
6085 pc->et,
6087 pc);
6088}
6089
6090
6091// This function
6092static void
6093pils_sign_addr_cb (void *cls,
6094 const struct GNUNET_PeerIdentity *pid,
6095 const struct GNUNET_CRYPTO_EddsaSignature *sig)
6096{
6097 struct PilsAddressSignContext *pc = cls;
6098 char *sig_str;
6099 void *result;
6100 size_t result_size;
6101
6102 pc->req->op = NULL;
6105 pc->req);
6106 GNUNET_free (pc->req);
6107 sig_str = NULL;
6108 (void) GNUNET_STRINGS_base64_encode (sig, sizeof(*sig), &sig_str);
6109 result_size =
6110 1 + GNUNET_asprintf (
6111 (char **) &result,
6112 "%s;%llu;%u;%s",
6113 sig_str,
6114 (unsigned long long) pc->et.abs_value_us,
6115 (unsigned int) pc->ale->nt,
6116 pc->ale->address);
6117 GNUNET_free (sig_str);
6118
6120 "Build our HELLO URI `%s'\n",
6121 (char*) result);
6122
6123 pc->ale->signed_address = result;
6124 pc->ale->signed_address_len = result_size;
6126
6127 expiration = GNUNET_TIME_relative_to_absolute (pc->ale->expiration);
6129 "transport",
6130 pid,
6132 result,
6133 result_size,
6134 expiration,
6137 pc);
6138}
6139
6140
6144struct SignedAddress
6145{
6150
6155
6159 struct GNUNET_HashCode addr_hash GNUNET_PACKED;
6160};
6161
6162
6176void
6178 struct AddressListEntry *ale,
6179 struct GNUNET_TIME_Absolute mono_time)
6180{
6181 struct SignedAddress sa;
6182 struct PilsAddressSignContext *pc;
6183
6184 sa.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS);
6185 sa.purpose.size = htonl (sizeof(sa));
6186 sa.mono_time = GNUNET_TIME_absolute_hton (mono_time);
6187 GNUNET_CRYPTO_hash (ale->address, strlen (ale->address), &sa.addr_hash);
6189 pc->ale = ale;
6190 pc->et = mono_time;
6191 pc->req = GNUNET_new (struct PilsRequest);
6193 &sa.purpose,
6195 pc);
6198 pc->req);
6199}
6200
6201
6207static void
6208store_pi (void *cls)
6209{
6210 struct AddressListEntry *ale = cls;
6211 const char *dash;
6212 char *address_uri;
6213 char *prefix;
6214 unsigned int add_success;
6215
6216 if (NULL == GNUNET_PILS_get_identity (pils))
6217 {
6219 &store_pi,
6220 ale);
6221 return;
6222 }
6224 dash = strchr (ale->address, '-');
6225 GNUNET_assert (NULL != dash);
6226 dash++;
6227 GNUNET_asprintf (&address_uri,
6228 "%s://%s",
6229 prefix,
6230 dash);
6232 ale->st = NULL;
6234 "Storing our address `%s' in peerstore until %s!\n",
6235 ale->address,
6238 address_uri);
6239 if (GNUNET_OK != add_success)
6240 {
6242 "Storing our address `%s' %s\n",
6243 address_uri,
6244 GNUNET_NO == add_success ? "not done" : "failed");
6245 GNUNET_free (address_uri);
6246 return;
6247 }
6248 else
6249 {
6250
6252 "Storing our address `%s'\n",
6253 address_uri);
6254 }
6255 // FIXME hello_mono_time used here?? What about expiration in ale?
6256 pils_sign_address (ale,
6258 // TODO keep track of op and potentially cancel/clean
6259 GNUNET_free (address_uri);
6260}
6261
6262
6263static struct AddressListEntry *
6267 const char *address,
6268 uint32_t aid,
6269 size_t slen)
6270{
6271 struct AddressListEntry *ale;
6272 char *address_without_port;
6273
6274 ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
6275 ale->tc = tc;
6276 ale->address = (const char *) &ale[1];
6277 ale->expiration = expiration;
6278 ale->aid = aid;
6279 ale->nt = nt;
6280 memcpy (&ale[1], address, slen);
6281 address_without_port = get_address_without_port (ale->address);
6283 "Is this %s a local address (%s)\n",
6284 address_without_port,
6285 ale->address);
6286 if (0 != strcmp ("127.0.0.1", address_without_port))
6287 {
6288 if (NULL != ale->st)
6289 {
6291 }
6292 ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
6293 }
6294 GNUNET_free (address_without_port);
6295
6296 return ale;
6297}
6298
6299
6300static void
6301feed_addresses_to_pils (void *cls)
6302{
6303
6305 "Feeding addresses to PILS\n");
6306 pils_feed_task = NULL;
6307
6309 GST_my_hello);
6310}
6311
6312
6319static void
6320handle_add_address (void *cls,
6321 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
6322{
6323 struct TransportClient *tc = cls;
6324 struct AddressListEntry *ale;
6325 size_t slen;
6326 char *address;
6327
6328 /* 0-termination of &aam[1] was checked in #check_add_address */
6330 "Communicator added address `%s'!\n",
6331 (const char *) &aam[1]);
6332 slen = ntohs (aam->header.size) - sizeof(*aam);
6333 address = GNUNET_malloc (slen);
6334 memcpy (address, &aam[1], slen);
6335 ale = create_address_entry (tc,
6337 ntohl (aam->nt),
6338 address,
6339 aam->aid,
6340 slen);
6341 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
6342 tc->details.communicator.addr_tail,
6343 ale);
6344 {
6345 for (struct AddressListEntry *iter = tc->details.communicator.addr_head;
6346 (NULL != iter && NULL != iter->next);
6347 iter = iter->next)
6348 {
6349 char *address_uri;
6350 const char *dash = strchr (ale->address, '-');
6352 GNUNET_assert (NULL != dash);
6353 dash++;
6354 GNUNET_asprintf (&address_uri,
6355 "%s://%s",
6356 prefix,
6357 dash);
6360 GNUNET_free (address_uri);
6361 }
6362 if (NULL != pils_feed_task)
6366 NULL);
6367 }
6370}
6371
6372
6379static void
6380handle_del_address (void *cls,
6381 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
6382{
6383 struct TransportClient *tc = cls;
6384 struct AddressListEntry *alen;
6385
6386 if (CT_COMMUNICATOR != tc->type)
6387 {
6388 GNUNET_break (0);
6390 return;
6391 }
6392 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
6393 NULL != ale;
6394 ale = alen)
6395 {
6396 alen = ale->next;
6397 if (dam->aid != ale->aid)
6398 continue;
6399 GNUNET_assert (ale->tc == tc);
6401 "Communicator deleted address `%s'!\n",
6402 ale->address);
6404 ale->address);
6405 if (NULL != pils_feed_task)
6409 NULL);
6412 return;
6413 }
6415 "Communicator removed address we did not even have.\n");
6417 // GNUNET_SERVICE_client_drop (tc->client);
6418}
6419
6420
6428static void
6430
6431
6439static void
6440core_env_sent_cb (void *cls)
6441{
6442 struct CoreSentContext *ctx = cls;
6443 struct VirtualLink *vl = ctx->vl;
6444
6445 if (NULL == vl)
6446 {
6447 /* lost the link in the meantime, ignore */
6448 GNUNET_free (ctx);
6449 return;
6450 }
6453 vl->incoming_fc_window_size_ram -= ctx->size;
6454 vl->incoming_fc_window_size_used += ctx->isize;
6456 GNUNET_free (ctx);
6457}
6458
6459
6460static void
6462 const struct GNUNET_MessageHeader *mh,
6463 struct CommunicatorMessageContext *cmc,
6464 unsigned int free_cmc)
6465{
6466 uint16_t size = ntohs (mh->size);
6467 int have_core;
6468
6469 if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
6470 {
6472 "# CORE messages dropped (FC arithmetic overflow)",
6473 1,
6474 GNUNET_NO);
6476 "CORE messages of type %u with %u bytes dropped (FC arithmetic overflow)\n",
6477 (unsigned int) ntohs (mh->type),
6478 (unsigned int) ntohs (mh->size));
6479 if (GNUNET_YES == free_cmc)
6481 return;
6482 }
6484 {
6486 "# CORE messages dropped (FC window overflow)",
6487 1,
6488 GNUNET_NO);
6490 "CORE messages of type %u with %u bytes dropped (FC window overflow)\n",
6491 (unsigned int) ntohs (mh->type),
6492 (unsigned int) ntohs (mh->size));
6493 if (GNUNET_YES == free_cmc)
6495 return;
6496 }
6497
6498 /* Forward to all CORE clients */
6499 have_core = GNUNET_NO;
6500 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
6501 {
6502 struct GNUNET_MQ_Envelope *env;
6503 struct InboundMessage *im;
6504 struct CoreSentContext *ctx;
6505
6506 if (CT_CORE != tc->type)
6507 continue;
6510 ctx = GNUNET_new (struct CoreSentContext);
6511 ctx->vl = vl;
6512 ctx->size = size;
6513 ctx->isize = (GNUNET_NO == have_core) ? size : 0;
6514 have_core = GNUNET_YES;
6517 im->peer = cmc->im.sender;
6518 memcpy (&im[1], mh, size);
6519 GNUNET_MQ_send (tc->mq, env);
6521 }
6522 if (GNUNET_NO == have_core)
6523 {
6525 "Dropped message to CORE: no CORE client connected!\n");
6526 /* Nevertheless, count window as used, as it is from the
6527 perspective of the other peer! */
6529 /* TODO-M1 */
6531 "Dropped message of type %u with %u bytes to CORE: no CORE client connected!\n",
6532 (unsigned int) ntohs (mh->type),
6533 (unsigned int) ntohs (mh->size));
6534 if (GNUNET_YES == free_cmc)
6536 return;
6537 }
6539 "Delivered message from %s of type %u to CORE recv window %d\n",
6540 GNUNET_i2s (&cmc->im.sender),
6541 ntohs (mh->type),
6543 if (vl->core_recv_window > 0)
6544 {
6545 if (GNUNET_YES == free_cmc)
6547 return;
6548 }
6549 /* Wait with calling #finish_cmc_handling(cmc) until the message
6550 was processed by CORE MQs (for CORE flow control)! */
6551 if (GNUNET_YES == free_cmc)
6553}
6554
6555
6564static void
6565handle_raw_message (void *cls, const struct GNUNET_MessageHeader *mh)
6566{
6567 struct CommunicatorMessageContext *cmc = cls;
6568 // struct CommunicatorMessageContext *cmc_copy =
6569 // GNUNET_new (struct CommunicatorMessageContext);
6570 struct GNUNET_MessageHeader *mh_copy;
6571 struct RingBufferEntry *rbe;
6572 struct VirtualLink *vl;
6573 uint16_t size = ntohs (mh->size);
6574
6576 "Handling raw message of type %u with %u bytes\n",
6577 (unsigned int) ntohs (mh->type),
6578 (unsigned int) ntohs (mh->size));
6579
6580 if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
6581 (size < sizeof(struct GNUNET_MessageHeader)))
6582 {
6583 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6584
6585 GNUNET_break (0);
6586 finish_cmc_handling (cmc);
6588 return;
6589 }
6590 vl = lookup_virtual_link (&cmc->im.sender);
6591 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6592 {
6593 /* FIXME: sender is giving us messages for CORE but we don't have
6594 the link up yet! I *suspect* this can happen right now (i.e.
6595 sender has verified us, but we didn't verify sender), but if
6596 we pass this on, CORE would be confused (link down, messages
6597 arrive). We should investigate more if this happens often,
6598 or in a persistent manner, and possibly do "something" about
6599 it. Thus logging as error for now. */
6600
6601 mh_copy = GNUNET_malloc (size);
6602 rbe = GNUNET_new (struct RingBufferEntry);
6603 rbe->cmc = cmc;
6604 /*cmc_copy->tc = cmc->tc;
6605 cmc_copy->im = cmc->im;*/
6606 GNUNET_memcpy (mh_copy, mh, size);
6607
6608 rbe->mh = mh_copy;
6609
6611 {
6612 struct RingBufferEntry *rbe_old = ring_buffer[ring_buffer_head];
6613 GNUNET_free (rbe_old->cmc);
6614 GNUNET_free (rbe_old->mh);
6615 GNUNET_free (rbe_old);
6616 }
6617 ring_buffer[ring_buffer_head] = rbe;// cmc_copy;
6618 // cmc_copy->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6619 cmc->mh = (const struct GNUNET_MessageHeader *) mh_copy;
6621 "Storing message for %s and type %u (%u) in ring buffer head %u is full %u\n",
6622 GNUNET_i2s (&cmc->im.sender),
6623 (unsigned int) ntohs (mh->type),
6624 (unsigned int) ntohs (mh_copy->type),
6628 {
6629 ring_buffer_head = 0;
6631 }
6632 else
6634
6636 "%u items stored in ring buffer\n",
6639
6640 /*GNUNET_break_op (0);
6641 GNUNET_STATISTICS_update (GST_stats,
6642 "# CORE messages dropped (virtual link still down)",
6643 1,
6644 GNUNET_NO);
6645
6646 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6647 "CORE messages of type %u with %u bytes dropped (virtual link still down)\n",
6648 (unsigned int) ntohs (mh->type),
6649 (unsigned int) ntohs (mh->size));
6650 finish_cmc_handling (cmc);*/
6653 // GNUNET_free (cmc);
6654 return;
6655 }
6657}
6658
6659
6667static int
6668check_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
6669{
6670 uint16_t size = ntohs (fb->header.size);
6671 uint16_t bsize = size - sizeof(*fb);
6672
6673 (void) cls;
6674 if (0 == bsize)
6675 {
6676 GNUNET_break_op (0);
6677 return GNUNET_SYSERR;
6678 }
6679 if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
6680 {
6681 GNUNET_break_op (0);
6682 return GNUNET_SYSERR;
6683 }
6684 if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
6685 {
6686 GNUNET_break_op (0);
6687 return GNUNET_SYSERR;
6688 }
6689 return GNUNET_YES;
6690}
6691
6692
6698static void
6699destroy_ack_cummulator (void *cls)
6700{
6701 struct AcknowledgementCummulator *ac = cls;
6702
6703 ac->task = NULL;
6704 GNUNET_assert (0 == ac->num_acks);
6706 GNUNET_YES ==
6708 GNUNET_free (ac);
6709}
6710
6711
6717static void
6719{
6720 struct Neighbour *n;
6721 struct VirtualLink *vl;
6722 struct AcknowledgementCummulator *ac = cls;
6723 char buf[sizeof(struct TransportReliabilityAckMessage)
6724 + ac->num_acks
6726 struct TransportReliabilityAckMessage *ack =
6727 (struct TransportReliabilityAckMessage *) buf;
6729
6730 ac->task = NULL;
6732 "Sending ACK with %u components to %s\n",
6733 ac->num_acks,
6734 GNUNET_i2s (&ac->target));
6735 GNUNET_assert (0 < ac->num_acks);
6737 ack->header.size =
6738 htons (sizeof(*ack)
6739 + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP));
6740 ack->ack_counter = htonl (ac->ack_counter += ac->num_acks);
6741 ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
6742 for (unsigned int i = 0; i < ac->num_acks; i++)
6743 {
6744 ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
6747 }
6748 /*route_control_message_without_fc (
6749 &ac->target,
6750 &ack->header,
6751 RMO_DV_ALLOWED);*/
6752 vl = lookup_virtual_link (&ac->target);
6753 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
6754 {
6756 vl,
6757 &ack->header,
6759 }
6760 else
6761 {
6762 /* Use route via neighbour */
6763 n = lookup_neighbour (&ac->target);
6764 if (NULL != n)
6766 n,
6767 &ack->header,
6768 RMO_NONE);
6769 }
6770 ac->num_acks = 0;
6773 ac);
6774}
6775
6776
6785static void
6787 const struct AcknowledgementUUIDP *ack_uuid,
6788 struct GNUNET_TIME_Absolute max_delay)
6789{
6790 struct AcknowledgementCummulator *ac;
6791
6793 "Scheduling ACK %s for transmission to %s\n",
6794 GNUNET_uuid2s (&ack_uuid->value),
6795 GNUNET_i2s (pid));
6797 if (NULL == ac)
6798 {
6800 ac->target = *pid;
6801 ac->min_transmission_time = max_delay;
6805 &ac->target,
6806 ac,
6808 }
6809 else
6810 {
6811 if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
6812 {
6813 /* must run immediately, ack buffer full! */
6815 }
6819 }
6822 ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
6823 ac->num_acks++;
6826 ac);
6827}
6828
6829
6834{
6839
6843 struct ReassemblyContext *rc;
6844};
6845
6846
6856static int
6857find_by_message_uuid (void *cls, uint32_t key, void *value)
6858{
6859 struct FindByMessageUuidContext *fc = cls;
6860 struct ReassemblyContext *rc = value;
6861
6862 (void) key;
6863 if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
6864 {
6865 fc->rc = rc;
6866 return GNUNET_NO;
6867 }
6868 return GNUNET_YES;
6869}
6870
6871
6879static void
6880handle_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
6881{
6882 struct CommunicatorMessageContext *cmc = cls;
6883 struct VirtualLink *vl;
6884 struct ReassemblyContext *rc;
6885 const struct GNUNET_MessageHeader *msg;
6886 uint16_t msize;
6887 uint16_t fsize;
6888 uint16_t frag_off;
6889 char *target;
6890 struct GNUNET_TIME_Relative cdelay;
6891 struct FindByMessageUuidContext fc;
6892
6893 vl = lookup_virtual_link (&cmc->im.sender);
6894 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
6895 {
6896 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
6897
6899 "No virtual link for %s to handle fragment\n",
6900 GNUNET_i2s (&cmc->im.sender));
6901 GNUNET_break (0);
6902 finish_cmc_handling (cmc);
6904 return;
6905 }
6906 if (NULL == vl->reassembly_map)
6907 {
6909 vl->reassembly_heap =
6914 vl);
6915 }
6916 msize = ntohs (fb->msg_size);
6917 fc.message_uuid = fb->msg_uuid;
6918 fc.rc = NULL;
6920 fb->msg_uuid.uuid,
6922 &fc);
6923 fsize = ntohs (fb->header.size) - sizeof(*fb);
6924 if (NULL == (rc = fc.rc))
6925 {
6926 rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */
6927 + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
6928 rc->msg_uuid = fb->msg_uuid;
6929 rc->virtual_link = vl;
6930 rc->msg_size = msize;
6931 rc->reassembly_timeout =
6935 rc,
6939 vl->reassembly_map,
6940 rc->msg_uuid.uuid,
6941 rc,
6943 target = (char *) &rc[1];
6944 rc->bitfield = (uint8_t *) (target + rc->msg_size);
6945 if (fsize != rc->msg_size)
6946 rc->msg_missing = rc->msg_size;
6947 else
6948 rc->msg_missing = 0;
6950 "Received fragment with size %u at offset %u/%u %u bytes missing from %s for NEW message %"
6951 PRIu64 "\n",
6952 fsize,
6953 ntohs (fb->frag_off),
6954 msize,
6955 rc->msg_missing,
6956 GNUNET_i2s (&cmc->im.sender),
6957 fb->msg_uuid.uuid);
6958 }
6959 else
6960 {
6961 target = (char *) &rc[1];
6963 "Received fragment at offset %u/%u from %s for message %u\n",
6964 ntohs (fb->frag_off),
6965 msize,
6966 GNUNET_i2s (&cmc->im.sender),
6967 (unsigned int) fb->msg_uuid.uuid);
6968 }
6969 if (msize != rc->msg_size)
6970 {
6971 GNUNET_break (0);
6972 finish_cmc_handling (cmc);
6973 return;
6974 }
6975
6976 /* reassemble */
6977 if (0 == fsize)
6978 {
6979 GNUNET_break (0);
6980 finish_cmc_handling (cmc);
6981 return;
6982 }
6983 frag_off = ntohs (fb->frag_off);
6984 if (frag_off + fsize > msize)
6985 {
6986 /* Fragment (plus fragment size) exceeds message size! */
6987 GNUNET_break_op (0);
6988 finish_cmc_handling (cmc);
6989 return;
6990 }
6991 memcpy (&target[frag_off], &fb[1], fsize);
6992 /* update bitfield and msg_missing */
6993 for (unsigned int i = frag_off; i < frag_off + fsize; i++)
6994 {
6995 if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
6996 {
6997 rc->bitfield[i / 8] |= (1 << (i % 8));
6998 rc->msg_missing--;
6999 }
7000 }
7001
7002 /* Compute cumulative ACK */
7004 cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
7005 if (0 == rc->msg_missing)
7006 cdelay = GNUNET_TIME_UNIT_ZERO;
7007 cummulative_ack (&cmc->im.sender,
7008 &fb->ack_uuid,
7011 /* is reassembly complete? */
7012 if (0 != rc->msg_missing)
7013 {
7014 finish_cmc_handling (cmc);
7015 return;
7016 }
7017 /* reassembly is complete, verify result */
7018 msg = (const struct GNUNET_MessageHeader *) &rc[1];
7019 if (ntohs (msg->size) != rc->msg_size)
7020 {
7021 GNUNET_break (0);
7023 finish_cmc_handling (cmc);
7024 return;
7025 }
7026 /* successful reassembly */
7028 "Fragment reassembly complete for message %u\n",
7029 (unsigned int) fb->msg_uuid.uuid);
7030 /* FIXME: check that the resulting msg is NOT a
7031 DV Box or Reliability Box, as that is NOT allowed! */
7032 cmc->mh = msg;
7034 /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
7035 en-route and we forget that we finished this reassembly immediately!
7036 -> keep around until timeout?
7037 -> shorten timeout based on ACK? */
7039}
7040
7041
7049static int
7050check_reliability_box (void *cls,
7051 const struct TransportReliabilityBoxMessage *rb)
7052{
7053 const struct GNUNET_MessageHeader *box = (const struct
7054 GNUNET_MessageHeader *) &rb[1];
7055 (void) cls;
7056
7058 "check_send_msg with size %u: inner msg type %u and size %u (%lu %lu)\n",
7059 ntohs (rb->header.size),
7060 ntohs (box->type),
7061 ntohs (box->size),
7062 sizeof (struct TransportReliabilityBoxMessage),
7063 sizeof (struct GNUNET_MessageHeader));
7065 return GNUNET_YES;
7066}
7067
7068
7076static void
7077handle_reliability_box (void *cls,
7078 const struct TransportReliabilityBoxMessage *rb)
7079{
7080 struct CommunicatorMessageContext *cmc = cls;
7081 const struct GNUNET_MessageHeader *inbox =
7082 (const struct GNUNET_MessageHeader *) &rb[1];
7083 struct GNUNET_TIME_Relative rtt;
7084
7086 "Received reliability box from %s with UUID %s of type %u\n",
7087 GNUNET_i2s (&cmc->im.sender),
7089 (unsigned int) ntohs (inbox->type));
7090 rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
7091 do not really have an RTT for the
7092 * incoming* queue (should we have
7093 the sender add it to the rb message?) */
7095 &cmc->im.sender,
7096 &rb->ack_uuid,
7097 (0 == ntohl (rb->ack_countdown))
7100 GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
7101 /* continue with inner message */
7102 /* FIXME: check that inbox is NOT a DV Box, fragment or another
7103 reliability box (not allowed!) */
7104 cmc->mh = inbox;
7106}
7107
7108
7117static void
7118update_pd_age (struct PerformanceData *pd, unsigned int age)
7119{
7120 unsigned int sage;
7121
7122 if (age == pd->last_age)
7123 return; /* nothing to do */
7124 sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
7125 for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
7126 {
7127 struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
7128
7129 the->bytes_sent = 0;
7130 the->bytes_received = 0;
7131 }
7132 pd->last_age = age;
7133}
7134
7135
7144static void
7146 struct GNUNET_TIME_Relative rtt,
7147 uint16_t bytes_transmitted_ok)
7148{
7149 uint64_t nval = rtt.rel_value_us;
7150 uint64_t oval = pd->aged_rtt.rel_value_us;
7151 unsigned int age = get_age ();
7152 struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
7153
7154 if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
7155 pd->aged_rtt = rtt;
7156 else
7157 pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
7158 update_pd_age (pd, age);
7159 the->bytes_received += bytes_transmitted_ok;
7160}
7161
7162
7170static void
7172 struct GNUNET_TIME_Relative rtt,
7173 uint16_t bytes_transmitted_ok)
7174{
7175 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
7176}
7177
7178
7186static void
7188 struct GNUNET_TIME_Relative rtt,
7189 uint16_t bytes_transmitted_ok)
7190{
7191 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
7192}
7193
7194
7202static void
7204{
7205 struct PendingMessage *pos;
7206
7208 "Complete transmission of message %" PRIu64 " %u\n",
7209 pm->logging_uuid,
7210 pm->pmt);
7211 switch (pm->pmt)
7212 {
7213 case PMT_CORE:
7215 /* Full message sent, we are done */
7217 return;
7218
7219 case PMT_FRAGMENT_BOX:
7220 /* Fragment sent over reliable channel */
7221 pos = pm->frag_parent;
7225 "pos frag_off %lu pos bytes_msg %lu pmt %u parent %u\n",
7226 (unsigned long) pos->frag_off,
7227 (unsigned long) pos->bytes_msg,
7228 pos->pmt,
7229 NULL == pos->frag_parent ? 1 : 0);
7230 /* check if subtree is done */
7231 while ((NULL == pos->head_frag) && (pos->frag_off == (pos->bytes_msg
7232 - sizeof(struct
7234 &&
7235 (NULL != pos->frag_parent))
7236 {
7237 pm = pos;
7238 pos = pm->frag_parent;
7239 if ((NULL == pos) && (PMT_DV_BOX == pm->pmt))
7240 {
7242 return;
7243 }
7244 else if (PMT_DV_BOX == pm->pmt)
7245 {
7247 return;
7248 }
7251 }
7252
7253 /* Was this the last applicable fragment? */
7254 if ((NULL == pos->head_frag) && (NULL == pos->frag_parent || PMT_DV_BOX ==
7255 pos->pmt) &&
7256 (pos->frag_off == pos->bytes_msg))
7258 return;
7259
7260 case PMT_DV_BOX:
7262 "Completed transmission of message %" PRIu64 " (DV Box)\n",
7263 pm->logging_uuid);
7264 if (NULL != pm->frag_parent)
7265 {
7266 pos = pm->frag_parent;
7268 pos->bpm = NULL;
7270 }
7271 else
7273 return;
7274 }
7275}
7276
7277
7285static void
7287 struct GNUNET_TIME_Relative ack_delay)
7288{
7289 struct GNUNET_TIME_Relative delay;
7290
7292 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
7293 if (NULL != pa->queue && 1 == pa->num_send)
7295 if (NULL != pa->dvh && 1 == pa->num_send)
7296 update_dvh_performance (pa->dvh, delay, pa->message_size);
7297 if (NULL != pa->pm)
7300}
7301
7302
7310static int
7311check_reliability_ack (void *cls,
7312 const struct TransportReliabilityAckMessage *ra)
7313{
7314 unsigned int n_acks;
7315
7316 (void) cls;
7317 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7318 / sizeof(struct TransportCummulativeAckPayloadP);
7319 if (0 == n_acks)
7320 {
7321 GNUNET_break_op (0);
7322 return GNUNET_SYSERR;
7323 }
7324 if ((ntohs (ra->header.size) - sizeof(*ra)) !=
7325 n_acks * sizeof(struct TransportCummulativeAckPayloadP))
7326 {
7327 GNUNET_break_op (0);
7328 return GNUNET_SYSERR;
7329 }
7330 return GNUNET_OK;
7331}
7332
7333
7341static void
7342handle_reliability_ack (void *cls,
7343 const struct TransportReliabilityAckMessage *ra)
7344{
7345 struct CommunicatorMessageContext *cmc = cls;
7346 const struct TransportCummulativeAckPayloadP *ack;
7347 unsigned int n_acks;
7348 uint32_t ack_counter;
7349
7350 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7351 / sizeof(struct TransportCummulativeAckPayloadP);
7352 ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
7353 for (unsigned int i = 0; i < n_acks; i++)
7354 {
7355 struct PendingAcknowledgement *pa =
7357 if (NULL == pa)
7358 {
7360 "Received ACK from %s with UUID %s which is unknown to us!\n",
7361 GNUNET_i2s (&cmc->im.sender),
7362 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7364 GST_stats,
7365 "# FRAGMENT_ACKS dropped, no matching pending message",
7366 1,
7367 GNUNET_NO);
7368 continue;
7369 }
7371 "Received ACK from %s with UUID %s\n",
7372 GNUNET_i2s (&cmc->im.sender),
7373 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7374 handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
7375 }
7376
7377 ack_counter = htonl (ra->ack_counter);
7378 (void) ack_counter; /* silence compiler warning for now */
7379 // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
7380 // (DV and/or Neighbour?)
7381 finish_cmc_handling (cmc);
7382}
7383
7384
7392static int
7394 void *cls,
7396{
7397 uint16_t size = ntohs (be->header.size) - sizeof(*be);
7398 const struct GNUNET_MessageHeader *inbox =
7399 (const struct GNUNET_MessageHeader *) &be[1];
7400 const char *is;
7401 uint16_t isize;
7402
7403 (void) cls;
7404 if (ntohs (inbox->size) >= size)
7405 {
7406 GNUNET_break_op (0);
7407 return GNUNET_SYSERR;
7408 }
7409 isize = ntohs (inbox->size);
7410 is = ((const char *) inbox) + isize;
7411 size -= isize;
7412 if ('\0' != is[size - 1])
7413 {
7414 GNUNET_break_op (0);
7415 return GNUNET_SYSERR;
7416 }
7417 return GNUNET_YES;
7418}
7419
7420
7429static void
7431 void *cls,
7433{
7434 const struct GNUNET_PeerIdentity *my_identity;
7435 struct CommunicatorMessageContext *cmc = cls;
7437 struct GNUNET_MQ_Envelope *env;
7438 struct TransportClient *tc;
7439 const struct GNUNET_MessageHeader *inbox =
7440 (const struct GNUNET_MessageHeader *) &be[1];
7441 uint16_t isize = ntohs (inbox->size);
7442 const char *target_communicator = ((const char *) inbox) + isize;
7443 char *sender;
7444 char *self;
7445
7448
7449 GNUNET_asprintf (&sender,
7450 "%s",
7451 GNUNET_i2s (&cmc->im.sender));
7452 GNUNET_asprintf (&self,
7453 "%s",
7455
7456 /* Find client providing this communicator */
7457 for (tc = clients_head; NULL != tc; tc = tc->next)
7458 if ((CT_COMMUNICATOR == tc->type) &&
7459 (0 ==
7460 strcmp (tc->details.communicator.address_prefix, target_communicator)))
7461 break;
7462 if (NULL == tc)
7463 {
7464 char *stastr;
7465
7467 &stastr,
7468 "# Backchannel message dropped: target communicator `%s' unknown",
7469 target_communicator);
7471 GNUNET_free (stastr);
7472 finish_cmc_handling (cmc);
7473 return;
7474 }
7475 /* Finally, deliver backchannel message to communicator */
7477 "Delivering backchannel message from %s to %s of type %u to %s\n",
7478 sender,
7479 self,
7480 ntohs (inbox->type),
7481 target_communicator);
7483 cbi,
7484 isize,
7486 cbi->pid = cmc->im.sender;
7487 memcpy (&cbi[1], inbox, isize);
7488 GNUNET_MQ_send (tc->mq, env);
7489 finish_cmc_handling (cmc);
7490}
7491
7492
7502static void
7503path_cleanup_cb (void *cls)
7504{
7505 struct DistanceVector *dv = cls;
7506 struct DistanceVectorHop *pos;
7507
7508 dv->timeout_task = NULL;
7509 while (NULL != (pos = dv->dv_head))
7510 {
7511 GNUNET_assert (dv == pos->dv);
7513 break;
7515 }
7516 if (NULL == pos)
7517 {
7518 free_dv_route (dv);
7519 return;
7520 }
7521 dv->timeout_task =
7523}
7524
7525
7526static void
7528{
7529
7530 const struct GNUNET_PeerIdentity target = vl->target;
7531
7532
7534 {
7535 struct RingBufferEntry *ring_buffer_copy[RING_BUFFER_SIZE];
7536 unsigned int tail = GNUNET_YES == is_ring_buffer_full ? ring_buffer_head :
7537 0;
7538 unsigned int head = GNUNET_YES == is_ring_buffer_full ? RING_BUFFER_SIZE :
7541 struct CommunicatorMessageContext *cmc;
7542 struct RingBufferEntry *rbe;
7543 struct GNUNET_MessageHeader *mh;
7544
7546 "Sending from ring buffer, which has %u items\n",
7547 head);
7548
7549 ring_buffer_head = 0;
7550 for (unsigned int i = 0; i < head; i++)
7551 {
7552 rbe = ring_buffer[(i + tail) % RING_BUFFER_SIZE];
7553 cmc = rbe->cmc;
7554 mh = rbe->mh;
7555
7556 im = cmc->im;
7557 // mh = cmc->mh;
7559 "Sending message of type %u to ring buffer target %s using vl target %s index %u\n",
7560 mh->type,
7561 GNUNET_i2s (&im.sender),
7562 GNUNET_i2s2 (&target),
7563 (i + tail) % RING_BUFFER_SIZE);
7564 if (0 == GNUNET_memcmp (&target, &im.sender))
7565 {
7567 "Finish handling message of type %u and size %u\n",
7568 (unsigned int) ntohs (mh->type),
7569 (unsigned int) ntohs (mh->size));
7571 GNUNET_free (mh);
7572 GNUNET_free (rbe->cmc);
7573 GNUNET_free (rbe);
7574 }
7575 else
7576 {
7577 ring_buffer_copy[ring_buffer_head] = rbe;
7579 }
7580 }
7581
7584 {
7586 }
7587
7588 for (unsigned int i = 0; i < ring_buffer_head; i++)
7589 {
7590 ring_buffer[i] = ring_buffer_copy[i];
7592 "ring_buffer_copy[i]->mh->type for i %u %u\n",
7593 i,
7594 ring_buffer_copy[i]->mh->type);
7596 "ring_buffer[i]->mh->type for i %u %u\n",
7597 i,
7598 ring_buffer[i]->mh->type);
7599 }
7600
7602 "%u items still in ring buffer\n",
7604 }
7605
7607 {
7608 struct PendingMessage *ring_buffer_dv_copy[RING_BUFFER_SIZE];
7609 struct PendingMessage *pm;
7610 unsigned int tail = GNUNET_YES == is_ring_buffer_dv_full ?
7612 0;
7613 unsigned int head = GNUNET_YES == is_ring_buffer_dv_full ?
7616
7618 "Sending from ring buffer dv, which has %u items\n",
7619 head);
7620
7622 for (unsigned int i = 0; i < head; i++)
7623 {
7624 pm = ring_buffer_dv[(i + tail) % RING_BUFFER_SIZE];
7625
7627 "Sending to ring buffer target %s using vl target %s\n",
7628 GNUNET_i2s (&pm->target),
7629 GNUNET_i2s2 (&target));
7630 if (0 == GNUNET_memcmp (&target, &pm->target))
7631 {
7633 "Adding PendingMessage to vl, checking transmission.\n");
7634 pm->vl = vl;
7638 pm);
7639
7641 }
7642 else
7643 {
7644 ring_buffer_dv_copy[ring_buffer_dv_head] = pm;
7646 }
7647 }
7648
7650 {
7652 }
7653
7654 for (unsigned int i = 0; i < ring_buffer_dv_head; i++)
7655 ring_buffer_dv[i] = ring_buffer_dv_copy[i];
7656
7658 "%u items still in ring buffer dv.\n",
7660
7661 }
7662}
7663
7664
7672static void
7674{
7675 struct DistanceVector *dv = hop->dv;
7676 struct VirtualLink *vl;
7677
7678 vl = lookup_virtual_link (&dv->target);
7679 if (NULL == vl)
7680 {
7681
7682 vl = GNUNET_new (struct VirtualLink);
7684 "Creating new virtual link %p to %s using DV!\n",
7685 vl,
7686 GNUNET_i2s (&dv->target));
7687 vl->burst_addr = NULL;
7688 vl->confirmed = GNUNET_YES;
7689 vl->message_uuid_ctr =
7691 vl->target = dv->target;
7697 links,
7698 &vl->target,
7699 vl,
7701 vl->dv = dv;
7702 dv->vl = vl;
7703 vl->visibility_task =
7706 /* We lacked a confirmed connection to the target
7707 before, so tell CORE about it (finally!) */
7710 }
7711 else
7712 {
7713 /* Link was already up, remember dv is also now available and we are done */
7714 vl->dv = dv;
7715 dv->vl = vl;
7716 if (GNUNET_NO == vl->confirmed)
7717 {
7718 vl->confirmed = GNUNET_YES;
7719 vl->visibility_task =
7722 /* We lacked a confirmed connection to the target
7723 before, so tell CORE about it (finally!) */
7726 }
7727 else
7729 "Virtual link to %s could now also use DV!\n",
7730 GNUNET_i2s (&dv->target));
7731 }
7732}
7733
7734
7760static int
7761learn_dv_path (const struct GNUNET_PeerIdentity *path,
7762 unsigned int path_len,
7763 struct GNUNET_TIME_Relative network_latency,
7764 struct GNUNET_TIME_Absolute path_valid_until)
7765{
7766 const struct GNUNET_PeerIdentity *my_identity;
7767 struct DistanceVectorHop *hop;
7768 struct DistanceVector *dv;
7769 struct Neighbour *next_hop;
7770 unsigned int shorter_distance;
7771
7772 if (path_len < 3)
7773 {
7774 /* what a boring path! not allowed! */
7775 GNUNET_break (0);
7776 return GNUNET_SYSERR;
7777 }
7778
7781
7782 GNUNET_assert (0 == GNUNET_memcmp (my_identity, &path[0]));
7783 next_hop = lookup_neighbour (&path[1]);
7784 if (NULL == next_hop)
7785 {
7786 /* next hop must be a neighbour, otherwise this whole thing is useless! */
7787 GNUNET_break (0);
7788 return GNUNET_SYSERR;
7789 }
7790 for (unsigned int i = 2; i < path_len; i++)
7791 {
7792 struct Neighbour *n = lookup_neighbour (&path[i]);
7793 struct GNUNET_TIME_Absolute q_timeout;
7794
7795 if (NULL != n)
7796 {
7797 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
7798 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
7799 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
7801 "remaining %lu to %s\n",
7802 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout)
7803 .rel_value_us,
7804 GNUNET_i2s (&n->pid));
7805 if (0 != GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
7806 {
7807 /* Useless path: we have a direct active connection to some hop
7808 in the middle of the path, so this one is not even
7809 terribly useful for redundancy */
7811 "Path of %u hops useless: directly link to hop %u (%s)\n",
7812 path_len,
7813 i,
7814 GNUNET_i2s (&path[i]));
7816 "# Useless DV path ignored: hop is neighbour",
7817 1,
7818 GNUNET_NO);
7819 return GNUNET_SYSERR;
7820 }
7821 }
7822 }
7823 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
7824 if (NULL == dv)
7825 {
7826 dv = GNUNET_new (struct DistanceVector);
7827 dv->target = path[path_len - 1];
7830 dv);
7833 dv_routes,
7834 &dv->target,
7835 dv,
7837 }
7838 /* Check if we have this path already! */
7839 shorter_distance = 0;
7840 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
7841 pos = pos->next_dv)
7842 {
7843 if (pos->distance < path_len - 3)
7844 shorter_distance++;
7845 /* Note that the distances in 'pos' excludes us (path[0]),
7846 the next_hop (path[1]) and the target so we need to subtract three
7847 and check next_hop explicitly */
7848 if ((pos->distance == path_len - 3) && (pos->next_hop == next_hop))
7849 {
7850 int match = GNUNET_YES;
7851
7852 for (unsigned int i = 0; i < pos->distance; i++)
7853 {
7854 if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
7855 {
7856 match = GNUNET_NO;
7857 break;
7858 }
7859 }
7860 if (GNUNET_YES == match)
7861 {
7862 struct GNUNET_TIME_Relative last_timeout;
7863
7864 /* Re-discovered known path, update timeout */
7866 "# Known DV path refreshed",
7867 1,
7868 GNUNET_NO);
7869 last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
7870 pos->timeout =
7872 pos->path_valid_until =
7873 GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
7874 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
7875 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
7876 if (0 <
7879 if (last_timeout.rel_value_us <
7882 .rel_value_us)
7883 {
7884 /* Some peer send DV learn messages too often, we are learning
7885 the same path faster than it would be useful; do not forward! */
7887 "Rediscovered path too quickly, not forwarding further\n")
7888 ;
7889 return GNUNET_NO;
7890 }
7892 "Refreshed known path to %s valid until %s, forwarding further\n",
7893 GNUNET_i2s (&dv->target),
7895 pos->path_valid_until));
7896 return GNUNET_YES;
7897 }
7898 }
7899 }
7900 /* Count how many shorter paths we have (incl. direct
7901 neighbours) before simply giving up on this one! */
7902 if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
7903 {
7904 /* We have a shorter path already! */
7906 "Have many shorter DV paths %s, not forwarding further\n",
7907 GNUNET_i2s (&dv->target));
7908 return GNUNET_NO;
7909 }
7910 /* create new DV path entry */
7912 "Discovered new DV path to %s valid until %s\n",
7913 GNUNET_i2s (&dv->target),
7914 GNUNET_STRINGS_absolute_time_to_string (path_valid_until));
7915 hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
7916 + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7917 hop->next_hop = next_hop;
7918 hop->dv = dv;
7919 hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
7920 memcpy (&hop[1],
7921 &path[2],
7922 sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7924 hop->path_valid_until = path_valid_until;
7925 hop->distance = path_len - 3;
7926 hop->pd.aged_rtt = network_latency;
7927 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
7929 next_hop->dv_head,
7930 next_hop->dv_tail,
7931 hop);
7932 if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
7934 return GNUNET_YES;
7935}
7936
7937
7945static int
7946check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
7947{
7948 const struct GNUNET_PeerIdentity *my_identity;
7949 uint16_t size = ntohs (dvl->header.size);
7950 uint16_t num_hops = ntohs (dvl->num_hops);
7951 const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
7952
7953 (void) cls;
7954 if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
7955 {
7956 GNUNET_break_op (0);
7957 return GNUNET_SYSERR;
7958 }
7959 if (num_hops > MAX_DV_HOPS_ALLOWED)
7960 {
7961 GNUNET_break_op (0);
7962 return GNUNET_SYSERR;
7963 }
7964
7967
7968 for (unsigned int i = 0; i < num_hops; i++)
7969 {
7970 if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
7971 {
7972 GNUNET_break_op (0);
7973 return GNUNET_SYSERR;
7974 }
7975 if (0 == GNUNET_memcmp (my_identity, &hops[i].hop))
7976 {
7977 GNUNET_break_op (0);
7978 return GNUNET_SYSERR;
7979 }
7980 }
7981 return GNUNET_YES;
7982}
7983
7984
7985struct SignDhpCls
7986{
7987 struct DVPathEntryP *dhops;
7988 uint16_t nhops;
7989 const struct GNUNET_PeerIdentity *next_hop;
7991 struct PilsRequest *pr;
7992};
7993
7994
7995static void
7996sign_dhp_cp (void *cls,
7997 const struct GNUNET_PeerIdentity *pid,
7998 const struct GNUNET_CRYPTO_EddsaSignature *sig)
7999{
8000 struct SignDhpCls *sign_dhp_cls = cls;
8001 struct VirtualLink *vl;
8002 struct DVPathEntryP *dhops = sign_dhp_cls->dhops;
8003 uint16_t nhops = sign_dhp_cls->nhops;
8004 const struct GNUNET_PeerIdentity *next_hop = sign_dhp_cls->next_hop;
8005 struct TransportDVLearnMessage *fwd = sign_dhp_cls->fwd;
8006 struct Neighbour *n;
8007
8008 sign_dhp_cls->pr->op = NULL;
8011 sign_dhp_cls->pr);
8012 GNUNET_free (sign_dhp_cls->pr);
8013 dhops[nhops].hop_sig = *sig;
8014
8015 /*route_control_message_without_fc (next_hop,
8016 &fwd->header,
8017 RMO_UNCONFIRMED_ALLOWED);*/
8018 vl = lookup_virtual_link (next_hop);
8019 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
8020 {
8022 &fwd->header,
8024 }
8025 else
8026 {
8027 /* Use route via neighbour */
8028 n = lookup_neighbour (next_hop);
8029 if (NULL != n)
8031 n,
8032 &fwd->header,
8034 }
8035 GNUNET_free (sign_dhp_cls);
8036}
8037
8038
8050static void
8051forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop,
8052 const struct TransportDVLearnMessage *msg,
8053 uint16_t bi_history,
8054 uint16_t nhops,
8055 const struct DVPathEntryP *hops,
8056 struct GNUNET_TIME_Absolute in_time)
8057{
8058 struct DVPathEntryP *dhops;
8059 char buf[sizeof(struct TransportDVLearnMessage)
8060 + (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
8061 struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
8062 struct GNUNET_TIME_Relative nnd;
8063 const struct GNUNET_PeerIdentity *my_identity;
8064
8065 /* compute message for forwarding */
8067 "Forwarding DV learn message originating from %s to %s\n",
8068 GNUNET_i2s (&msg->initiator),
8069 GNUNET_i2s2 (next_hop));
8072 fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
8073 + (nhops + 1) * sizeof(struct DVPathEntryP));
8074 fwd->num_hops = htons (nhops + 1);
8075 fwd->bidirectional = htons (bi_history);
8078 msg->non_network_delay));
8080 fwd->init_sig = msg->init_sig;
8081 fwd->initiator = msg->initiator;
8082 fwd->challenge = msg->challenge;
8083 fwd->monotonic_time = msg->monotonic_time;
8084
8087
8088 dhops = (struct DVPathEntryP *) &fwd[1];
8089 GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
8090 dhops[nhops].hop = *my_identity;
8091 {
8092 struct DvHopPS dhp = {
8094 .purpose.size = htonl (sizeof(dhp)),
8095 .pred = (0 == nhops) ? msg->initiator : dhops[nhops - 1].hop,
8096 .succ = *next_hop,
8098 };
8099 struct SignDhpCls *sign_dhp_cls = GNUNET_new (struct SignDhpCls);
8100 sign_dhp_cls->dhops = dhops;
8101 sign_dhp_cls->nhops = nhops;
8102 sign_dhp_cls->next_hop = next_hop;
8103 sign_dhp_cls->fwd = fwd;
8104 sign_dhp_cls->pr = GNUNET_new (struct PilsRequest);
8107 sign_dhp_cls->pr);
8108 sign_dhp_cls->pr->op =
8110 &dhp.purpose,
8112 sign_dhp_cls);
8113 }
8114}
8115
8116
8126static int
8128 struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
8129 const struct GNUNET_PeerIdentity *init,
8130 const struct GNUNET_CRYPTO_ChallengeNonceP *challenge,
8131 const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
8132{
8133 struct DvInitPS ip = { .purpose.purpose = htonl (
8135 .purpose.size = htonl (sizeof(ip)),
8136 .monotonic_time = sender_monotonic_time,
8137 .challenge = *challenge };
8138
8139 if (
8140 GNUNET_OK !=
8142 &ip,
8143 init_sig,
8144 &init->public_key))
8145 {
8146 GNUNET_break_op (0);
8147 return GNUNET_SYSERR;
8148 }
8149 return GNUNET_OK;
8150}
8151
8152
8157{
8161 const struct TransportDVLearnMessage *dvl;
8162
8166 const struct DVPathEntryP *hops;
8167
8172
8177
8181 unsigned int num_eligible;
8182
8186 unsigned int num_selections;
8187
8191 uint16_t nhops;
8192
8196 uint16_t bi_history;
8197};
8198
8199
8208static int
8209dv_neighbour_selection (void *cls,
8210 const struct GNUNET_PeerIdentity *pid,
8211 void *value)
8212{
8213 struct NeighbourSelectionContext *nsc = cls;
8214
8215 (void) value;
8216 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8217 return GNUNET_YES; /* skip initiator */
8218 for (unsigned int i = 0; i < nsc->nhops; i++)
8219 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8220 return GNUNET_YES;
8221 /* skip peers on path */
8222 nsc->num_eligible++;
8223 return GNUNET_YES;
8224}
8225
8226
8237static int
8238dv_neighbour_transmission (void *cls,
8239 const struct GNUNET_PeerIdentity *pid,
8240 void *value)
8241{
8242 struct NeighbourSelectionContext *nsc = cls;
8243
8245 "transmission %s\n",
8246 GNUNET_i2s (pid));
8247 (void) value;
8248 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8249 return GNUNET_YES; /* skip initiator */
8250 for (unsigned int i = 0; i < nsc->nhops; i++)
8251 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8252 return GNUNET_YES;
8253 /* skip peers on path */
8254 for (unsigned int i = 0; i < nsc->num_selections; i++)
8255 {
8256 if (nsc->selections[i] == nsc->num_eligible)
8257 {
8259 nsc->dvl,
8260 nsc->bi_history,
8261 nsc->nhops,
8262 nsc->hops,
8263 nsc->in_time);
8264 break;
8265 }
8266 }
8267 nsc->num_eligible++;
8268 return GNUNET_YES;
8269}
8270
8271
8315static unsigned int
8316calculate_fork_degree (unsigned int hops_taken,
8317 unsigned int neighbour_count,
8318 unsigned int eligible_count)
8319{
8320 double target_total = 50.0; /* FIXME: use LOG(NSE)? */
8321 double eligible_ratio =
8322 ((double) eligible_count) / ((double) neighbour_count);
8323 double boost_factor = eligible_ratio * eligible_ratio;
8324 unsigned int rnd;
8325 double left;
8326
8327 if (hops_taken >= 64)
8328 {
8329 GNUNET_break (0);
8330 return 0; /* precaution given bitshift below */
8331 }
8332 for (unsigned int i = 1; i < hops_taken; i++)
8333 {
8334 /* For each hop, subtract the expected number of targets
8335 reached at distance d (so what remains divided by 2^d) */
8336 target_total -= (target_total * boost_factor / (1LLU << i));
8337 }
8338 rnd =
8339 (unsigned int) floor (target_total * boost_factor / (1LLU << hops_taken));
8340 /* round up or down probabilistically depending on how close we were
8341 when floor()ing to rnd */
8342 left = target_total - (double) rnd;
8343 if (UINT32_MAX * left >
8345 rnd++; /* round up */
8347 "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
8348 hops_taken,
8349 rnd,
8350 eligible_count,
8351 neighbour_count);
8352 return rnd;
8353}
8354
8355
8362static void
8363neighbour_store_dvmono_cb (void *cls, int success)
8364{
8365 struct Neighbour *n = cls;
8366
8367 n->sc = NULL;
8368 if (GNUNET_YES != success)
8370 "Failed to store other peer's monotonic time in peerstore!\n");
8371}
8372
8373
8374static struct GNUNET_TIME_Relative
8376{
8377 struct GNUNET_TIME_Relative host_latency_sum;
8378 struct GNUNET_TIME_Relative latency;
8379 struct GNUNET_TIME_Relative network_latency;
8380 uint16_t nhops = ntohs (dvl->num_hops);;
8381
8382 /* We initiated this, learn the forward path! */
8383 host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
8384
8385 // Need also something to lookup initiation time
8386 // to compute RTT! -> add RTT argument here?
8388 dvl->monotonic_time));
8389 GNUNET_assert (latency.rel_value_us >= host_latency_sum.rel_value_us);
8390 // latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
8391 // (based on dvl->challenge, we can identify time of origin!)
8392
8393 network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
8394 /* assumption: latency on all links is the same */
8395 network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
8396
8397 return network_latency;
8398}
8399
8400
8408static void
8409handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
8410{
8411 struct CommunicatorMessageContext *cmc = cls;
8413 int bi_hop;
8414 uint16_t nhops;
8415 uint16_t bi_history;
8416 const struct DVPathEntryP *hops;
8417 int do_fwd;
8418 int did_initiator;
8419 struct GNUNET_TIME_Absolute in_time;
8420 struct Neighbour *n;
8421 const struct GNUNET_PeerIdentity *my_identity;
8422
8423 nhops = ntohs (dvl->num_hops); /* 0 = sender is initiator */
8424 bi_history = ntohs (dvl->bidirectional);
8425 hops = (const struct DVPathEntryP *) &dvl[1];
8426 if (0 == nhops)
8427 {
8428 /* sanity check */
8429 if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
8430 {
8431 GNUNET_break (0);
8432 finish_cmc_handling (cmc);
8433 return;
8434 }
8435 }
8436 else
8437 {
8439 "handle dv learn message last hop %s\n",
8440 GNUNET_i2s (&hops[nhops - 1].hop));
8441 /* sanity check */
8442 if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
8443 {
8444 GNUNET_break (0);
8445 finish_cmc_handling (cmc);
8446 return;
8447 }
8448 }
8449
8451 cc = cmc->tc->details.communicator.cc;
8452 bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
8453 cc); // FIXME: add bi-directional flag to cc?
8454 in_time = GNUNET_TIME_absolute_get ();
8455
8456 /* continue communicator here, everything else can happen asynchronous! */
8457 finish_cmc_handling (cmc);
8458
8459 n = lookup_neighbour (&dvl->initiator);
8460 if (NULL != n)
8461 {
8462 if ((n->dv_monotime_available == GNUNET_YES) &&
8465 {
8467 "DV learn from %s discarded due to time travel",
8468 GNUNET_i2s (&dvl->initiator));
8470 "# DV learn discarded due to time travel",
8471 1,
8472 GNUNET_NO);
8473 return;
8474 }
8476 &dvl->initiator,
8477 &dvl->challenge,
8478 &dvl->init_sig))
8479 {
8481 "DV learn signature from %s invalid\n",
8482 GNUNET_i2s (&dvl->initiator));
8483 GNUNET_break_op (0);
8484 return;
8485 }
8488 {
8489 if (NULL != n->sc)
8490 {
8492 "store cancel\n");
8494 }
8495 n->sc =
8497 "transport",
8498 &dvl->initiator,
8500 &dvl->monotonic_time,
8501 sizeof(dvl->monotonic_time),
8505 n);
8506 }
8507 }
8508
8511
8512 /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
8513 If signature verification load too high, implement random drop strategy */
8514 for (unsigned int i = 0; i < nhops; i++)
8515 {
8516 struct DvHopPS dhp = { .purpose.purpose =
8518 .purpose.size = htonl (sizeof(dhp)),
8519 .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
8520 .succ = (nhops == i + 1) ? *my_identity
8521 : hops[i + 1].hop,
8522 .challenge = dvl->challenge };
8523
8524 if (GNUNET_OK !=
8526 &dhp,
8527 &hops[i].hop_sig,
8528 &hops[i].hop.public_key))
8529 {
8531 "DV learn from %s signature of hop %u invalid\n",
8532 GNUNET_i2s (&dvl->initiator),
8533 i);
8535 "signature of hop %s invalid\n",
8536 GNUNET_i2s (&hops[i].hop));
8538 "pred %s\n",
8539 GNUNET_i2s (&dhp.pred));
8541 "succ %s\n",
8542 GNUNET_i2s (&dhp.succ));
8544 "hash %s\n",
8545 GNUNET_sh2s (&dhp.challenge.value));
8546 GNUNET_break_op (0);
8547 return;
8548 }
8549 }
8550 if (GNUNET_EXTRA_LOGGING > 0)
8551 {
8552 char *path;
8553
8554 path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
8555 for (unsigned int i = 0; i < nhops; i++)
8556 {
8557 char *tmp;
8558
8559 GNUNET_asprintf (&tmp,
8560 "%s%s%s",
8561 path,
8562 (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
8563 GNUNET_i2s (&hops[i].hop));
8564 GNUNET_free (path);
8565 path = tmp;
8566 }
8568 "Received DVInit via %s%s%s\n",
8569 path,
8570 bi_hop ? "<->" : "-->",
8572 GNUNET_free (path);
8573 }
8574 do_fwd = GNUNET_YES;
8575 if (0 == GNUNET_memcmp (my_identity, &dvl->initiator))
8576 {
8577 struct GNUNET_PeerIdentity path[nhops + 1];
8578 struct GNUNET_TIME_Relative network_latency;
8579
8580 /* We initiated this, learn the forward path! */
8581 path[0] = *my_identity;
8582 path[1] = hops[0].hop;
8583
8584 network_latency = get_network_latency (dvl);
8585
8586 for (unsigned int i = 2; i <= nhops; i++)
8587 {
8588 struct GNUNET_TIME_Relative ilat;
8589
8590 /* assumption: linear latency increase per hop */
8591 ilat = GNUNET_TIME_relative_multiply (network_latency, i);
8592 path[i] = hops[i - 1].hop;
8594 "Learned path with %u hops to %s with latency %s\n",
8595 i,
8596 GNUNET_i2s (&path[i]),
8598 learn_dv_path (path,
8599 i + 1,
8600 ilat,
8603 }
8604 /* as we initiated, do not forward again (would be circular!) */
8605 do_fwd = GNUNET_NO;
8606 return;
8607 }
8608 if (bi_hop)
8609 {
8610 /* last hop was bi-directional, we could learn something here! */
8611 struct GNUNET_PeerIdentity path[nhops + 2];
8612 struct GNUNET_TIME_Relative ilat;
8613 struct GNUNET_TIME_Relative network_latency;
8614
8615 path[0] = *my_identity;
8616 path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
8617 for (unsigned int i = 0; i < nhops; i++)
8618 {
8619 int iret;
8620
8621 if (0 == (bi_history & (1 << i)))
8622 break; /* i-th hop not bi-directional, stop learning! */
8623 if (i == nhops - 1)
8624 {
8625 path[i + 2] = dvl->initiator;
8626 }
8627 else
8628 {
8629 path[i + 2] = hops[nhops - i - 2].hop;
8630 }
8631
8633 "Learned inverse path with %u hops to %s\n",
8634 i + 2,
8635 GNUNET_i2s (&path[i + 2]));
8636 network_latency = get_network_latency (dvl);
8637 ilat = GNUNET_TIME_relative_multiply (network_latency, i + 2);
8638 iret = learn_dv_path (path,
8639 i + 3,
8640 ilat,
8643 if (GNUNET_SYSERR == iret)
8644 {
8645 /* path invalid or too long to be interesting for US, thus should also
8646 not be interesting to our neighbours, cut path when forwarding to
8647 'i' hops, except of course for the one that goes back to the
8648 initiator */
8650 "# DV learn not forwarded due invalidity of path",
8651 1,
8652 GNUNET_NO);
8653 do_fwd = GNUNET_NO;
8654 break;
8655 }
8656 if ((GNUNET_NO == iret) && (nhops == i + 1))
8657 {
8658 /* we have better paths, and this is the longest target,
8659 so there cannot be anything interesting later */
8661 "# DV learn not forwarded, got better paths",
8662 1,
8663 GNUNET_NO);
8664 do_fwd = GNUNET_NO;
8665 break;
8666 }
8667 }
8668 }
8669 if (MAX_DV_HOPS_ALLOWED == nhops)
8670 {
8671 /* At limit, we're out of here! */
8672 return;
8673 }
8674
8675 /* Forward to initiator, if path non-trivial and possible */
8676 bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
8677 did_initiator = GNUNET_NO;
8678 if ((1 <= nhops) &&
8679 (GNUNET_YES ==
8681 {
8682 /* send back to origin! */
8684 "Sending DVL back to initiator %s\n",
8685 GNUNET_i2s (&dvl->initiator));
8686 forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
8687 did_initiator = GNUNET_YES;
8688 }
8689 /* We forward under two conditions: either we still learned something
8690 ourselves (do_fwd), or the path was darn short and thus the initiator is
8691 likely to still be very interested in this (and we did NOT already
8692 send it back to the initiator) */
8693 if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
8694 (GNUNET_NO == did_initiator)))
8695 {
8696 /* Pick random neighbours that are not yet on the path */
8697 struct NeighbourSelectionContext nsc;
8698 unsigned int n_cnt;
8699
8701 nsc.nhops = nhops;
8702 nsc.dvl = dvl;
8703 nsc.bi_history = bi_history;
8704 nsc.hops = hops;
8705 nsc.in_time = in_time;
8706 nsc.num_eligible = 0;
8709 &nsc);
8710 if (0 == nsc.num_eligible)
8711 return; /* done here, cannot forward to anyone else */
8713 nsc.num_selections =
8716 "Forwarding DVL to %u other peers\n",
8717 nsc.num_selections);
8718 for (unsigned int i = 0; i < nsc.num_selections; i++)
8719 nsc.selections[i] =
8720 (nsc.num_selections == n_cnt)
8721 ? i /* all were selected, avoid collisions by chance */
8723 nsc.num_eligible = 0;
8726 &nsc);
8727 }
8728}
8729
8730
8738static int
8739check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
8740{
8741 uint16_t size = ntohs (dvb->header.size);
8742 uint16_t num_hops = ntohs (dvb->num_hops);
8743 const struct GNUNET_PeerIdentity *hops =
8744 (const struct GNUNET_PeerIdentity *) &dvb[1];
8745 const struct GNUNET_PeerIdentity *my_identity;
8746
8747 (void) cls;
8748 if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
8749 + sizeof(struct GNUNET_MessageHeader))
8750 {
8751 GNUNET_break_op (0);
8752 return GNUNET_SYSERR;
8753 }
8754
8757
8758 /* This peer must not be on the path */
8759 for (unsigned int i = 0; i < num_hops; i++)
8760 if (0 == GNUNET_memcmp (&hops[i], my_identity))
8761 {
8762 GNUNET_break_op (0);
8763 return GNUNET_SYSERR;
8764 }
8765 return GNUNET_YES;
8766}
8767
8768
8781static void
8782forward_dv_box (struct Neighbour *next_hop,
8783 struct TransportDVBoxMessage *hdr,
8784 uint16_t total_hops,
8785 uint16_t num_hops,
8786 const struct GNUNET_PeerIdentity *hops,
8787 const void *enc_payload,
8788 uint16_t enc_payload_size)
8789{
8790 struct VirtualLink *vl = next_hop->vl;
8791 struct PendingMessage *pm;
8792 size_t msg_size = sizeof(struct TransportDVBoxMessage)
8793 + num_hops * sizeof(struct GNUNET_PeerIdentity)
8794 + enc_payload_size;
8795 char *buf;
8796 char msg_buf[msg_size] GNUNET_ALIGN;
8797 struct GNUNET_PeerIdentity *dhops;
8798
8799 hdr->num_hops = htons (num_hops);
8800 hdr->total_hops = htons (total_hops);
8801 hdr->header.size = htons (msg_size);
8802 memcpy (msg_buf, hdr, sizeof(*hdr));
8803 dhops = (struct GNUNET_PeerIdentity *) &msg_buf[sizeof(struct
8805 ;
8806 memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
8807 memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
8808
8809 if (GNUNET_YES == ntohs (hdr->without_fc))
8810 {
8812 "Forwarding control message (payload size %u) in DV Box to next hop %s (%u/%u) \n",
8813 enc_payload_size,
8814 GNUNET_i2s (&next_hop->pid),
8815 (unsigned int) num_hops,
8816 (unsigned int) total_hops);
8817 route_via_neighbour (next_hop, (const struct
8818 GNUNET_MessageHeader *) msg_buf,
8820 }
8821 else
8822 {
8823 pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
8825 "2 created pm %p storing vl %p \n",
8826 pm,
8827 vl);
8828 pm->pmt = PMT_DV_BOX;
8829 pm->vl = vl;
8830 pm->target = next_hop->pid;
8832 pm->logging_uuid = logging_uuid_gen++;
8834 pm->bytes_msg = msg_size;
8835 buf = (char *) &pm[1];
8836 memcpy (buf, msg_buf, msg_size);
8837
8839 "Created pending message %" PRIu64
8840 " for DV Box with next hop %s (%u/%u)\n",
8841 pm->logging_uuid,
8842 GNUNET_i2s (&next_hop->pid),
8843 (unsigned int) num_hops,
8844 (unsigned int) total_hops);
8845
8846 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
8847 {
8849 vl->pending_msg_head,
8850 vl->pending_msg_tail,
8851 pm);
8852
8854 }
8855 else
8856 {
8858 "The virtual link is not ready for forwarding a DV Box with payload, storing PendingMessage in ring buffer.\n");
8859
8861 {
8863
8864 GNUNET_free (pm_old);
8865 }
8868 {
8871 }
8872 else
8874
8876 "%u items stored in DV ring buffer\n",
8879 }
8880 }
8881}
8882
8883
8889static void
8890free_backtalker (struct Backtalker *b)
8891{
8892 if (NULL != b->get)
8893 {
8895 b->get = NULL;
8896 GNUNET_assert (NULL != b->cmc);
8898 b->cmc = NULL;
8899 }
8900 if (NULL != b->task)
8901 {
8903 b->task = NULL;
8904 }
8905 if (NULL != b->sc)
8906 {
8908 "store cancel\n");
8910 b->sc = NULL;
8911 }
8913 "Removing backtalker for %s\n",
8914 GNUNET_i2s (&b->pid));
8916 GNUNET_YES ==
8918 GNUNET_free (b);
8919}
8920
8921
8930static int
8931free_backtalker_cb (void *cls,
8932 const struct GNUNET_PeerIdentity *pid,
8933 void *value)
8934{
8935 struct Backtalker *b = value;
8936
8937 (void) cls;
8938 (void) pid;
8939 free_backtalker (b);
8940 return GNUNET_OK;
8941}
8942
8943
8949static void
8950backtalker_timeout_cb (void *cls)
8951{
8952 struct Backtalker *b = cls;
8953
8955 "backtalker timeout.\n");
8956 b->task = NULL;
8958 {
8960 return;
8961 }
8962 GNUNET_assert (NULL == b->sc);
8963 free_backtalker (b);
8964}
8965
8966
8975static void
8976backtalker_monotime_cb (void *cls,
8977 const struct GNUNET_PEERSTORE_Record *record,
8978 const char *emsg)
8979{
8980 struct Backtalker *b = cls;
8981 struct GNUNET_TIME_AbsoluteNBO *mtbe;
8982 struct GNUNET_TIME_Absolute mt;
8983
8984 (void) emsg;
8985 if (NULL == record)
8986 {
8987 /* we're done with #backtalker_monotime_cb() invocations,
8988 continue normal processing */
8989 b->get = NULL;
8990 GNUNET_assert (NULL != b->cmc);
8991 b->cmc->mh = (const struct GNUNET_MessageHeader *) &b[1];
8992 if (0 != b->body_size)
8994 else
8996 b->cmc = NULL;
8997 return;
8998 }
8999 if (sizeof(*mtbe) != record->value_size)
9000 {
9002 GNUNET_break (0);
9003 return;
9004 }
9005 mtbe = record->value;
9006 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
9007 if (mt.abs_value_us > b->monotonic_time.abs_value_us)
9008 {
9010 "Backtalker message from %s dropped, monotime in the past\n",
9011 GNUNET_i2s (&b->pid));
9013 GST_stats,
9014 "# Backchannel messages dropped: monotonic time not increasing",
9015 1,
9016 GNUNET_NO);
9017 b->monotonic_time = mt;
9018 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
9019 */
9020 b->body_size = 0;
9021 }
9023}
9024
9025
9033static void
9034backtalker_monotime_store_cb (void *cls, int success)
9035{
9036 struct Backtalker *b = cls;
9037
9038 if (GNUNET_OK != success)
9039 {
9041 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
9042 }
9043 b->sc = NULL;
9044 if (NULL != b->task)
9045 {
9047 b->task = NULL;
9048 }
9050}
9051
9052
9058static void
9060{
9061 struct GNUNET_TIME_AbsoluteNBO mtbe;
9062
9063 if (NULL != b->sc)
9064 {
9066 "store cancel before store with sc %p\n",
9067 b->sc);
9068 /*GNUNET_PEERSTORE_store_cancel (b->sc);
9069 b->sc = NULL;*/
9071 "store cancel before store with sc %p is null\n",
9072 b->sc);
9073 }
9074 else
9075 {
9077 b->task = NULL;
9078 }
9080 b->sc =
9082 "transport",
9083 &b->pid,
9085 &mtbe,
9086 sizeof(mtbe),
9090 b);
9091}
9092
9093
9094struct DecapsDvBoxCls
9095{
9097 const struct TransportDVBoxMessage *dvb;
9098 struct PilsRequest *pr;
9099};
9100
9101
9102static void
9103decaps_dv_box_cb (void *cls, const struct GNUNET_ShortHashCode *km)
9104{
9105 struct DecapsDvBoxCls *decaps_dv_box_cls = cls;
9106 struct CommunicatorMessageContext *cmc = decaps_dv_box_cls->cmc;
9107 const struct TransportDVBoxMessage *dvb = decaps_dv_box_cls->dvb;
9108 struct DVKeyState key;
9109 const char *hdr;
9110 size_t hdr_len;
9111 struct GNUNET_HashCode hmac;
9112
9113 decaps_dv_box_cls->pr->op = NULL;
9116 decaps_dv_box_cls->pr);
9117 GNUNET_free (decaps_dv_box_cls->pr);
9118 if (NULL == km)
9119 {
9120 GNUNET_break_op (0);
9121 finish_cmc_handling (cmc);
9122 return;
9123 }
9124 dv_setup_key_state_from_km (km, &dvb->iv, &key);
9125 hdr = (const char *) &dvb[1];
9126 hdr_len = ntohs (dvb->orig_size) - sizeof(*dvb) - sizeof(struct
9128 * ntohs (dvb->total_hops);
9129
9130 dv_hmac (&key, &hmac, hdr, hdr_len);
9131 if (0 != GNUNET_memcmp (&hmac, &dvb->hmac))
9132 {
9133 /* HMAC mismatch, discard! */
9134 GNUNET_break_op (0);
9135 finish_cmc_handling (cmc);
9136 return;
9137 }
9138 /* begin actual decryption */
9139 {
9140 struct Backtalker *b;
9141 struct GNUNET_TIME_Absolute monotime;
9142 struct TransportDVBoxPayloadP ppay = { 0 };
9143 char body[hdr_len - sizeof(ppay)] GNUNET_ALIGN;
9144 const struct GNUNET_MessageHeader *mh;
9145
9146 GNUNET_assert (hdr_len >=
9147 sizeof(ppay) + sizeof(struct GNUNET_MessageHeader));
9148 if (GNUNET_OK != dv_decrypt (&key, &ppay, hdr, sizeof(ppay)))
9149 {
9151 "Error decrypting DV payload header\n");
9152 GNUNET_break_op (0);
9153 finish_cmc_handling (cmc);
9154 return;
9155 }
9156 if (GNUNET_OK != dv_decrypt (&key, body,
9157 &hdr[sizeof(ppay)], hdr_len - sizeof(ppay)))
9158 {
9160 "Error decrypting DV payload\n");
9161 GNUNET_break_op (0);
9162 finish_cmc_handling (cmc);
9163 return;
9164 }
9165 mh = (const struct GNUNET_MessageHeader *) body;
9166 dv_key_clean (&key);
9167 if (ntohs (mh->size) != sizeof(body))
9168 {
9169 GNUNET_break_op (0);
9170 finish_cmc_handling (cmc);
9171 return;
9172 }
9173 /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
9174 switch (ntohs (mh->type))
9175 {
9177 GNUNET_break_op (0);
9178 finish_cmc_handling (cmc);
9179 return;
9180
9182 GNUNET_break_op (0);
9183 finish_cmc_handling (cmc);
9184 return;
9185
9186 default:
9187 /* permitted, continue */
9188 break;
9189 }
9190 monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time);
9192 "Decrypted backtalk from %s\n",
9193 GNUNET_i2s (&ppay.sender));
9195 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
9196 {
9198 GST_stats,
9199 "# Backchannel messages dropped: monotonic time not increasing",
9200 1,
9201 GNUNET_NO);
9202 finish_cmc_handling (cmc);
9203 return;
9204 }
9205 if ((NULL == b) ||
9206 (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
9207 {
9208 /* Check signature */
9209 const struct GNUNET_PeerIdentity *my_identity;
9210 struct EphemeralConfirmationPS ec;
9211
9214
9215 ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL);
9216 ec.target = *my_identity;
9217 ec.ephemeral_key = dvb->ephemeral_key;
9218 ec.purpose.size = htonl (sizeof(ec));
9219 ec.sender_monotonic_time = ppay.monotonic_time;
9220 if (
9221 GNUNET_OK !=
9224 &ec,
9225 &ppay.sender_sig,
9226 &ppay.sender.public_key))
9227 {
9228 /* Signature invalid, discard! */
9229 GNUNET_break_op (0);
9230 finish_cmc_handling (cmc);
9231 return;
9232 }
9233 }
9234 /* Update sender, we now know the real origin! */
9236 "DVBox received for me from %s via %s\n",
9237 GNUNET_i2s2 (&ppay.sender),
9238 GNUNET_i2s (&cmc->im.sender));
9239 cmc->im.sender = ppay.sender;
9240
9241 if (NULL != b)
9242 {
9243 /* update key cache and mono time */
9244 b->last_ephemeral = dvb->ephemeral_key;
9245 b->monotonic_time = monotime;
9247 b->timeout =
9249 cmc->mh = mh;
9251 return;
9252 }
9253 /* setup data structure to cache signature AND check
9254 monotonic time with PEERSTORE before forwarding backchannel payload */
9255 b = GNUNET_malloc (sizeof(struct Backtalker) + sizeof(body));
9256 b->pid = ppay.sender;
9257 b->body_size = sizeof(body);
9258 memcpy (&b[1], body, sizeof(body));
9262 &b->pid,
9263 b,
9265 b->monotonic_time = monotime; /* NOTE: to be checked still! */
9266 b->cmc = cmc;
9267 b->timeout =
9270 b->get =
9272 "transport",
9273 &b->pid,
9276 b);
9277 } /* end actual decryption */
9278}
9279
9280
9288static void
9289handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
9290{
9291 struct CommunicatorMessageContext *cmc = cls;
9292 uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
9293 uint16_t num_hops = ntohs (dvb->num_hops);
9294 const struct GNUNET_PeerIdentity *hops =
9295 (const struct GNUNET_PeerIdentity *) &dvb[1];
9296 const char *enc_payload = (const char *) &hops[num_hops];
9297 uint16_t enc_payload_size =
9298 size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
9299 struct DecapsDvBoxCls *decaps_dv_box_cls;
9300 const struct GNUNET_PeerIdentity *my_identity;
9301
9304
9305 if (GNUNET_EXTRA_LOGGING > 0)
9306 {
9307 char *path;
9308
9310 for (unsigned int i = 0; i < num_hops; i++)
9311 {
9312 char *tmp;
9313
9314 GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
9315 GNUNET_free (path);
9316 path = tmp;
9317 }
9319 "Received DVBox with remaining path %s\n",
9320 path);
9321 GNUNET_free (path);
9322 }
9323
9324 if (num_hops > 0)
9325 {
9326 /* We're trying from the end of the hops array, as we may be
9327 able to find a shortcut unknown to the origin that way */
9328 for (int i = num_hops - 1; i >= 0; i--)
9329 {
9330 struct Neighbour *n;
9331
9332 if (0 == GNUNET_memcmp (&hops[i], my_identity))
9333 {
9334 GNUNET_break_op (0);
9335 finish_cmc_handling (cmc);
9336 return;
9337 }
9338 n = lookup_neighbour (&hops[i]);
9339 if (NULL == n)
9340 continue;
9342 "Skipping %u/%u hops ahead while routing DV Box\n",
9343 i,
9344 num_hops);
9345
9346 forward_dv_box (n,
9347 (struct TransportDVBoxMessage *) dvb,
9348 ntohs (dvb->total_hops) + 1,
9349 num_hops - i - 1, /* number of hops left */
9350 &hops[i + 1], /* remaining hops */
9351 enc_payload,
9352 enc_payload_size);
9354 "# DV hops skipped routing boxes",
9355 i,
9356 GNUNET_NO);
9358 "# DV boxes routed (total)",
9359 1,
9360 GNUNET_NO);
9361 finish_cmc_handling (cmc);
9362 return;
9363 }
9364 /* Woopsie, next hop not in neighbours, drop! */
9366 "# DV Boxes dropped: next hop unknown",
9367 1,
9368 GNUNET_NO);
9369 finish_cmc_handling (cmc);
9370 return;
9371 }
9372 /* We are the target. Unbox and handle message. */
9374 "# DV boxes opened (ultimate target)",
9375 1,
9376 GNUNET_NO);
9377 cmc->total_hops = ntohs (dvb->total_hops);
9378
9379 {
9380 // DH key derivation with received DV, could be garbage.
9381 decaps_dv_box_cls = GNUNET_new (struct DecapsDvBoxCls);
9382 decaps_dv_box_cls->cmc = cmc;
9383 decaps_dv_box_cls->dvb = dvb;
9384 decaps_dv_box_cls->pr = GNUNET_new (struct PilsRequest);
9385
9388 decaps_dv_box_cls->pr);
9389 decaps_dv_box_cls->pr->op = GNUNET_PILS_kem_decaps (pils,
9390 &dvb->ephemeral_key,
9392 decaps_dv_box_cls);
9393 }
9394 // TODO keep track of cls and potentially clean
9395}
9396
9397
9405static int
9406check_incoming_msg (void *cls,
9407 const struct GNUNET_TRANSPORT_IncomingMessage *im)
9408{
9409 struct TransportClient *tc = cls;
9410
9411 if (CT_COMMUNICATOR != tc->type)
9412 {
9413 GNUNET_break (0);
9414 return GNUNET_SYSERR;
9415 }
9417 return GNUNET_OK;
9418}
9419
9420
9425{
9429 const char *address;
9430
9434 struct ValidationState *vs;
9435};
9436
9437
9447static int
9448check_known_address (void *cls,
9449 const struct GNUNET_PeerIdentity *pid,
9450 void *value)
9451{
9452 struct CheckKnownAddressContext *ckac = cls;
9453 struct ValidationState *vs = value;
9454
9455 (void) pid;
9456 if (0 != strcmp (vs->address, ckac->address))
9457 return GNUNET_OK;
9458 ckac->vs = vs;
9459 return GNUNET_NO;
9460}
9461
9462
9468static void
9469validation_start_cb (void *cls);
9470
9471
9479static void
9481 struct GNUNET_TIME_Absolute new_time)
9482{
9484
9485 if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
9486 return; /* be lazy */
9487 vs->next_challenge = new_time;
9488 if (NULL == vs->hn)
9489 vs->hn =
9491 else
9494 (NULL != validation_task))
9495 return;
9496 if (NULL != validation_task)
9498 /* randomize a bit */
9501 MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
9502 new_time = GNUNET_TIME_absolute_add (new_time, delta);
9505}
9506
9507
9514static void
9516 const char *address)
9517{
9518 struct GNUNET_TIME_Absolute now;
9519 struct ValidationState *vs;
9520 struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
9521
9523 pid,
9525 &ckac);
9526 if (NULL != (vs = ckac.vs))
9527 {
9528 /* if 'vs' is not currently valid, we need to speed up retrying the
9529 * validation */
9530 if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
9531 {
9532 /* reduce backoff as we got a fresh advertisement */
9533 vs->challenge_backoff =
9536 vs->challenge_backoff,
9537 2));
9540 vs->challenge_backoff));
9541 }
9542 return;
9543 }
9545 vs = GNUNET_new (struct ValidationState);
9546 vs->pid = *pid;
9547 vs->valid_until =
9549 vs->first_challenge_use = now;
9550 vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
9552 &vs->challenge,
9553 sizeof(vs->challenge));
9554 vs->address = GNUNET_strdup (address);
9555 GNUNET_CRYPTO_hash (vs->address, strlen (vs->address), &vs->hc);
9557 "Starting address validation `%s' of peer %s using challenge %s\n",
9558 address,
9559 GNUNET_i2s (pid),
9560 GNUNET_sh2s (&vs->challenge.value));
9564 &vs->pid,
9565 vs,
9568}
9569
9570
9571static struct Queue *
9572find_queue (const struct GNUNET_PeerIdentity *pid, const char *address);
9573
9574
9575static void
9576suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address);
9577
9578
9579static void
9580hello_for_incoming_cb (void *cls,
9581 const struct GNUNET_PeerIdentity *pid,
9582 const char *uri)
9583{
9584 struct Queue *q;
9585 int pfx_len;
9586 const char *eou;
9587 char *address;
9588 (void) cls;
9589
9590 eou = strstr (uri,
9591 "://");
9592 pfx_len = eou - uri;
9593 eou += 3;
9595 "%.*s-%s",
9596 pfx_len,
9597 uri,
9598 eou);
9599
9601 "helo for client %s\n",
9602 address);
9603 q = find_queue (pid, address);
9604 if (NULL == q)
9605 {
9607 }
9608 else
9611}
9612
9613
9621static void
9622handle_hello_for_incoming (void *cls,
9623 const struct GNUNET_PEERSTORE_Record *record,
9624 const char *emsg)
9625{
9626 struct IncomingRequest *ir = cls;
9628 struct GNUNET_MessageHeader *hello;
9629 const struct GNUNET_PeerIdentity *my_identity;
9630
9631 if (NULL != emsg)
9632 {
9634 "Got failure from PEERSTORE: %s\n",
9635 emsg);
9636 return;
9637 }
9638 hello = record->value;
9641 if (0 == GNUNET_memcmp (&record->peer, my_identity))
9642 {
9644 return;
9645 }
9646 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
9649 NULL);
9650 GNUNET_HELLO_parser_free (parser);
9651}
9652
9653
9654static void
9656{
9658 "Error in PEERSTORE monitoring\n");
9659}
9660
9661
9662static void
9664{
9666 "Done with initial PEERSTORE iteration during monitoring\n");
9667}
9668
9669
9670struct SignTValidationCls
9671{
9674 struct PilsRequest *pr;
9675};
9676
9677
9678static void
9679sign_t_validation_cb (void *cls,
9680 const struct GNUNET_PeerIdentity *pid,
9681 const struct GNUNET_CRYPTO_EddsaSignature *sig)
9682{
9683 struct SignTValidationCls *sign_t_validation_cls = cls;
9684 struct CommunicatorMessageContext *cmc = sign_t_validation_cls->cmc;
9685 struct TransportValidationResponseMessage tvr = sign_t_validation_cls->tvr;
9686 struct VirtualLink *vl;
9687 struct Neighbour *n;
9688 struct IncomingRequest *ir;
9689 struct GNUNET_PeerIdentity sender;
9690
9691 sign_t_validation_cls->pr->op = NULL;
9694 sign_t_validation_cls->pr);
9695 GNUNET_free (sign_t_validation_cls->pr);
9696 tvr.signature = *sig;
9697 sender = cmc->im.sender;
9698 vl = lookup_virtual_link (&sender);
9699 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9700 {
9701 // route_control_message_without_fc (&cmc->im.sender,
9703 &tvr.header,
9705 }
9706 else
9707 {
9708 /* Use route via neighbour */
9709 n = lookup_neighbour (&sender);
9710 if (NULL != n)
9711 route_via_neighbour (n, &tvr.header,
9714 }
9715
9716 finish_cmc_handling (cmc);
9717 if (NULL != vl)
9718 return;
9719
9720 /* For us, the link is still down, but we need bi-directional
9721 connections (for flow-control and for this to be useful for
9722 CORE), so we must try to bring the link up! */
9723
9724 /* (1) Check existing queues, if any, we may be lucky! */
9725 n = lookup_neighbour (&sender);
9726 if (NULL != n)
9727 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
9728 start_address_validation (&sender, q->address);
9729 /* (2) Also try to see if we have addresses in PEERSTORE for this peer
9730 we could use */
9731 for (ir = ir_head; NULL != ir; ir = ir->next)
9732 if (0 == GNUNET_memcmp (&ir->pid, &sender))
9733 return;
9734 /* we are already trying */
9735 ir = GNUNET_new (struct IncomingRequest);
9736 ir->pid = sender;
9738
9740 GNUNET_YES,
9741 "peerstore",
9742 NULL,
9745 NULL,
9747 NULL,
9749 ir);
9750 ir_total++;
9751 /* Bound attempts we do in parallel here, might otherwise get excessive */
9754};
9755
9756
9765static void
9767 void *cls,
9768 const struct TransportValidationChallengeMessage *tvc)
9769{
9770 struct CommunicatorMessageContext *cmc = cls;
9771 struct TransportValidationResponseMessage tvr = { 0 };
9772 struct GNUNET_TIME_RelativeNBO validity_duration;
9773
9774 /* DV-routed messages are not allowed for validation challenges */
9775 if (cmc->total_hops > 0)
9776 {
9777 GNUNET_break_op (0);
9778 finish_cmc_handling (cmc);
9779 return;
9780 }
9781 validity_duration = cmc->im.expected_address_validity;
9783 "Received address validation challenge %s\n",
9784 GNUNET_sh2s (&tvc->challenge.value));
9785 /* If we have a virtual link, we use this mechanism to signal the
9786 size of the flow control window, and to allow the sender
9787 to ask for increases. If for us the virtual link is still down,
9788 we will always give a window size of zero. */
9789 tvr.header.type =
9791 tvr.header.size = htons (sizeof(tvr));
9792 tvr.reserved = htonl (0);
9793 tvr.challenge = tvc->challenge;
9794 tvr.origin_time = tvc->sender_time;
9795 tvr.validity_duration = validity_duration;
9796 {
9797 /* create signature */
9798 struct TransportValidationPS tvp = {
9800 .purpose.size = htonl (sizeof(tvp)),
9801 .validity_duration = validity_duration,
9802 .challenge = tvc->challenge
9803 };
9804 struct SignTValidationCls *sign_t_validation_cls;
9805
9806 sign_t_validation_cls = GNUNET_new (struct SignTValidationCls);
9807 sign_t_validation_cls->cmc = cmc;
9808 sign_t_validation_cls->tvr = tvr;
9809 sign_t_validation_cls->pr = GNUNET_new (struct PilsRequest);
9812 sign_t_validation_cls->pr);
9813 sign_t_validation_cls->pr->op =
9815 &tvp.purpose,
9817 sign_t_validation_cls);
9818 }
9819}
9820
9821
9826{
9831
9835 struct ValidationState *vs;
9836};
9837
9838
9848static int
9849check_known_challenge (void *cls,
9850 const struct GNUNET_PeerIdentity *pid,
9851 void *value)
9852{
9853 struct CheckKnownChallengeContext *ckac = cls;
9854 struct ValidationState *vs = value;
9855
9856 (void) pid;
9857 if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
9858 return GNUNET_OK;
9859 ckac->vs = vs;
9860 return GNUNET_NO;
9861}
9862
9863
9871static void
9872peerstore_store_validation_cb (void *cls, int success)
9873{
9874 struct ValidationState *vs = cls;
9875
9876 vs->sc = NULL;
9877 if (GNUNET_YES == success)
9878 return;
9880 "# Peerstore failed to store foreign address",
9881 1,
9882 GNUNET_NO);
9883}
9884
9885
9893static struct Queue *
9894find_queue (const struct GNUNET_PeerIdentity *pid, const char *address)
9895{
9896 struct Neighbour *n;
9897
9898 n = lookup_neighbour (pid);
9899 if (NULL == n)
9900 return NULL;
9901 for (struct Queue *pos = n->queue_head; NULL != pos;
9902 pos = pos->next_neighbour)
9903 {
9904 if (0 == strcmp (pos->address, address))
9905 return pos;
9906 }
9907 return NULL;
9908}
9909
9910
9911static void
9913
9914static void
9915revalidation_start_cb (void *cls)
9916{
9917 struct ValidationState *vs = cls;
9918 struct Queue *q;
9919 struct GNUNET_TIME_Absolute now;
9920
9921 vs->revalidation_task = NULL;
9922 q = find_queue (&vs->pid, vs->address);
9923 if (NULL == q)
9924 {
9925 now = GNUNET_TIME_absolute_get ();
9926 vs->awaiting_queue = GNUNET_YES;
9927 suggest_to_connect (&vs->pid, vs->address);
9929 }
9930 else
9932}
9933
9934
9935static enum GNUNET_GenericReturnValue
9937 void *cls,
9938 const struct GNUNET_HashCode *key,
9939 void *value)
9940{
9941 (void) cls;
9943 "Key in revalidate map %s \n",
9944 GNUNET_h2s (key));
9945 return GNUNET_YES;
9946}
9947
9948
9957static void
9959 void *cls,
9960 const struct TransportValidationResponseMessage *tvr)
9961{
9962 struct CommunicatorMessageContext *cmc = cls;
9963 struct ValidationState *vs;
9964 struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
9965 .vs = NULL};
9966 struct GNUNET_TIME_Absolute origin_time;
9967 struct Queue *q;
9968 struct Neighbour *n;
9969 struct VirtualLink *vl;
9971 GST_cfg);
9972
9973 /* check this is one of our challenges */
9975 &cmc->im.sender,
9977 &ckac);
9978 if (NULL == (vs = ckac.vs))
9979 {
9980 /* This can happen simply if we 'forgot' the challenge by now,
9981 i.e. because we received the validation response twice */
9983 "# Validations dropped, challenge unknown",
9984 1,
9985 GNUNET_NO);
9987 "Validation response %s dropped, challenge unknown\n",
9988 GNUNET_sh2s (&tvr->challenge.value));
9989 finish_cmc_handling (cmc);
9990 return;
9991 }
9992
9993 /* sanity check on origin time */
9994 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
9995 if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
9996 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
9997 {
9999 "Diff first use %" PRIu64 " and last use %" PRIu64 "\n",
10000 vs->first_challenge_use.abs_value_us - origin_time.abs_value_us,
10001 origin_time.abs_value_us - vs->last_challenge_use.abs_value_us);
10002 GNUNET_break_op (0);
10003 finish_cmc_handling (cmc);
10004 return;
10005 }
10006
10007 {
10008 /* check signature */
10009 struct TransportValidationPS tvp = {
10011 .purpose.size = htonl (sizeof(tvp)),
10012 .validity_duration = tvr->validity_duration,
10013 .challenge = tvr->challenge
10014 };
10015
10016 if (
10017 GNUNET_OK !=
10019 &tvp,
10020 &tvr->signature,
10021 &cmc->im.sender.public_key))
10022 {
10023 GNUNET_break_op (0);
10024 finish_cmc_handling (cmc);
10025 return;
10026 }
10027 }
10028
10029 /* validity is capped by our willingness to keep track of the
10030 validation entry and the maximum the other peer allows */
10033 tvr->validity_duration),
10035 vs->validated_until =
10039 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
10040 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
10042 &vs->challenge,
10043 sizeof(vs->challenge));
10044 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
10045 vs->validated_until,
10046 GNUNET_TIME_relative_multiply (vs->validation_rtt,
10048 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, <, now))
10049 {
10051 "First challenge use is now %" PRIu64 " %s \n",
10052 vs->first_challenge_use.abs_value_us,
10053 GNUNET_sh2s (&vs->challenge.value));
10054 vs->first_challenge_use = now;
10055 }
10056 else
10058 "First challenge use is later %" PRIu64 " %s \n",
10059 vs->first_challenge_use.abs_value_us,
10060 GNUNET_sh2s (&vs->challenge.value));
10061 vs->last_challenge_use =
10062 GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
10063 update_next_challenge_time (vs, vs->first_challenge_use);
10065 "Validation response %s from %s accepted, address valid until %s\n",
10066 GNUNET_sh2s (&tvr->challenge.value),
10067 GNUNET_i2s (&cmc->im.sender),
10069 /*memcpy (&hkey,
10070 &hc,
10071 sizeof (hkey));*/
10073 "Key %s for address %s map size %u contains %u\n",
10074 GNUNET_h2s (&vs->hc),
10075 vs->address,
10078 &vs->hc));
10082 &vs->hc,
10083 vs,
10087 NULL);
10088 vs->revalidation_task =
10093 "transport",
10094 &cmc->im.sender,
10096 vs->address,
10097 strlen (vs->address) + 1,
10098 vs->valid_until,
10101 vs);
10102 finish_cmc_handling (cmc);
10103
10104 /* Finally, we now possibly have a confirmed (!) working queue,
10105 update queue status (if queue still is around) */
10106 q = find_queue (&vs->pid, vs->address);
10107 if (NULL == q)
10108 {
10110 "# Queues lost at time of successful validation",
10111 1,
10112 GNUNET_NO);
10113 return;
10114 }
10115 q->validated_until = vs->validated_until;
10116 q->pd.aged_rtt = vs->validation_rtt;
10117 n = q->neighbour;
10118 vl = lookup_virtual_link (&vs->pid);
10119 if (NULL == vl)
10120 {
10121 vl = GNUNET_new (struct VirtualLink);
10123 "Creating new virtual link %p to %s using direct neighbour!\n",
10124 vl,
10125 GNUNET_i2s (&vs->pid));
10126 vl->burst_addr = NULL;
10127 vl->confirmed = GNUNET_YES;
10128 vl->message_uuid_ctr =
10130 vl->target = n->pid;
10136 links,
10137 &vl->target,
10138 vl,
10140 vl->n = n;
10141 n->vl = vl;
10142 q->idle = GNUNET_YES;
10143 vl->visibility_task =
10144 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
10146 /* We lacked a confirmed connection to the target
10147 before, so tell CORE about it (finally!) */
10150 }
10151 else
10152 {
10153 /* Link was already up, remember n is also now available and we are done */
10154 if (NULL == vl->n)
10155 {
10156 vl->n = n;
10157 n->vl = vl;
10158 if (GNUNET_YES == vl->confirmed)
10160 "Virtual link to %s could now also use direct neighbour!\n",
10161 GNUNET_i2s (&vs->pid));
10162 }
10163 else
10164 {
10165 GNUNET_assert (n == vl->n);
10166 }
10167 if (GNUNET_NO == vl->confirmed)
10168 {
10169 vl->confirmed = GNUNET_YES;
10170 q->idle = GNUNET_YES;
10171 vl->visibility_task =
10172 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
10174 /* We lacked a confirmed connection to the target
10175 before, so tell CORE about it (finally!) */
10178 }
10179 }
10180}
10181
10182
10188static void
10189handle_incoming_msg (void *cls,
10190 const struct GNUNET_TRANSPORT_IncomingMessage *im)
10191{
10192 struct TransportClient *tc = cls;
10193 struct CommunicatorMessageContext *cmc =
10195
10196 cmc->tc = tc;
10197 cmc->im = *im;
10199 "Received message with size %u and flow control id %" PRIu64
10200 " via communicator from peer %s\n",
10201 ntohs (im->header.size),
10202 im->fc_id,
10203 GNUNET_i2s (&im->sender));
10204 cmc->im.neighbour_sender = cmc->im.sender;
10205 cmc->mh = (const struct GNUNET_MessageHeader *) &im[1];
10207}
10208
10209
10218static int
10219check_flow_control (void *cls, const struct TransportFlowControlMessage *fc)
10220{
10221 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10222 (void) cls;
10223
10225 "Flow control header size %u size of addresses %u number of addresses %u size of message struct %lu second struct %lu\n",
10226 ntohs (fc->header.size),
10227 ntohl (fc->size_of_addresses),
10228 ntohl (fc->number_of_addresses),
10229 sizeof(struct TransportFlowControlMessage),
10230 sizeof (struct TransportGlobalNattedAddress));
10231
10232 if (0 == number_of_addresses || ntohs (fc->header.size) == sizeof(struct
10234 + ntohl (fc->number_of_addresses) * sizeof (struct
10236 + ntohl (fc->size_of_addresses))
10237 return GNUNET_OK;
10238 else
10239 {
10240 GNUNET_break_op (0);
10241 return GNUNET_SYSERR;
10242 }
10243}
10244
10245
10246static struct GNUNET_TIME_Relative
10247calculate_rtt (struct DistanceVector *dv)
10248{
10250 unsigned int n_hops = 0;
10251
10253 "calculate_rtt\n");
10254 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
10255 pos = pos->next_dv)
10256 {
10258 "calculate_rtt %lu\n",
10259 (unsigned long) pos->pd.aged_rtt.rel_value_us);
10260 n_hops++;
10262 aged_rtt, pos
10263 ->distance
10264 + 2), ret);
10265 }
10266
10267 GNUNET_assert (0 != n_hops);
10268
10269 return ret;
10270}
10271
10272
10273static void
10275 const struct GNUNET_PeerIdentity *pid,
10276 const char *uri)
10277{
10278 struct VirtualLink *vl = cls;
10279 const char *slash;
10280 char *address_uri;
10281 char *prefix;
10282 char *uri_without_port;
10283
10284 slash = strrchr (uri, '/');
10285 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
10286 GNUNET_assert (NULL != slash);
10287 slash++;
10288 GNUNET_asprintf (&address_uri,
10289 "%s-%s",
10290 prefix,
10291 slash);
10292
10293 uri_without_port = get_address_without_port (address_uri);
10295 "iterate_address_start_burst %s %s %s %s\n",
10296 uri_without_port,
10297 uri,
10298 address_uri,
10299 slash);
10300 if (0 == strcmp (uri_without_port, slash))
10301 {
10302 vl->burst_addr = GNUNET_strndup (uri_without_port, strlen (uri_without_port)
10303 );
10304 }
10305 else
10306 vl->burst_addr = NULL;
10307
10309 GNUNET_free (uri_without_port);
10310}
10311
10312
10313static void
10314check_for_burst_address (void *cls,
10315 const struct GNUNET_PEERSTORE_Record *record,
10316 const char *emsg)
10317{
10318 struct GNUNET_StartBurstCls *sb_cls = cls;
10319 struct VirtualLink *vl = sb_cls->vl;
10320 struct GNUNET_MessageHeader *hello;
10322
10323 if (NULL != emsg)
10324 {
10326 "Got failure from PEERSTORE: %s\n",
10327 emsg);
10328 return;
10329 }
10330 if (NULL == record)
10331 {
10333 "Hello iteration end for %s\n",
10334 GNUNET_i2s (&vl->target));
10335 vl->ic = NULL;
10336 GNUNET_free (sb_cls);
10337 return;
10338 }
10339
10341 "check_for_burst_address\n");
10342 hello = record->value;
10343 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
10346 vl);
10347 GNUNET_HELLO_parser_free (parser);
10348
10350 GNUNET_free (sb_cls);
10351}
10352
10353
10354static void
10355burst_timeout (void *cls)
10356{
10358}
10359
10360
10361static void
10362start_burst (void *cls)
10363{
10364 struct GNUNET_StartBurstCls *sb_cls = cls;
10365 struct VirtualLink *vl = sb_cls->vl;
10366 struct GNUNET_TRANSPORT_StartBurst *sb;
10367 struct GNUNET_MQ_Envelope *env;
10368 char *uri_without_port = vl->burst_addr;
10369
10370 burst_task = NULL;
10371 /*char buf[strlen (uri_without_port) + 1];
10372
10373 GNUNET_memcpy (buf, uri_without_port, strlen (uri_without_port));
10374 buf[strlen (uri_without_port)] = '\0';*/
10375 env =
10377 strlen (uri_without_port) + 1,
10379 sb->rtt = GNUNET_TIME_relative_hton (sb_cls->rtt);
10380 sb->pid = vl->target;
10381 memcpy (&sb[1], uri_without_port, strlen (uri_without_port) + 1);
10382 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
10383 {
10385 "iterate_address_start_burst client tc prefix %s\n",
10386 tc->details.communicator.address_prefix);
10387 if (CT_COMMUNICATOR != tc->type)
10388 continue;
10389 if (GNUNET_YES == tc->details.communicator.can_burst)
10390 {
10392 "iterate_address_start_burst %s call %lu %u rtt %lu\n",
10393 uri_without_port,
10394 strlen (uri_without_port),
10395 ntohs (sb->header.size),
10396 (unsigned long) sb_cls->rtt.rel_value_us);
10397 GNUNET_MQ_send (tc->mq, env);
10401 60),
10403 NULL);
10404 // TODO We need some algo to choose from available communicators. Can we run two bursts at once? Atm we only implemented udp burst.
10405 break;
10406 }
10407 }
10408 GNUNET_free (env);
10409 GNUNET_free (sb_cls);
10410}
10411
10412
10413static void
10414queue_burst (void *cls)
10415{
10416 struct GNUNET_StartBurstCls *sb_cls = cls;
10417 struct VirtualLink *vl = sb_cls->vl;
10418
10419 if (GNUNET_YES != use_burst)
10420 return;
10422 "burst_task %p ready %s burst addr %s (%p)\n",
10423 burst_task,
10424 sb_cls->sync_ready ? "yes" : "no",
10425 vl->burst_addr,
10426 vl->burst_addr);
10427 if (NULL != burst_task && GNUNET_NO == sb_cls->sync_ready)
10428 {
10430 burst_task = NULL;
10432 return;
10433 }
10434 if (GNUNET_NO == burst_running && NULL != vl->burst_addr && NULL == burst_task
10435 )
10436 {
10438 &start_burst,
10439 sb_cls);
10440 }
10441 else if (NULL == vl->burst_addr)
10442 {
10444 "peerstore",
10445 &vl->target,
10448 sb_cls);
10449 }
10450}
10451
10452
10461static void
10462handle_flow_control (void *cls, const struct TransportFlowControlMessage *fc)
10463{
10464 struct CommunicatorMessageContext *cmc = cls;
10465 struct VirtualLink *vl;
10467 uint32_t seq;
10468 struct GNUNET_TIME_Absolute st;
10469 uint64_t os;
10470 uint64_t wnd;
10471 uint32_t random;
10472
10474 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
10475 vl = lookup_virtual_link (&cmc->im.sender);
10476 if (NULL == vl)
10477 {
10478 vl = GNUNET_new (struct VirtualLink);
10480 "No virtual link for %p FC creating new unconfirmed virtual link to %s!\n",
10481 vl,
10482 GNUNET_i2s (&cmc->im.sender));
10483 vl->burst_addr = NULL;
10484 vl->confirmed = GNUNET_NO;
10485 vl->message_uuid_ctr =
10487 vl->target = cmc->im.sender;
10493 links,
10494 &vl->target,
10495 vl,
10497 }
10498 if (NULL != vl->n)
10499 {
10500 for (struct Queue *q = vl->n->queue_head; NULL != q; q = q->next_neighbour)
10501 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
10502 }
10503
10505 "remaining %lu timeout for neighbour %p\n",
10506 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout).
10507 rel_value_us,
10508 vl->n);
10509 if (NULL == vl->n ||
10510 0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
10511 {
10512 struct GNUNET_TIME_Relative rtt;
10513 struct GNUNET_BurstSync burst_sync;
10514 struct GNUNET_StartBurstCls *bcls;
10515
10516 bcls = GNUNET_new (struct GNUNET_StartBurstCls);
10517 bcls->vl = vl;
10518 vl->sb_cls = bcls;
10519 if (NULL != vl->dv)
10520 rtt = calculate_rtt (vl->dv);
10521 else
10523 burst_sync.rtt_average = fc->rtt;
10524 bcls->rtt = GNUNET_TIME_relative_ntoh (burst_sync.rtt_average);
10525 burst_sync.sync_ready = fc->sync_ready;
10526
10528 &burst_sync,
10529 &queue_burst,
10530 bcls);
10531 }
10532 if (0 != ntohl (fc->number_of_addresses))
10533 {
10534 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10535 const char *tgnas;
10536 unsigned int off = 0;
10537
10538 tgnas = (const char *) &fc[1];
10539
10540 for (int i = 1; i <= number_of_addresses; i++)
10541 {
10542 struct TransportGlobalNattedAddress *tgna;
10543 char *addr;
10544 unsigned int address_length;
10545
10546 tgna = (struct TransportGlobalNattedAddress*) &tgnas[off];
10547 addr = (char *) &tgna[1];
10548 address_length = ntohl (tgna->address_length);
10549 off += sizeof(struct TransportGlobalNattedAddress) + address_length;
10550
10552 "received address %s length %u\n",
10553 addr,
10554 ntohl (tgna->address_length));
10555
10556 GNUNET_NAT_add_global_address (nh, addr, ntohl (tgna->address_length));
10557 }
10558 }
10560 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
10561 {
10563 "FC dropped: Message out of order\n");
10564 /* out of order, drop */
10566 "# FC dropped: message out of order",
10567 1,
10568 GNUNET_NO);
10569 finish_cmc_handling (cmc);
10570 return;
10571 }
10572 seq = ntohl (fc->seq);
10573 if (seq < vl->last_fc_seq)
10574 {
10575 /* Wrap-around/reset of other peer; start all counters from zero */
10577 }
10578 vl->last_fc_seq = seq;
10579 vl->last_fc_timestamp = st;
10581 os = GNUNET_ntohll (fc->outbound_sent);
10583 (int64_t) (os - vl->incoming_fc_window_size_used);
10585 "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
10586 GNUNET_i2s (&vl->target),
10587 (unsigned int) seq,
10588 (unsigned long long) vl->outbound_fc_window_size,
10589 (long long) vl->incoming_fc_window_size_loss);
10592 UINT32_MAX);
10593 if ((GNUNET_YES == vl->confirmed) && ((wnd < vl->incoming_fc_window_size
10597 != wnd) ||
10598 (0 == random
10600 {
10602 "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",
10603 (unsigned long long) wnd,
10604 (unsigned long long) vl->incoming_fc_window_size,
10605 (unsigned long long) vl->last_outbound_window_size_received,
10608 }
10609 if ((wnd == vl->incoming_fc_window_size
10613 (NULL != vl->fc_retransmit_task))
10614 {
10616 "Stopping FC retransmission to %s: peer is current at window %llu\n",
10617 GNUNET_i2s (&vl->target),
10618 (unsigned long long) wnd);
10620 vl->fc_retransmit_task = NULL;
10621 vl->fc_retransmit_count = 0;
10622 }
10624 /* FC window likely increased, check transmission possibilities! */
10626 finish_cmc_handling (cmc);
10627}
10628
10629
10637static void
10639{
10641 { GNUNET_MQ_hd_var_size (fragment_box,
10644 cmc),
10645 GNUNET_MQ_hd_var_size (reliability_box,
10648 cmc),
10649 GNUNET_MQ_hd_var_size (reliability_ack,
10652 cmc),
10653 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
10656 cmc),
10657 GNUNET_MQ_hd_var_size (dv_learn,
10660 cmc),
10661 GNUNET_MQ_hd_var_size (dv_box,
10663 struct TransportDVBoxMessage,
10664 cmc),
10665 GNUNET_MQ_hd_var_size (flow_control,
10668 cmc),
10670 validation_challenge,
10673 cmc),
10675 validation_response,
10678 cmc),
10680 int ret;
10681 const struct GNUNET_MessageHeader *msg = cmc->mh;
10682
10684 "Handling message of type %u with %u bytes\n",
10685 (unsigned int) ntohs (msg->type),
10686 (unsigned int) ntohs (msg->size));
10688 if (GNUNET_SYSERR == ret)
10689 {
10690 GNUNET_break (0);
10692 GNUNET_free (cmc);
10693 return;
10694 }
10695 if (GNUNET_NO == ret)
10696 {
10697 /* unencapsulated 'raw' message */
10698 handle_raw_message (cmc, msg);
10699 }
10700}
10701
10702
10709static int
10710check_add_queue_message (void *cls,
10711 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
10712{
10713 struct TransportClient *tc = cls;
10714
10715 if (CT_COMMUNICATOR != tc->type)
10716 {
10717 GNUNET_break (0);
10718 return GNUNET_SYSERR;
10719 }
10721 return GNUNET_OK;
10722}
10723
10724
10730static void
10732{
10733 if (pm->msg_uuid_set)
10734 return;
10735 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
10736 pm->msg_uuid_set = GNUNET_YES;
10737}
10738
10739
10748static struct PendingAcknowledgement *
10750 struct DistanceVectorHop *dvh,
10751 struct PendingMessage *pm)
10752{
10753 struct PendingAcknowledgement *pa;
10754
10755 pa = GNUNET_new (struct PendingAcknowledgement);
10756 pa->queue = queue;
10757 pa->dvh = dvh;
10758 pa->pm = pm;
10759 do
10760 {
10762 &pa->ack_uuid,
10763 sizeof(pa->ack_uuid));
10764 }
10767 &pa->ack_uuid.value,
10768 pa,
10770 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
10771 GNUNET_CONTAINER_MDLL_insert (pm, pm->pa_head, pm->pa_tail, pa);
10772 if (NULL != dvh)
10775 pa->message_size = pm->bytes_msg;
10777 "Waiting for ACKnowledgment `%s' for <%" PRIu64 ">\n",
10779 pm->logging_uuid);
10780 return pa;
10781}
10782
10783
10795static struct PendingMessage *
10797 struct DistanceVectorHop *dvh,
10798 struct PendingMessage *pm)
10799{
10800 struct PendingAcknowledgement *pa;
10801 struct PendingMessage *ff;
10802 uint16_t mtu;
10803 uint16_t msize;
10804
10805 mtu = (UINT16_MAX == queue->mtu)
10806 ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
10807 : queue->mtu;
10809 "Fragmenting message <%" PRIu64
10810 "> with size %u to %s for MTU %u\n",
10811 pm->logging_uuid,
10812 pm->bytes_msg,
10813 GNUNET_i2s (&pm->vl->target),
10814 (unsigned int) mtu);
10817 "Fragmenting message %" PRIu64 " <%" PRIu64
10818 "> with size %u to %s for MTU %u\n",
10819 pm->msg_uuid.uuid,
10820 pm->logging_uuid,
10821 pm->bytes_msg,
10822 GNUNET_i2s (&pm->vl->target),
10823 (unsigned int) mtu);
10824
10825 /* This invariant is established in #handle_add_queue_message() */
10826 GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
10827
10828 /* select fragment for transmission, descending the tree if it has
10829 been expanded until we are at a leaf or at a fragment that is small
10830 enough
10831 */
10832 ff = pm;
10833 msize = ff->bytes_msg;
10834
10835 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
10836 (ff->frag_off == msize) && (NULL != ff->head_frag))
10837 {
10838 ff = ff->head_frag; /* descent into fragmented fragments */
10839 msize = ff->bytes_msg - sizeof(struct TransportFragmentBoxMessage);
10840 }
10841
10842 if (((ff->bytes_msg > mtu) || (pm == ff)) && (ff->frag_off < msize))
10843 {
10844 /* Did not yet calculate all fragments, calculate next fragment */
10845 struct PendingMessage *frag;
10846 struct TransportFragmentBoxMessage tfb;
10847 const char *orig;
10848 char *msg;
10849 uint16_t fragmax;
10850 uint16_t fragsize;
10851 uint16_t msize_ff;
10852 uint16_t xoff = 0;
10853 pm->frag_count++;
10854
10855 orig = (const char *) &ff[1];
10856 msize_ff = ff->bytes_msg;
10857 if (pm != ff)
10858 {
10859 const struct TransportFragmentBoxMessage *tfbo;
10860
10861 tfbo = (const struct TransportFragmentBoxMessage *) orig;
10862 orig += sizeof(struct TransportFragmentBoxMessage);
10863 msize_ff -= sizeof(struct TransportFragmentBoxMessage);
10864 xoff = ntohs (tfbo->frag_off);
10865 }
10866 fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
10867 fragsize = GNUNET_MIN (msize_ff - ff->frag_off, fragmax);
10868 frag =
10869 GNUNET_malloc (sizeof(struct PendingMessage)
10870 + sizeof(struct TransportFragmentBoxMessage) + fragsize);
10872 "3 created pm %p from pm %p storing vl %p from pm %p\n",
10873 frag,
10874 ff,
10875 pm->vl,
10876 pm);
10878 frag->vl = pm->vl;
10879 frag->frag_parent = ff;
10880 frag->timeout = pm->timeout;
10881 frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
10882 frag->pmt = PMT_FRAGMENT_BOX;
10883 msg = (char *) &frag[1];
10884 tfb.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT);
10885 tfb.header.size =
10886 htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
10887 pa = prepare_pending_acknowledgement (queue, dvh, frag);
10888 tfb.ack_uuid = pa->ack_uuid;
10889 tfb.msg_uuid = pm->msg_uuid;
10890 tfb.frag_off = htons (ff->frag_off + xoff);
10891 tfb.msg_size = htons (pm->bytes_msg);
10892 memcpy (msg, &tfb, sizeof(tfb));
10893 memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
10895 ff->tail_frag, frag);
10896 ff->frag_off += fragsize;
10897 ff = frag;
10898 }
10899
10900 /* Move head to the tail and return it */
10904 ff);
10908 ff);
10909
10910 return ff;
10911}
10912
10913
10926static struct PendingMessage *
10928 struct DistanceVectorHop *dvh,
10929 struct PendingMessage *pm)
10930{
10932 struct PendingAcknowledgement *pa;
10933 struct PendingMessage *bpm;
10934 char *msg;
10935
10936 if ((PMT_CORE != pm->pmt) && (PMT_DV_BOX != pm->pmt))
10937 return pm; /* already fragmented or reliability boxed, or control message:
10938 do nothing */
10939 if (NULL != pm->bpm)
10940 return pm->bpm; /* already computed earlier: do nothing */
10941 // TODO I guess we do not need this assertion. We might have a DLL with
10942 // fragments, because the MTU changed, and we do not need to fragment anymore.
10943 // But we should keep the fragments until message was completed, because
10944 // the MTU might change again.
10945 // GNUNET_assert (NULL == pm->head_frag);
10946 if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
10947 {
10948 /* failed hard */
10949 GNUNET_break (0);
10951 return NULL;
10952 }
10953
10955
10956 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
10957 + pm->bytes_msg);
10959 "4 created pm %p storing vl %p from pm %p\n",
10960 bpm,
10961 pm->vl,
10962 pm);
10964 bpm->vl = pm->vl;
10965 bpm->frag_parent = pm;
10966 // Why was this needed?
10967 // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
10968 bpm->timeout = pm->timeout;
10970 bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
10972 rbox.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX);
10973 rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
10974 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
10975
10976 rbox.ack_uuid = pa->ack_uuid;
10977 msg = (char *) &bpm[1];
10978 memcpy (msg, &rbox, sizeof(rbox));
10979 memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
10980 pm->bpm = bpm;
10982 "Preparing reliability box for message <%" PRIu64
10983 "> of size %d (%d) to %s on queue %s\n",
10984 pm->logging_uuid,
10985 pm->bytes_msg,
10986 ntohs (((const struct GNUNET_MessageHeader *) &pm[1])->size),
10987 GNUNET_i2s (&pm->vl->target),
10988 queue->address);
10989 return bpm;
10990}
10991
10992
10993static void
10996{
10997 struct VirtualLink *vl = pm->vl;
10998 struct PendingMessage *pos;
10999
11000 /* re-insert sort in neighbour list */
11004 pm);
11005 pos = vl->pending_msg_tail;
11006 while ((NULL != pos) &&
11008 pos = pos->prev_vl;
11012 pos,
11013 pm);
11014}
11015
11016
11017static unsigned int
11019{
11020 struct PendingMessage *pos;
11022
11023 pos = pm->head_frag;
11024 while (NULL != pos)
11025 {
11026 if (pos->frags_in_flight_round == pm->frags_in_flight_round ||
11027 GNUNET_NO == check_next_attempt_tree (pos, root))
11029 else
11030 {
11032 break;
11033 }
11034 pos = pos->next_frag;
11035 }
11036
11037 return frags_in_flight;
11038}
11039
11040
11041static void
11043{
11044 struct PendingMessage *pos;
11045
11046 pos = pm->head_frag;
11047 while (NULL != pos)
11048 {
11049 pos->frags_in_flight_round = pm->frags_in_flight_round;
11051 pos = pos->next_frag;
11052 }
11053}
11054
11055
11064static void
11067{
11068 if (NULL == pm->frag_parent)
11069 {
11072 "Next attempt for message <%" PRIu64 "> set to %" PRIu64 "\n",
11073 pm->logging_uuid,
11076 }
11077 else if ((PMT_RELIABILITY_BOX == pm->pmt) || (PMT_DV_BOX == pm->pmt))// || (PMT_FRAGMENT_BOX == pm->pmt))
11078 {
11079 struct PendingMessage *root = pm->frag_parent;
11080
11081 while (NULL != root->frag_parent)
11082 root = root->frag_parent;
11084 "Next attempt for root message <%" PRIu64 "> set to %s\n",
11085 root->logging_uuid,
11087 root->next_attempt = next_attempt;
11089 }
11090 else
11091 {
11092 struct PendingMessage *root = pm->frag_parent;
11093
11094 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11095 root = root->frag_parent;
11096
11098 "frag_count next attempt %u\n",
11099 root->frag_count);
11100
11101 if (GNUNET_NO == root->frags_in_flight)
11102 {
11103 root->next_attempt = next_attempt;
11105 root->frags_in_flight_round++;
11107 "Next attempt for fragmented message <%" PRIu64 "> (<%" PRIu64
11108 ">)set to %" PRIu64 "\n",
11109 pm->logging_uuid,
11110 root->logging_uuid,
11112 }
11113
11114 pm->next_attempt = root->next_attempt;
11115 pm->frags_in_flight_round = root->frags_in_flight_round;
11117
11118 if (root->bytes_msg == root->frag_off)
11119 root->frags_in_flight = check_next_attempt_tree (root, root);
11120 else
11122
11123 if (GNUNET_NO == root->frags_in_flight)
11124 {
11126 "We have no fragments in flight for message %" PRIu64
11127 ", reorder root! Next attempt is %" PRIu64 "\n",
11128 root->logging_uuid,
11130 if (PMT_DV_BOX == root->pmt)
11131 root = root->frag_parent;
11132 reorder_root_pm (root, root->next_attempt);
11133 // root->next_attempt = GNUNET_TIME_UNIT_ZERO_ABS;
11134 }
11135 else
11136 {
11137 double factor = ((double) root->frag_count - 1)
11138 / (double) root->frag_count;
11139 struct GNUNET_TIME_Relative s1;
11140 struct GNUNET_TIME_Relative s2;
11141 struct GNUNET_TIME_Relative plus_mean =
11144 next_attempt);
11145
11147 "frag_count %u after factor\n",
11148 root->frag_count);
11150 factor);
11151 s2 = GNUNET_TIME_relative_divide (plus,
11152 root->frag_count);
11153 plus_mean = GNUNET_TIME_relative_add (s1, s2);
11156 "We have fragments in flight for message %" PRIu64
11157 ", do not reorder root! Actual next attempt %" PRIu64 "\n",
11158 root->logging_uuid,
11160 }
11161 }
11162}
11163
11164
11169{
11173 struct PendingMessage *best;
11174
11178 struct DistanceVectorHop *dvh;
11179
11183 size_t real_overhead;
11184
11188 unsigned int consideration_counter;
11189
11193 int frag;
11194
11198 int relb;
11199
11203 int to_early;
11204
11208 unsigned int frags_in_flight;
11209
11214};
11215
11216
11228static void
11230 struct Queue *queue,
11231 struct VirtualLink *vl,
11232 struct DistanceVectorHop *dvh,
11233 size_t overhead)
11234{
11235 struct GNUNET_TIME_Absolute now;
11236
11237 now = GNUNET_TIME_absolute_get ();
11238 sc->to_early = GNUNET_NO;
11239 sc->frags_in_flight = GNUNET_NO;
11240 for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
11241 pos = pos->next_vl)
11242 {
11243 size_t real_overhead = overhead;
11244 int frag;
11245 int relb;
11246
11247 if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
11248 {
11250 "DV messages must not be DV-routed to next hop!\n");
11251 continue; /* DV messages must not be DV-routed to next hop! */
11252 }
11253 if (pos->next_attempt.abs_value_us > now.abs_value_us)
11254 {
11255 if (GNUNET_YES == pos->frags_in_flight)
11256 {
11257 sc->frags_in_flight = GNUNET_YES;
11259 "Fragments in flight for message %" PRIu64 "\n",
11260 pos->logging_uuid);
11261 }
11262 else
11263 {
11265 "Maybe too early, because message are sorted by next_attempt, if there are no fragments in flight.Checked message %"
11266 PRIu64 "\n",
11267 pos->logging_uuid);
11268 sc->to_early = GNUNET_YES;
11269 sc->to_early_retry_delay = GNUNET_TIME_absolute_get_remaining (
11270 pos->next_attempt);
11271 continue;
11272 }
11273 // break; /* too early for all messages, they are sorted by next_attempt */
11274 }
11275 if (NULL != pos->qe)
11276 {
11278 "not eligible\n");
11279 continue; /* not eligible */
11280 }
11281 sc->consideration_counter++;
11282 /* determine if we have to fragment, if so add fragmentation
11283 overhead! */
11285 "check %" PRIu64 " for sc->best\n",
11286 pos->logging_uuid);
11287 frag = GNUNET_NO;
11288 if (((0 != queue->mtu) &&
11289 (pos->bytes_msg + real_overhead > queue->mtu)) ||
11290 (pos->bytes_msg > UINT16_MAX - sizeof(struct
11292 ||
11293 (NULL != pos->head_frag /* fragments already exist, should
11294 respect that even if MTU is UINT16_MAX for
11295 this queue */))
11296 {
11298 "fragment msg with size %u, realoverhead is %lu\n",
11299 pos->bytes_msg,
11300 real_overhead);
11301 frag = GNUNET_YES;
11302 if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
11303 {
11304 /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
11305 header without the ACK UUID when using a *reliable* channel! */
11306 }
11307 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11308 }
11309 /* determine if we have to reliability-box, if so add reliability box
11310 overhead */
11311 relb = GNUNET_NO;
11312 if ((GNUNET_NO == frag) &&
11313 (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
11314 (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
11315 {
11316 real_overhead += sizeof(struct TransportReliabilityBoxMessage);
11317
11318 if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu))
11319 {
11320 frag = GNUNET_YES;
11321 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11322 }
11323 else
11324 {
11325 relb = GNUNET_YES;
11326 }
11328 "Create reliability box of msg with size %u, realoverhead is %lu %u %u %u\n",
11329 pos->bytes_msg,
11330 real_overhead,
11331 queue->mtu,
11332 frag,
11333 relb);
11334 }
11335
11336 /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
11337 message would beat it! */
11338 if (GNUNET_NO == sc->frags_in_flight && NULL != sc->best)
11339 {
11340 /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
11341 OPTIMIZE-ME: This is a heuristic, which so far has NOT been
11342 experimentally validated. There may be some huge potential for
11343 improvement here. Also, we right now only compare how well the
11344 given message fits _this_ queue, and do not consider how well other
11345 queues might suit the message. Taking other queues into consideration
11346 may further improve the result, but could also be expensive
11347 in terms of CPU time. */
11348 long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
11349 long long pm_score = frag * 40 + relb * 20 + real_overhead;
11350 long long time_delta =
11351 (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
11352 / 1000LL;
11353
11354 /* "time_delta" considers which message has been 'ready' for transmission
11355 for longer, if a message has a preference for low latency, increase
11356 the weight of the time_delta by 10x if it is favorable for that message */
11357 if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11358 (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
11359 time_delta *= 10; /* increase weight (always, both are low latency) */
11360 else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11361 (time_delta > 0))
11362 time_delta *= 10; /* increase weight, favors 'pos', which is low latency */
11363 else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11364 (time_delta < 0))
11365 time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */
11366 if (0 != queue->mtu)
11367 {
11368 /* Grant bonus if we are below MTU, larger bonus the closer we will
11369 be to the MTU */
11370 if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
11371 sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
11372 if (queue->mtu > real_overhead + pos->bytes_msg)
11373 pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
11374 }
11375 if (sc_score + time_delta > pm_score)
11376 {
11378 "sc_score of %" PRIu64 " larger, keep sc->best %" PRIu64
11379 "\n",
11380 pos->logging_uuid,
11381 sc->best->logging_uuid);
11382 continue; /* sc_score larger, keep sc->best */
11383 }
11384 }
11385 sc->best = pos;
11386 sc->dvh = dvh;
11387 sc->frag = frag;
11388 sc->relb = relb;
11389 sc->real_overhead = real_overhead;
11390 }
11391}
11392
11393
11404static void
11405extract_box_cb (void *cls,
11406 struct Neighbour *next_hop,
11407 const struct GNUNET_MessageHeader *hdr,
11409{
11410 struct PendingMessageScoreContext *sc = cls;
11411 struct PendingMessage *pm = sc->best;
11412 struct PendingMessage *bpm;
11413 uint16_t bsize = ntohs (hdr->size);
11414
11415 GNUNET_assert (NULL == pm->bpm);
11416 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
11418 "5 created pm %p storing vl %p from pm %p\n",
11419 bpm,
11420 pm->vl,
11421 pm);
11423 bpm->pmt = PMT_DV_BOX;
11424 bpm->vl = pm->vl;
11425 bpm->timeout = pm->timeout;
11426 bpm->bytes_msg = bsize;
11427 bpm->frag_parent = pm;
11430 "Creating DV Box %" PRIu64 " for original message %" PRIu64
11431 " (next hop is %s)\n",
11433 pm->logging_uuid,
11434 GNUNET_i2s (&next_hop->pid));
11435 memcpy (&bpm[1], hdr, bsize);
11436 pm->bpm = bpm;
11437}
11438
11439
11455static void
11456transmit_on_queue (void *cls)
11457{
11458 struct Queue *queue = cls;
11459 struct Neighbour *n = queue->neighbour;
11461 struct PendingMessage *pm;
11462
11463 queue->transmit_task = NULL;
11464 if (NULL == n->vl)
11465 {
11467 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
11468 GNUNET_i2s (&n->pid),
11469 queue->address);
11470 queue->idle = GNUNET_YES;
11471 return;
11472 }
11473 memset (&sc, 0, sizeof(sc));
11474 select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
11475 if (NULL == sc.best)
11476 {
11477 /* Also look at DVH that have the n as first hop! */
11478 for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
11479 dvh = dvh->next_neighbour)
11480 {
11482 queue,
11483 dvh->dv->vl,
11484 dvh,
11485 sizeof(struct GNUNET_PeerIdentity)
11486 * (1 + dvh->distance)
11487 + sizeof(struct TransportDVBoxMessage)
11488 + sizeof(struct TransportDVBoxPayloadP));
11489 }
11490 }
11491 if (NULL == sc.best)
11492 {
11493 /* no message pending, nothing to do here! */
11495 "No pending messages, queue `%s' to %s now idle\n",
11496 queue->address,
11497 GNUNET_i2s (&n->pid));
11498 if (GNUNET_YES == sc.to_early)
11499 schedule_transmit_on_queue (sc.to_early_retry_delay,
11500 queue,
11502 queue->idle = GNUNET_YES;
11503 return;
11504 }
11505 /* There is a message pending, we are certainly not idle */
11506 queue->idle = GNUNET_NO;
11507
11508 /* Given selection in `sc`, do transmission */
11509 pm = sc.best;
11511 "Selected message <%" PRIu64 ">\n",
11512 pm->logging_uuid);
11513 if (NULL != sc.dvh)
11514 {
11516 "Is this %u a DV box?\n",
11517 pm->pmt);
11518 GNUNET_assert (PMT_DV_BOX != pm->pmt);
11519 if ((NULL != sc.best->bpm) && (sc.best->bpm->used_dvh != sc.dvh))
11520 {
11522 "Discard old box, because we have a new DV path.\n");
11523 free_pending_message (sc.best->bpm);
11524 sc.best->bpm = NULL;
11525 }
11526
11527 if (NULL == sc.best->bpm)
11528 {
11530 "encapsulate_for_dv 2\n");
11531 encapsulate_for_dv (sc.dvh->dv,
11532 1,
11533 &sc.dvh,
11534 (const struct GNUNET_MessageHeader *) &sc.best[1],
11536 &sc,
11537 RMO_NONE,
11538 GNUNET_NO);
11539 GNUNET_assert (NULL != sc.best->bpm);
11541 "%lu %lu %lu %lu %u\n",
11542 sizeof(struct GNUNET_PeerIdentity),
11543 sizeof(struct TransportDVBoxMessage),
11544 sizeof(struct TransportDVBoxPayloadP),
11545 sizeof(struct TransportFragmentBoxMessage),
11546 ((const struct GNUNET_MessageHeader *) &sc.best[1])->size);
11547 sc.best->bpm->used_dvh = sc.dvh;
11548 }
11549 pm = sc.best->bpm;
11550 }
11551 if (GNUNET_YES == sc.frag)
11552 {
11553 pm = fragment_message (queue, sc.dvh, pm);
11554 if (NULL == pm)
11555 {
11557 "Fragmentation failed queue %s to %s for <%" PRIu64
11558 ">, trying again\n",
11559 queue->address,
11560 GNUNET_i2s (&n->pid),
11561 sc.best->logging_uuid);
11563 queue,
11565 return;
11566 }
11567 }
11568 else if (GNUNET_YES == sc.relb)
11569 {
11571 if (NULL == pm)
11572 {
11573 /* Reliability boxing failed, try next message... */
11574 GNUNET_log (
11576 "Reliability boxing failed queue %s to %s for <%" PRIu64
11577 ">, trying again\n",
11578 queue->address,
11579 GNUNET_i2s (&n->pid),
11580 sc.best->logging_uuid);
11582 queue,
11584 return;
11585 }
11586 }
11587
11588 /* Pass 'pm' for transission to the communicator */
11589 GNUNET_log (
11591 "Passing message <%" PRIu64
11592 "> to queue %s for peer %s (considered %u others)\n",
11593 pm->logging_uuid,
11594 queue->address,
11595 GNUNET_i2s (&n->pid),
11596 sc.consideration_counter);
11597
11598 /* Flow control: increment amount of traffic sent; if we are routing
11599 via DV (and thus the ultimate target of the pending message is for
11600 a different virtual link than the one of the queue), then we need
11601 to use up not only the window of the direct link but also the
11602 flow control window for the DV link! */
11603 pm->vl->outbound_fc_window_size_used += pm->bytes_msg;
11604
11605 if (pm->vl != queue->neighbour->vl)
11606 {
11607 /* If the virtual link of the queue differs, this better be distance
11608 vector routing! */
11609 GNUNET_assert (NULL != sc.dvh);
11610 /* If we do distance vector routing, we better not do this for a
11611 message that was itself DV-routed */
11612 GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
11613 /* We use the size of the unboxed message here, to avoid counting
11614 the DV-Box header which is eaten up on the way by intermediaries */
11615 queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
11616 }
11617 else
11618 {
11619 GNUNET_assert (NULL == sc.dvh);
11620 }
11621
11622 queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
11623
11624 /* Check if this transmission somehow conclusively finished handing 'pm'
11625 even without any explicit ACKs */
11626 if ((PMT_CORE == pm->pmt) ||
11627 (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
11628 {
11630 }
11631 else
11632 {
11633 struct GNUNET_TIME_Relative wait_duration;
11634 unsigned int wait_multiplier;
11635
11636 if (PMT_FRAGMENT_BOX == pm->pmt)
11637 {
11638 struct PendingMessage *root;
11639
11640 root = pm->frag_parent;
11641 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11642 root = root->frag_parent;
11643
11644 wait_multiplier = (unsigned int) ceil ((double) root->bytes_msg
11645 / ((double) root->frag_off
11646 / (double) root->frag_count))
11647 * 4;
11648 }
11649 else
11650 {
11651 // No fragments, we use 4 RTT before retransmitting.
11652 wait_multiplier = 4;
11653 }
11654
11655 // Depending on how much pending message the VirtualLink is queueing, we wait longer.
11656 // wait_multiplier = wait_multiplier * pm->vl->pending_msg_num;
11657
11659 "Wait multiplier %u\n",
11660 wait_multiplier);
11661
11662 /* Message not finished, waiting for acknowledgement.
11663 Update time by which we might retransmit 's' based on queue
11664 characteristics (i.e. RTT); it takes one RTT for the message to
11665 arrive and the ACK to come back in the best case; but the other
11666 side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
11667 retransmitting.
11668
11669 OPTIMIZE: Note that in the future this heuristic should likely
11670 be improved further (measure RTT stability, consider message
11671 urgency and size when delaying ACKs, etc.) */
11672
11673 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
11674 queue->pd.aged_rtt.rel_value_us)
11675 wait_duration = queue->pd.aged_rtt;
11676 else
11677 {
11678 wait_duration = DEFAULT_ACK_WAIT_DURATION;
11679 wait_multiplier = 4;
11680 }
11681 {
11684 wait_duration, wait_multiplier));
11686 wait_duration, wait_multiplier);
11688 "Waiting %s for ACK until %s\n",
11693 GNUNET_TIME_relative_multiply (wait_duration,
11694 wait_multiplier))
11695 );
11696 }
11697 }
11698 /* finally, re-schedule queue transmission task itself */
11700 queue,
11702}
11703
11704
11711static void
11712handle_del_queue_message (void *cls,
11713 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
11714{
11715 struct TransportClient *tc = cls;
11716
11717 if (CT_COMMUNICATOR != tc->type)
11718 {
11719 GNUNET_break (0);
11721 return;
11722 }
11723 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11724 queue = queue->next_client)
11725 {
11726 struct Neighbour *neighbour = queue->neighbour;
11727
11728 if ((ntohl (dqm->qid) != queue->qid) ||
11729 (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
11730 continue;
11732 "Dropped queue %s to peer %s\n",
11733 queue->address,
11734 GNUNET_i2s (&neighbour->pid));
11735 free_queue (queue);
11737 return;
11738 }
11739 GNUNET_break (0);
11741}
11742
11743
11744static void
11746 struct TransportClient *tc)
11747{
11748 struct PendingMessage *pm;
11749
11750 GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
11751 qe->queue->queue_tail,
11752 qe);
11753 qe->queue->queue_length--;
11754 tc->details.communicator.total_queue_length--;
11756 "Received ACK on queue %s (QID %u) to peer %s (new length: %u/%u)\n",
11757 qe->queue->address,
11758 qe->queue->qid,
11759 GNUNET_i2s (&qe->queue->neighbour->pid),
11760 qe->queue->queue_length,
11761 tc->details.communicator.total_queue_length);
11762
11763 /* if applicable, resume transmissions that waited on ACK */
11765 tc->details.communicator.total_queue_length)
11766 {
11767 /* Communicator dropped below threshold, resume all queues
11768 incident with this client! */
11770 GST_stats,
11771 "# Transmission throttled due to communicator queue limit",
11772 -1,
11773 GNUNET_NO);
11774 for (struct Queue *queue = tc->details.communicator.queue_head;
11775 NULL != queue;
11776 queue = queue->next_client)
11777 {
11779 queue,
11781 }
11782 }
11783 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
11784 {
11785 /* queue dropped below threshold; only resume this one queue */
11787 "# Transmission throttled due to queue queue limit",
11788 -1,
11789 GNUNET_NO);
11791 qe->queue,
11793 }
11794 else if (1 == qe->queue->q_capacity)
11795 {
11796 // TODO I guess this will never happen, because the communicator triggers this by updating its queue length itself.
11798 "Transmission rescheduled due to communicator message queue with qid %u has capacity %"
11799 PRIu64 ".\n",
11800 qe->queue->qid,
11801 qe->queue->q_capacity);
11802 /* message queue has capacity; only resume this one queue */
11803 /* queue dropped below threshold; only resume this one queue */
11805 "# Transmission throttled due to message queue capacity",
11806 -1,
11807 GNUNET_NO);
11809 qe->queue,
11811 }
11812
11813 if (NULL != (pm = qe->pm))
11814 {
11815 struct VirtualLink *vl;
11816
11817 // GNUNET_assert (qe == pm->qe);
11818 pm->qe = NULL;
11819 /* If waiting for this communicator may have blocked transmission
11820 of pm on other queues for this neighbour, force schedule
11821 transmit on queue for queues of the neighbour */
11822 if (NULL == pm->frag_parent)
11823 {
11824 vl = pm->vl;
11825 if ((NULL != vl) &&
11826 (NULL != vl->pending_msg_head) &&
11827 (vl->pending_msg_head == pm))
11829 }
11830 }
11831 GNUNET_free (qe);
11832}
11833
11834
11841static void
11842handle_send_message_ack (void *cls,
11843 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
11844{
11845 struct TransportClient *tc = cls;
11846 struct QueueEntry *qe;
11847
11848 if (CT_COMMUNICATOR != tc->type)
11849 {
11850 GNUNET_break (0);
11852 return;
11853 }
11854
11855 /* find our queue entry matching the ACK */
11856 qe = NULL;
11858 "Looking for queue for PID %s\n",
11859 GNUNET_i2s (&sma->receiver));
11860 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11861 queue = queue->next_client)
11862 {
11863 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
11864 continue;
11866 "Found PID %s\n",
11867 GNUNET_i2s (&queue->neighbour->pid));
11868
11869
11870 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
11871 qep = qep->next)
11872 {
11873 if (qep->mid != GNUNET_ntohll (sma->mid) || queue->qid != ntohl (
11874 sma->qid))
11875 continue;
11877 "QueueEntry MID: %" PRIu64 " on queue QID: %u, Ack MID: %"
11878 PRIu64 " Ack QID %u\n",
11879 qep->mid,
11880 queue->qid,
11881 GNUNET_ntohll (sma->mid),
11882 ntohl (sma->qid));
11883 qe = qep;
11884 if ((NULL != qe->pm) && (qe->pm->qe != qe))
11886 "For pending message %" PRIu64 " we had retransmissions.\n",
11887 qe->pm->logging_uuid);
11888 break;
11889 }
11890 }
11891 if (NULL == qe)
11892 {
11894 "No QueueEntry found for Ack MID %" PRIu64 " QID: %u\n",
11895 GNUNET_ntohll (sma->mid),
11896 ntohl (sma->qid));
11897 // TODO I guess this can happen, if the Ack from the peer comes before the Ack from the queue.
11898 // Update: Maybe QueueEntry was accidentally freed during freeing PendingMessage.
11899 /* this should never happen */
11900 // GNUNET_break (0);
11901 // GNUNET_SERVICE_client_drop (tc->client);
11903 return;
11904 }
11907}
11908
11909
11915static void
11916handle_burst_finished (void *cls,
11917 const struct GNUNET_TRANSPORT_BurstFinished *bf)
11918{
11920}
11921
11922
11932static int
11933notify_client_queues (void *cls,
11934 const struct GNUNET_PeerIdentity *pid,
11935 void *value)
11936{
11937 struct TransportClient *tc = cls;
11938 struct Neighbour *neighbour = value;
11939
11940 GNUNET_assert (CT_MONITOR == tc->type);
11941 for (struct Queue *q = neighbour->queue_head; NULL != q;
11942 q = q->next_neighbour)
11943 {
11944 struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
11945 .cs = q->cs,
11946 .num_msg_pending = q->num_msg_pending,
11947 .num_bytes_pending = q->num_bytes_pending };
11948
11949 notify_monitor (tc, pid, q->address, q->nt, &me);
11950 }
11951 return GNUNET_OK;
11952}
11953
11954
11961static void
11962handle_monitor_start (void *cls,
11964{
11965 struct TransportClient *tc = cls;
11966
11967 if (CT_NONE != tc->type)
11968 {
11969 GNUNET_break (0);
11971 return;
11972 }
11973 tc->type = CT_MONITOR;
11974 tc->details.monitor.peer = start->peer;
11975 tc->details.monitor.one_shot = ntohl (start->one_shot);
11979}
11980
11981
11989static struct TransportClient *
11990lookup_communicator (const char *prefix)
11991{
11992 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
11993 {
11994 if (CT_COMMUNICATOR != tc->type)
11995 continue;
11996 if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
11997 return tc;
11998 }
11999 GNUNET_log (
12001 "Someone suggested use of communicator for `%s', but we do not have such a communicator!\n",
12002 prefix);
12003 return NULL;
12004}
12005
12006
12014static void
12015suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address)
12016{
12017 static uint32_t idgen = 0;
12018 struct TransportClient *tc;
12019 char *prefix;
12020 struct GNUNET_TRANSPORT_CreateQueue *cqm;
12021 struct GNUNET_MQ_Envelope *env;
12022 size_t alen;
12023
12025 if (NULL == prefix)
12026 {
12027 GNUNET_break (0); /* We got an invalid address!? */
12028 return;
12029 }
12031 if (NULL == tc)
12032 {
12034 "# Suggestions ignored due to missing communicator",
12035 1,
12036 GNUNET_NO);
12038 "Cannot connect to %s at `%s', no matching communicator present\n",
12039 GNUNET_i2s (pid),
12040 address);
12042 return;
12043 }
12044 /* forward suggestion for queue creation to communicator */
12046 "Request #%u for `%s' communicator to create queue to `%s' at `%s'\n",
12047 (unsigned int) idgen,
12048 prefix,
12049 GNUNET_i2s (pid),
12050 address);
12052 alen = strlen (address) + 1;
12053 env =
12055 cqm->request_id = htonl (idgen++);
12056 cqm->receiver = *pid;
12057 memcpy (&cqm[1], address, alen);
12058 GNUNET_MQ_send (tc->mq, env);
12059}
12060
12061
12069static void
12071{
12073 struct GNUNET_TIME_Absolute monotonic_time;
12074
12075 if (NULL != vs->revalidation_task)
12076 {
12077 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
12078 vs->revalidation_task = NULL;
12079 }
12080 /*memcpy (&hkey,
12081 &hc,
12082 sizeof (hkey));*/
12084 "Remove key %s for address %s map size %u contains %u\n",
12085 GNUNET_h2s (&vs->hc),
12086 vs->address,
12089 &vs->hc));
12091
12093 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
12094 vs->last_challenge_use.abs_value_us)
12095 {
12096 vs->first_challenge_use = monotonic_time;
12097 }
12098 vs->last_challenge_use = monotonic_time;
12099 tvc.header.type =
12101 tvc.header.size = htons (sizeof(tvc));
12102 tvc.reserved = htonl (0);
12103 tvc.challenge = vs->challenge;
12104 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
12106 "Sending address validation challenge %s to %s\n",
12108 GNUNET_i2s (&q->neighbour->pid));
12109 queue_send_msg (q, NULL, &tvc, sizeof(tvc));
12110}
12111
12112
12118static void
12119validation_start_cb (void *cls)
12120{
12121 struct ValidationState *vs;
12122 struct Queue *q;
12124 GST_cfg);
12125
12126 (void) cls;
12127 validation_task = NULL;
12129 /* drop validations past their expiration */
12130 while (
12131 (NULL != vs) &&
12133 {
12135 "Validation response %s cleaned up\n",
12136 GNUNET_sh2s (&vs->challenge.value));
12139 }
12140 if (NULL == vs)
12141 {
12143 "Address validation task not scheduled anymore, nothing to do\n");
12144 return; /* woopsie, no more addresses known, should only
12145 happen if we're really a lonely peer */
12146 }
12147 q = find_queue (&vs->pid, vs->address);
12148 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
12149 {
12151 "To early to start next address validation for challenge %s\n",
12152 GNUNET_sh2s (&vs->challenge.value));
12153 return;
12154 }
12155 if (NULL == q)
12156 {
12157 vs->awaiting_queue = GNUNET_YES;
12158 suggest_to_connect (&vs->pid, vs->address);
12159 }
12160 else
12162 /* Finally, reschedule next attempt */
12163 vs->challenge_backoff =
12164 GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
12167 "Address validation task will run again in %s\n",
12168 GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
12169 GNUNET_YES));
12172 vs->challenge_backoff));
12173}
12174
12175
12180{
12184 struct Queue *q;
12185
12189 unsigned int quality_count;
12190
12194 unsigned int num_queues;
12195
12200 unsigned int k;
12201};
12202
12203
12215static int
12216check_connection_quality (void *cls,
12217 const struct GNUNET_PeerIdentity *pid,
12218 void *value)
12219{
12220 struct QueueQualityContext *ctx = cls;
12221 struct Neighbour *n = value;
12222 int do_inc;
12223
12224 (void) pid;
12225 do_inc = GNUNET_NO;
12226 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
12227 {
12228 ctx->num_queues++;
12229 if (0 == ctx->k--)
12230 ctx->q = q;
12231 /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
12232 statistics and consider those as well here? */
12233 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
12234 do_inc = GNUNET_YES;
12235 }
12236 if (GNUNET_YES == do_inc)
12237 ctx->quality_count++;
12238 return GNUNET_OK;
12239}
12240
12241
12253static void
12254start_dv_learn (void *cls);
12255
12256
12257struct SignDvInitCls
12258{
12260 struct LearnLaunchEntry *lle;
12261 struct QueueQualityContext qqc;
12262 struct PilsRequest *pr;
12263};
12264
12265
12266static void
12267sign_dv_init_cb (void *cls,
12268 const struct GNUNET_PeerIdentity *pid,
12269 const struct GNUNET_CRYPTO_EddsaSignature *sig)
12270{
12271 const struct GNUNET_PeerIdentity *my_identity;
12272 struct SignDvInitCls *sign_dv_init_cls = cls;
12273 struct TransportDVLearnMessage dvl = sign_dv_init_cls->dvl;
12274 struct LearnLaunchEntry *lle = sign_dv_init_cls->lle;
12275 struct QueueQualityContext qqc = sign_dv_init_cls->qqc;
12276
12279
12280 sign_dv_init_cls->pr->op = NULL;
12283 sign_dv_init_cls->pr);
12284 GNUNET_free (sign_dv_init_cls->pr);
12285
12286 dvl.init_sig = *sig;
12287 dvl.initiator = *my_identity;
12288 dvl.challenge = lle->challenge;
12289
12290 qqc.quality_count = 0;
12292 qqc.num_queues = 0;
12293 qqc.q = NULL;
12296 &qqc);
12297 GNUNET_assert (NULL != qqc.q);
12298
12299 /* Do this as close to transmission time as possible! */
12301
12302 queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
12303 /* reschedule this job, randomizing the time it runs (but no
12304 actual backoff!) */
12305 if (NULL != dvlearn_task)
12310 NULL);
12311}
12312
12313
12325static void
12326start_dv_learn (void *cls)
12327{
12328 struct LearnLaunchEntry *lle;
12329 struct QueueQualityContext qqc;
12330 struct TransportDVLearnMessage dvl;
12331 const struct GNUNET_PeerIdentity *my_identity;
12332
12333 (void) cls;
12334 dvlearn_task = NULL;
12336 return; /* lost all connectivity, cannot do learning */
12337 qqc.quality_count = 0;
12338 qqc.num_queues = 0;
12342 &qqc);
12344 {
12345 struct GNUNET_TIME_Relative delay;
12346 unsigned int factor;
12347
12348 /* scale our retries by how far we are above the threshold */
12352 "At connection quality %u, will launch DV learn in %s\n",
12353 qqc.quality_count,
12356 return;
12357 }
12358 /* remove old entries in #dvlearn_map if it has grown too big */
12359 while (MAX_DV_LEARN_PENDING <=
12361 {
12362 lle = lle_tail;
12365 &lle->challenge.value,
12366 lle));
12368 GNUNET_free (lle);
12369 }
12370 /* setup data structure for learning */
12371 lle = GNUNET_new (struct LearnLaunchEntry);
12373 &lle->challenge,
12374 sizeof(lle->challenge));
12376 "Starting launch DV learn with challenge %s\n",
12377 GNUNET_sh2s (&lle->challenge.value));
12382 &lle->challenge.value,
12383 lle,
12388 dvl.header.size = htons (sizeof(dvl));
12389 dvl.num_hops = htons (0);
12390 dvl.bidirectional = htons (0);
12392 dvl.monotonic_time =
12394 // We will set the below again later
12395 memset (&dvl.init_sig, 0, sizeof dvl.init_sig);
12396 dvl.challenge = lle->challenge;
12397 dvl.initiator = *my_identity;
12398 {
12399 struct DvInitPS dvip = {
12400 .purpose.purpose = htonl (
12402 .purpose.size = htonl (sizeof(dvip)),
12403 .monotonic_time = dvl.monotonic_time,
12404 .challenge = lle->challenge
12405 };
12406 struct SignDvInitCls *sign_dv_init_cls;
12407
12408 sign_dv_init_cls = GNUNET_new (struct SignDvInitCls);
12409 sign_dv_init_cls->dvl = dvl;
12410 sign_dv_init_cls->lle = lle;
12411 sign_dv_init_cls->qqc = qqc;
12412 sign_dv_init_cls->pr = GNUNET_new (struct PilsRequest);
12415 sign_dv_init_cls->pr);
12416 sign_dv_init_cls->pr->op =
12418 &dvip.purpose,
12420 sign_dv_init_cls);
12421 }
12422}
12423
12424
12432static char *
12434{
12435 const char *colon;
12436 char *colon_rest;
12437 size_t colon_rest_length;
12438 char *address_without_port;
12439
12440 colon = strchr (address,':');
12441 colon_rest = GNUNET_strndup (address, colon - address);
12442 colon_rest_length = strlen (colon_rest);
12443 address_without_port = GNUNET_strndup (&colon_rest[4], colon_rest_length - 4);
12444 GNUNET_free (colon_rest);
12445
12446 return address_without_port;
12447}
12448
12449
12459static int
12461 const struct GNUNET_PeerIdentity *pid,
12462 void *value)
12463{
12464 struct Queue *q = cls;
12465 struct ValidationState *vs = value;
12466 char *address_without_port_vs;
12467 char *address_without_port_q;
12468 int success = GNUNET_YES;
12469
12470 // TODO Check if this is really necessary.
12471 address_without_port_vs = get_address_without_port (vs->address);
12472 address_without_port_q = get_address_without_port (q->address);
12473
12475 "Check validation request pending for `%s' at `%s'/`%s' (vs)/(q)\n",
12476 GNUNET_i2s (pid),
12477 address_without_port_vs,
12478 address_without_port_q);
12479 (void) pid;
12480 if ((GNUNET_YES == vs->awaiting_queue) &&
12481 (0 == strcmp (address_without_port_vs, address_without_port_q)))
12482 {
12483
12484 vs->awaiting_queue = GNUNET_NO;
12486 success = GNUNET_NO;
12487 }
12488
12489 GNUNET_free (address_without_port_vs);
12490 GNUNET_free (address_without_port_q);
12491 return success;
12492}
12493
12494
12503static void
12504neighbour_dv_monotime_cb (void *cls,
12505 const struct GNUNET_PEERSTORE_Record *record,
12506 const char *emsg)
12507{
12508 struct Neighbour *n = cls;
12509 struct GNUNET_TIME_AbsoluteNBO *mtbe;
12510
12511 (void) emsg;
12512 if (NULL == record)
12513 {
12514 /* we're done with #neighbour_dv_monotime_cb() invocations,
12515 continue normal processing */
12516 n->get = NULL;
12518 return;
12519 }
12520 if (0 == record->value_size)
12521 {
12523 GNUNET_break (0);
12524 return;
12525 }
12526 mtbe = record->value;
12531}
12532
12533
12534static void
12536 const struct GNUNET_PeerIdentity *pid,
12537 const char *uri)
12538{
12539 struct Queue *queue = cls;
12540 struct sockaddr_in v4;
12541 const char *slash;
12542 char *address_uri;
12543 char *prefix;
12544 char *uri_without_port;
12545 char *address_uri_without_port;
12546
12547 slash = strrchr (uri, '/');
12548 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
12549 GNUNET_assert (NULL != slash);
12550 slash++;
12551 GNUNET_asprintf (&address_uri,
12552 "%s-%s",
12553 prefix,
12554 slash);
12555
12557 "1 not global natted_address %u %s %s %s\n",
12558 queue->is_global_natted,
12559 uri,
12560 queue->address,
12561 slash);
12562
12563 uri_without_port = get_address_without_port (address_uri);
12564 if (1 != inet_pton (AF_INET, uri_without_port, &v4.sin_addr))
12565 {
12567 GNUNET_free (address_uri);
12568 GNUNET_free (uri_without_port);
12569 return;
12570 }
12571
12573 "2 not global natted_address %u %s %s\n",
12574 queue->is_global_natted,
12575 uri,
12576 queue->address);
12577
12578 if (GNUNET_NO == queue->is_global_natted)
12579 {
12581 GNUNET_free (address_uri);
12582 GNUNET_free (uri_without_port);
12583 return;
12584 }
12585
12587 "3 not global natted_address %u %s %s\n",
12588 queue->is_global_natted,
12589 uri,
12590 queue->address);
12591
12592 if (0 == strcmp (uri_without_port, address_uri))
12593 {
12595 GNUNET_free (address_uri);
12596 GNUNET_free (uri_without_port);
12597 return;
12598 }
12599
12601 "4 not global natted_address %u %s %s\n",
12602 queue->is_global_natted,
12603 uri,
12604 queue->address);
12605
12606 address_uri_without_port = get_address_without_port (queue->address);
12607 if (0 == strcmp (uri_without_port, address_uri_without_port))
12608 {
12609 queue->is_global_natted = GNUNET_NO;
12610 }
12611
12613 "not global natted_address %u %s %s %s %s %s %u\n",
12614 queue->is_global_natted,
12615 uri,
12616 queue->address,
12617 uri_without_port,
12618 address_uri_without_port,
12619 prefix,
12620 GNUNET_NO);
12622 GNUNET_free (address_uri);
12623 GNUNET_free (address_uri_without_port);
12624 GNUNET_free (uri_without_port);
12625}
12626
12627
12629{
12633 char *addr;
12634
12639};
12640
12641
12642static enum GNUNET_GenericReturnValue
12643contains_address (void *cls,
12644 const struct GNUNET_PeerIdentity *pid,
12645 void *value)
12646{
12647 struct TransportGlobalNattedAddressClosure *tgna_cls = cls;
12648 struct TransportGlobalNattedAddress *tgna = value;
12649 char *addr = (char *) &tgna[1];
12650
12652 "Checking tgna %p with addr %s and length %u compare length %lu\n",
12653 tgna,
12654 addr,
12655 ntohl (tgna->address_length),
12656 strlen (tgna_cls->addr));
12657 if (strlen (tgna_cls->addr) == ntohl (tgna->address_length)
12658 && 0 == strncmp (addr, tgna_cls->addr, ntohl (tgna->address_length)))
12659 {
12660 tgna_cls->tgna = tgna;
12661 return GNUNET_NO;
12662 }
12663 return GNUNET_YES;
12664}
12665
12666
12667static void
12669{
12671 "Error in PEERSTORE monitoring for checking global natted\n");
12672}
12673
12674
12675static void
12677{
12679 "Done with initial PEERSTORE iteration during monitoring for checking global natted\n");
12680}
12681
12682
12683static void
12684check_for_global_natted (void *cls,
12685 const struct GNUNET_PEERSTORE_Record *record,
12686 const char *emsg)
12687{
12688 struct Queue *queue = cls;
12689 struct Neighbour *neighbour = queue->neighbour;
12691 struct GNUNET_MessageHeader *hello;
12693 size_t address_len_without_port;
12694
12695 if (NULL != emsg)
12696 {
12698 "Got failure from PEERSTORE: %s\n",
12699 emsg);
12700 return;
12701 }
12702 if (0 == record->value_size)
12703 {
12705 GNUNET_break (0);
12706 return;
12707 }
12708 queue->is_global_natted = GNUNET_YES;
12709 hello = record->value;
12710 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
12712 "before not global natted %u\n",
12713 queue->is_global_natted);
12716 queue);
12718 "after not global natted %u\n",
12719 queue->is_global_natted);
12720 GNUNET_HELLO_parser_free (parser);
12721
12722 tgna_cls.addr = get_address_without_port (queue->address);
12723 address_len_without_port = strlen (tgna_cls.addr);
12724 /*{
12725 char buf[address_len_without_port + 1];
12726
12727 GNUNET_memcpy (&buf, addr, address_len_without_port);
12728 buf[address_len_without_port] = '\0';
12729 GNUNET_free (addr);
12730 GNUNET_memcpy (tgna_cls.addr, buf, address_len_without_port + 1);
12731 }*/
12732 tgna_cls.tgna = NULL;
12734 &neighbour->pid,
12736 &tgna_cls);
12737 if (NULL != tgna_cls.tgna)
12739 " tgna_cls.tgna tgna %p %lu %u %u\n",
12740 tgna_cls.tgna,
12741 neighbour->size_of_global_addresses,
12742 ntohl (tgna_cls.tgna->address_length),
12743 neighbour->number_of_addresses);
12744 if (NULL == tgna_cls.tgna && GNUNET_YES == queue->is_global_natted)
12745 {
12746 struct TransportGlobalNattedAddress *tgna;
12747
12748 tgna = GNUNET_malloc (sizeof (struct TransportGlobalNattedAddress)
12749 + address_len_without_port);
12750 tgna->address_length = htonl (address_len_without_port);
12751 GNUNET_memcpy (&tgna[1], tgna_cls.addr, address_len_without_port);
12753 &neighbour->pid,
12754 tgna,
12756 neighbour->number_of_addresses++;
12757 neighbour->size_of_global_addresses += address_len_without_port + 1;
12759 "Created tgna %p with address %s and length %lu\n",
12760 tgna,
12761 tgna_cls.addr,
12762 address_len_without_port + 1);
12763 }
12764 else if (NULL != tgna_cls.tgna && GNUNET_NO == queue->is_global_natted)
12765 {
12767 &neighbour->pid,
12768 tgna_cls.tgna);
12769 GNUNET_assert (neighbour->size_of_global_addresses >= ntohl (tgna_cls.tgna->
12771 );
12772 neighbour->size_of_global_addresses -= ntohl (tgna_cls.tgna->address_length)
12773 ;
12774 GNUNET_assert (0 < neighbour->number_of_addresses);
12775 neighbour->number_of_addresses--;
12777 "removed tgna %p\n",
12778 tgna_cls.tgna);
12779 GNUNET_free (tgna_cls.tgna);
12780 }
12782 GNUNET_free (tgna_cls.addr);
12783}
12784
12785
12792static void
12793handle_add_queue_message (void *cls,
12794 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
12795{
12796 struct TransportClient *tc = cls;
12797 struct Queue *queue;
12798 struct Neighbour *neighbour;
12799 const char *addr;
12800 uint16_t addr_len;
12801
12802 if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
12803 {
12804 /* MTU so small as to be useless for transmissions,
12805 required for #fragment_message()! */
12806 GNUNET_break_op (0);
12808 return;
12809 }
12810 /* This may simply be a queue update */
12811 for (queue = tc->details.communicator.queue_head;
12812 NULL != queue;
12813 queue = queue->next_client)
12814 {
12815 if (queue->qid != ntohl (aqm->qid))
12816 continue;
12817 break;
12818 }
12819
12820 if (NULL != queue)
12821 {
12822 neighbour = queue->neighbour;
12823 }
12824 else
12825 {
12826 struct GNUNET_TIME_Absolute validated_until = GNUNET_TIME_UNIT_ZERO_ABS;
12827
12828 neighbour = lookup_neighbour (&aqm->receiver);
12829 if (NULL == neighbour)
12830 {
12831 neighbour = GNUNET_new (struct Neighbour);
12833 GNUNET_YES);
12834 neighbour->pid = aqm->receiver;
12837 neighbours,
12838 &neighbour->pid,
12839 neighbour,
12841 neighbour->get =
12843 "transport",
12844 &neighbour->pid,
12847 neighbour);
12848 }
12849 addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
12850 addr = (const char *) &aqm[1];
12852 "New queue %s to %s available with QID %u and q_len %" PRIu64
12853 " and mtu %u\n",
12854 addr,
12855 GNUNET_i2s (&aqm->receiver),
12856 ntohl (aqm->qid),
12857 GNUNET_ntohll (aqm->q_len),
12858 ntohl (aqm->mtu));
12859 queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
12860 queue->tc = tc;
12861 for (struct Queue *q = neighbour->queue_head; NULL != q; q = q->
12862 next_neighbour)
12863 validated_until = GNUNET_TIME_absolute_max (validated_until, q->
12864 validated_until);
12865 if (0 == GNUNET_TIME_absolute_get_remaining (validated_until).rel_value_us)
12866 {
12868 "New queue with QID %u inherit validated until\n",
12869 ntohl (aqm->qid));
12870 queue->validated_until = validated_until;
12871 }
12872 queue->address = (const char *) &queue[1];
12873 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
12874 queue->qid = ntohl (aqm->qid);
12875 queue->neighbour = neighbour;
12877 queue->unlimited_length = GNUNET_YES;
12878 queue->q_capacity = GNUNET_ntohll (aqm->q_len);
12879 memcpy (&queue[1], addr, addr_len);
12880 /* notify monitors about new queue */
12881 {
12882 struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
12883
12884 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
12885 }
12887 neighbour->queue_head,
12888 neighbour->queue_tail,
12889 queue);
12891 tc->details.communicator.queue_head,
12892 tc->details.communicator.queue_tail,
12893 queue);
12894
12895 }
12896 queue->mtu = ntohl (aqm->mtu);
12897 queue->nt = ntohl (aqm->nt);
12898 queue->cs = ntohl (aqm->cs);
12899 queue->idle = GNUNET_YES;
12900
12901 {
12902 struct sockaddr_in v4;
12903 char *addr_without = get_address_without_port (queue->address);
12904 if (1 == inet_pton (AF_INET, addr_without, &v4.sin_addr))
12905 {
12907 "start not global natted\n");
12909 GNUNET_YES,
12910 "peerstore",
12911 &neighbour->pid,
12913 &
12915 NULL,
12916 &
12918 NULL,
12920 queue);
12921 }
12922 GNUNET_free (addr_without);
12923 }
12924 /* check if valdiations are waiting for the queue */
12926 &aqm->receiver))
12927 {
12930 &aqm->
12931 receiver,
12932 &
12934 queue))
12935 start_address_validation (&aqm->receiver, queue->address);
12936 }
12937 else
12938 start_address_validation (&aqm->receiver, queue->address);
12939 /* look for traffic for this queue */
12940 // TODO Check whether this makes any sense at all.
12941 /*schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
12942 queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);*/
12943 /* might be our first queue, try launching DV learning */
12944 if (NULL == dvlearn_task)
12947}
12948
12949
12956static void
12958 const struct
12960{
12961 struct TransportClient *tc = cls;
12962 struct Queue *target_queue = NULL;
12963
12965 "Received queue update message for %u with q_len %llu and mtu %u\n",
12966 ntohl (msg->qid),
12967 (unsigned long long) GNUNET_ntohll (msg->q_len),
12968 ntohl (msg->mtu));
12969 for (target_queue = tc->details.communicator.queue_head;
12970 NULL != target_queue;
12971 target_queue = target_queue->next_client)
12972 {
12973 if (ntohl (msg->qid) == target_queue->qid)
12974 break;
12975 }
12976 if (NULL == target_queue)
12977 {
12979 "Queue to update no longer exists! Discarding update.\n");
12980 return;
12981 }
12982
12983 target_queue->nt = msg->nt;
12984 target_queue->mtu = ntohl (msg->mtu);
12985 target_queue->cs = msg->cs;
12986 target_queue->priority = ntohl (msg->priority);
12987 /* The update message indicates how many messages
12988 * the queue should be able to handle.
12989 */
12991 target_queue->unlimited_length = GNUNET_YES;
12992 else
12993 target_queue->unlimited_length = GNUNET_NO;
12994 target_queue->q_capacity += GNUNET_ntohll (msg->q_len);
12995 if (0 < target_queue->q_capacity)
12997 target_queue,
13000}
13001
13002
13010static void
13011handle_queue_create_ok (void *cls,
13012 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
13013{
13014 struct TransportClient *tc = cls;
13015
13016 if (CT_COMMUNICATOR != tc->type)
13017 {
13018 GNUNET_break (0);
13020 return;
13021 }
13023 "# Suggestions succeeded at communicator",
13024 1,
13025 GNUNET_NO);
13027 "Request #%u for communicator to create queue succeeded\n",
13028 (unsigned int) ntohs (cqr->request_id));
13030}
13031
13032
13041static void
13043 void *cls,
13044 const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
13045{
13046 struct TransportClient *tc = cls;
13047
13048 if (CT_COMMUNICATOR != tc->type)
13049 {
13050 GNUNET_break (0);
13052 return;
13053 }
13055 "Request #%u for communicator to create queue failed\n",
13056 (unsigned int) ntohl (cqr->request_id));
13058 "# Suggestions failed in queue creation at communicator",
13059 1,
13060 GNUNET_NO);
13062}
13063
13064
13072static void
13073handle_suggest_cancel (void *cls, const struct ExpressPreferenceMessage *msg)
13074{
13075 struct TransportClient *tc = cls;
13076 struct PeerRequest *pr;
13077
13078 if (CT_APPLICATION != tc->type)
13079 {
13080 GNUNET_break (0);
13082 return;
13083 }
13084 pr = GNUNET_CONTAINER_multipeermap_get (tc->details.application.requests,
13085 &msg->peer);
13086 if (NULL == pr)
13087 {
13088 GNUNET_break (0);
13090 return;
13091 }
13092 (void) stop_peer_request (tc, &pr->pid, pr);
13094}
13095
13096
13097static void
13098hello_for_client_cb (void *cls,
13099 const struct GNUNET_PeerIdentity *pid,
13100 const char *uri)
13101{
13102 struct Queue *q;
13103 int pfx_len;
13104 const char *eou;
13105 char *address;
13106 (void) cls;
13107
13108 eou = strstr (uri,
13109 "://");
13110 pfx_len = eou - uri;
13111 eou += 3;
13113 "%.*s-%s",
13114 pfx_len,
13115 uri,
13116 eou);
13117
13119 "hello for client %s\n",
13120 address);
13121
13122 q = find_queue (pid, address);
13123 if (NULL == q)
13124 {
13126 }
13127 else
13130}
13131
13132
13140static void
13141handle_hello_for_client (void *cls,
13142 const struct GNUNET_PEERSTORE_Record *record,
13143 const char *emsg)
13144{
13145 const struct GNUNET_PeerIdentity *my_identity;
13146 struct PeerRequest *pr = cls;
13148 struct GNUNET_MessageHeader *hello;
13149
13150 if (NULL != emsg)
13151 {
13153 "Got failure from PEERSTORE: %s\n",
13154 emsg);
13155 return;
13156 }
13158 if (NULL == my_identity)
13159 {
13161 "No identity given yet!\n");
13162 return;
13163 }
13164 hello = record->value;
13165 if (0 == GNUNET_memcmp (&record->peer, my_identity))
13166 {
13168 return;
13169 }
13170 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
13171 if (NULL == parser)
13172 {
13174 "HELLO cannot be parsed!\n");
13175 return;
13176 }
13178 "HELLO for `%s' could be parsed, iterating addresses...!\n",
13182 NULL);
13183 GNUNET_HELLO_parser_free (parser);
13184}
13185
13186
13187static void
13188hello_for_client_error_cb (void *cls)
13189{
13191 "Error in PEERSTORE monitoring\n");
13192}
13193
13194
13195static void
13196hello_for_client_sync_cb (void *cls)
13197{
13199 "Done with initial PEERSTORE iteration during monitoring\n");
13200}
13201
13202
13210static void
13211handle_suggest (void *cls, const struct ExpressPreferenceMessage *msg)
13212{
13213 struct TransportClient *tc = cls;
13214 const struct GNUNET_PeerIdentity *my_identity;
13215 struct PeerRequest *pr;
13216
13217 if (CT_NONE == tc->type)
13218 {
13219 tc->type = CT_APPLICATION;
13220 tc->details.application.requests =
13222 }
13223 if (CT_APPLICATION != tc->type)
13224 {
13225 GNUNET_break (0);
13227 return;
13228 }
13230 if (NULL == my_identity)
13231 {
13233 "Still waiting for own identity!\n");
13235 return;
13236 }
13238 "Client suggested we talk to %s with preference %d at rate %u\n",
13239 GNUNET_i2s (&msg->peer),
13240 (int) ntohl (msg->pk),
13241 (int) ntohl (msg->bw.value__));
13242 if (0 == GNUNET_memcmp (my_identity, &msg->peer))
13243 {
13245 "Client suggested connection to ourselves, ignoring...\n");
13247 return;
13248 }
13249 pr = GNUNET_new (struct PeerRequest);
13250 pr->tc = tc;
13251 pr->pid = msg->peer;
13252 pr->bw = msg->bw;
13253 pr->pk = ntohl (msg->pk);
13255 tc->details.application.requests,
13256 &pr->pid,
13257 pr,
13259 {
13260 GNUNET_break (0);
13261 GNUNET_free (pr);
13263 return;
13264 }
13265 pr->nc =
13267 GNUNET_YES,
13268 "peerstore",
13269 NULL,
13272 NULL,
13274 NULL,
13276 pr);
13278}
13279
13280
13289static int
13291 const struct RequestHelloValidationMessage *m)
13292{
13293 (void) cls;
13295 return GNUNET_OK;
13296}
13297
13298
13306static void
13308 const struct RequestHelloValidationMessage *m)
13309{
13310 struct TransportClient *tc = cls;
13311 struct Queue *q;
13312
13313 q = find_queue (&m->peer, (const char *) &m[1]);
13314 if (NULL == q)
13315 {
13316 suggest_to_connect (&m->peer, (const char *) &m[1]);
13317 }
13318 else
13319 start_address_validation (&m->peer, (const char *) &m[1]);
13321}
13322
13323
13332static int
13333free_neighbour_cb (void *cls,
13334 const struct GNUNET_PeerIdentity *pid,
13335 void *value)
13336{
13337 struct Neighbour *neighbour = value;
13338
13339 (void) cls;
13340 (void) pid;
13341 GNUNET_break (0); // should this ever happen?
13342 free_neighbour (neighbour, GNUNET_YES);
13343
13344 return GNUNET_OK;
13345}
13346
13347
13356static int
13357free_dv_routes_cb (void *cls,
13358 const struct GNUNET_PeerIdentity *pid,
13359 void *value)
13360{
13361 struct DistanceVector *dv = value;
13362
13363 (void) cls;
13364 (void) pid;
13365 free_dv_route (dv);
13366
13367 return GNUNET_OK;
13368}
13369
13370
13379static int
13380free_validation_state_cb (void *cls,
13381 const struct GNUNET_PeerIdentity *pid,
13382 void *value)
13383{
13384 struct ValidationState *vs = value;
13385
13386 (void) cls;
13387 (void) pid;
13389 return GNUNET_OK;
13390}
13391
13392
13401static int
13402free_pending_ack_cb (void *cls, const struct GNUNET_Uuid *key, void *value)
13403{
13404 struct PendingAcknowledgement *pa = value;
13405
13406 (void) cls;
13407 (void) key;
13409 return GNUNET_OK;
13410}
13411
13412
13421static int
13422free_ack_cummulator_cb (void *cls,
13423 const struct GNUNET_PeerIdentity *pid,
13424 void *value)
13425{
13426 struct AcknowledgementCummulator *ac = value;
13427
13428 (void) cls;
13429 (void) pid;
13431 GNUNET_free (ac);
13432 return GNUNET_OK;
13433}
13434
13435
13442static void
13443do_shutdown (void *cls)
13444{
13445 struct LearnLaunchEntry *lle;
13446 struct PilsRequest *pr;
13447 (void) cls;
13448
13450 "shutdown logic\n");
13453 &free_neighbour_cb, NULL);
13454 if (NULL != validation_task)
13455 {
13457 validation_task = NULL;
13458 }
13459 if (NULL != dvlearn_task)
13460 {
13462 dvlearn_task = NULL;
13463 }
13464 if (NULL != burst_task)
13465 {
13467 burst_task = NULL;
13468 }
13469 if (NULL != burst_timeout_task)
13470 {
13472 burst_timeout_task = NULL;
13473 }
13476 dvlearn_map = NULL;
13479 dv_routes = NULL;
13480 if (NULL != GST_stats)
13481 {
13483 GST_stats = NULL;
13484 }
13485 if (NULL != GST_my_hello)
13486 {
13488 GST_my_hello = NULL;
13489 }
13492 NULL);
13494 ack_cummulators = NULL;
13497 NULL);
13499 pending_acks = NULL;
13502 neighbours = NULL;
13505 links = NULL;
13508 NULL);
13510 backtalkers = NULL;
13513 NULL);
13515 validation_map = NULL;
13517 validation_heap = NULL;
13519 revalidation_map = NULL;
13520 while (NULL != ir_head)
13522 GNUNET_assert (0 == ir_total);
13523 while (NULL != (lle = lle_head))
13524 {
13526 GNUNET_free (lle);
13527 }
13528 while (NULL != (pr = pils_requests_head))
13529 {
13532 pr);
13533 if (NULL != pr->op)
13534 GNUNET_PILS_cancel (pr->op);
13535 GNUNET_free (pr);
13536 }
13537 if (NULL != pils_feed_task)
13538 {
13540 pils_feed_task = NULL;
13541 }
13542 if (NULL != pils)
13543 {
13545 pils = NULL;
13546 }
13547 if (NULL != peerstore)
13548 {
13550 "Disconnecting from PEERSTORE service\n");
13552 peerstore = NULL;
13553 }
13555}
13556
13557
13558static const char*
13560{
13561 switch (type)
13562 {
13563 case CT_CORE:
13564 return "CORE";
13565 case CT_MONITOR:
13566 return "MONITOR";
13567 case CT_COMMUNICATOR:
13568 return "COMMUNICATOR";
13569 case CT_APPLICATION:
13570 return "APPLICATION";
13571 default:
13572 return "UNKNOWN";
13573 }
13574}
13575
13576
13577static void
13578shutdown_task (void *cls)
13579{
13581
13583 "Shutdown task executed\n");
13584 if (NULL != clients_head)
13585 {
13586 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
13587 {
13589 "Client still connected: %s\n",
13590 get_client_type_name (tc->type));
13591 }
13592 }
13593 else
13594 do_shutdown (cls);
13595
13596}
13597
13598
13600{
13602};
13603
13604static void
13605update_hello_from_pid_change_cb (void *cls, int success)
13606{
13607 struct UpdateHelloFromPidCtx *pc = cls;
13608
13609 if (GNUNET_OK != success)
13610 {
13612 "Failed to store our new hello with peerstore\n");
13613 }
13614 GNUNET_free (pc);
13616 "Stored our new hello with peerstore\n");
13617}
13618
13619
13620void
13621print_address_list (void *cls,
13622 const struct GNUNET_PeerIdentity *pid,
13623 const char *uri)
13624{
13626 "%s\n", uri);
13627}
13628
13629
13639static void
13640pils_pid_change_cb (void *cls,
13641 const struct GNUNET_HELLO_Parser *parser,
13642 const struct GNUNET_HashCode *hash)
13643{
13644 const struct GNUNET_PeerIdentity *my_identity;
13645 struct GNUNET_MQ_Envelope *env;
13646 const struct GNUNET_MessageHeader *msg;
13647 struct UpdateHelloFromPidCtx *sc;
13648 struct GNUNET_HELLO_Builder *nbuilder;
13649 struct GNUNET_PeerIdentity npid;
13650
13653
13654 if (NULL == GST_my_hello)
13657 "My current identity is `%s'\n",
13669 nbuilder = GNUNET_HELLO_builder_from_parser (parser,
13670 &npid);
13671 if (GNUNET_NO ==
13673 {
13675 "New PID from PILS is derived from address list inconsistent with ours. Ignoring...\n");
13677 "Proposed address list:\n");
13680 "Current address list:\n");
13682 GNUNET_HELLO_builder_free (nbuilder);
13683 return;
13684 }
13686 GST_my_hello = nbuilder;
13688 "My new identity is `%s'\n",
13694 msg,
13696 sc);
13697 GNUNET_free (env);
13698}
13699
13700
13708static void
13709run (void *cls,
13710 const struct GNUNET_CONFIGURATION_Handle *c,
13712{
13713 (void) cls;
13714 (void) service;
13715 /* setup globals */
13718 GST_cfg = c;
13726 GNUNET_YES);
13731 // TODO check for all uses of GST_my_hello that it is not used uninitialized
13733 "transport",
13734 "USE_BURST_NAT");
13735 if (GNUNET_SYSERR == use_burst)
13737 "Could not configure burst nat use. Default to no.\n");
13743 "transport",
13744 0,
13745 0,
13746 NULL,
13747 0,
13748 NULL,
13749 NULL,
13750 NULL);
13751 if (NULL == peerstore)
13752 {
13753 GNUNET_break (0);
13755 return;
13756 }
13759 NULL); // FIXME we need to wait for
13760 // our first peer id before
13761 // we can start the service
13762 // completely - PILS in turn
13763 // waits for the first
13764 // addresses from the
13765 // communicators in order to
13766 // be able to generate a
13767 // peer id
13768 if (NULL == pils)
13769 {
13770 GNUNET_break (0);
13772 return;
13773 }
13774}
13775
13776
13782 "transport",
13784 &run,
13787 NULL,
13788 /* communication with applications */
13789 GNUNET_MQ_hd_fixed_size (suggest,
13792 NULL),
13793 GNUNET_MQ_hd_fixed_size (suggest_cancel,
13796 NULL),
13797 GNUNET_MQ_hd_var_size (request_hello_validation,
13800 NULL),
13801 /* communication with core */
13802 GNUNET_MQ_hd_fixed_size (client_start,
13804 struct StartMessage,
13805 NULL),
13806 GNUNET_MQ_hd_var_size (client_send,
13808 struct OutboundMessage,
13809 NULL),
13810 GNUNET_MQ_hd_fixed_size (client_recv_ok,
13812 struct RecvOkMessage,
13813 NULL),
13814 /* communication with communicators */
13815 GNUNET_MQ_hd_var_size (communicator_available,
13818 NULL),
13819 GNUNET_MQ_hd_var_size (communicator_backchannel,
13822 NULL),
13823 GNUNET_MQ_hd_var_size (add_address,
13826 NULL),
13827 GNUNET_MQ_hd_fixed_size (del_address,
13830 NULL),
13831 GNUNET_MQ_hd_var_size (incoming_msg,
13834 NULL),
13835 GNUNET_MQ_hd_fixed_size (queue_create_ok,
13838 NULL),
13839 GNUNET_MQ_hd_fixed_size (queue_create_fail,
13842 NULL),
13843 GNUNET_MQ_hd_var_size (add_queue_message,
13846 NULL),
13847 GNUNET_MQ_hd_fixed_size (update_queue_message,
13850 NULL),
13851 GNUNET_MQ_hd_fixed_size (del_queue_message,
13854 NULL),
13855 GNUNET_MQ_hd_fixed_size (send_message_ack,
13858 NULL),
13859 GNUNET_MQ_hd_fixed_size (burst_finished,
13862 NULL),
13863 /* communication with monitors */
13864 GNUNET_MQ_hd_fixed_size (monitor_start,
13867 NULL),
13869
13870
13871/* end of file gnunet-service-transport.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition 002.c:5
struct GNUNET_MQ_MessageHandlers handlers[]
Definition 003.c:1
struct GNUNET_MessageHeader * msg
Definition 005.c:2
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition gnunet-arm.c:103
static int start
Set if we are to start default services (including ARM).
Definition gnunet-arm.c:38
static int ret
Final status code.
Definition gnunet-arm.c:93
static char * init
Set to the name of a service to start.
Definition gnunet-arm.c:73
static int do_shutdown
Set to GNUNET_YES if we are shutting down.
static struct GNUNET_CADET_Handle * mh
Cadet handle.
static struct GNUNET_TESTING_Interpreter * is
static struct Queue * queue_head
Head of queue of messages to transmit.
static int prefix
If printing the value of PREFIX has been requested.
static struct GNUNET_SCHEDULER_Task * st
The shutdown task.
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
static char * address
GNS address for this phone.
static GNUNET_NETWORK_STRUCT_END struct GNUNET_PeerIdentity me
Our own peer identity.
static struct GNUNET_DATASTORE_QueueEntry * qe
Current operation.
static char * data
The data to insert into the dht.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_TIME_Relative expiration
User supplied expiration value.
static struct GNUNET_FS_Handle * ctx
static OpusEncoder * enc
OPUS encoder.
struct GNUNET_SCHEDULER_Task * shutdown_task
static void queue(const char *label, uint32_t rd_count, struct GNUNET_GNSRECORD_Data *rd, const struct Zone *zone)
Add hostname to the list of requests to be made.
static char * res
Currently read line or NULL on EOF.
static char * value
Value of the record to add/remove.
static uint32_t type
Type string converted to DNS type value.
static size_t data_size
Number of bytes in data.
static struct GNUNET_NAT_AUTO_Test * nt
Handle to a NAT test operation.
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
static struct GNUNET_FS_PublishContext * pc
Handle to FS-publishing operation.
static int result
Global testing status.
static struct GNUNET_REVOCATION_Query * q
Handle for revocation query.
static struct GNUNET_FS_SearchContext * sc
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static 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 enum GNUNET_GenericReturnValue dv_decrypt(struct DVKeyState *key, void *out, const void *ciph, size_t out_size)
Perform backchannel encryption using symmetric secret in key to encrypt data from in to dst.
static int dv_neighbour_transmission(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Function called for each neighbour during handle_dv_learn.
static void reassembly_cleanup_task(void *cls)
Task run to clean up reassembly context of a neighbour that have expired.
static void pils_sign_addr_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
static enum GNUNET_GenericReturnValue remove_global_addresses(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
static void backtalker_timeout_cb(void *cls)
Function called when it is time to clean up a backtalker.
static void handle_add_address(void *cls, const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
Address of our peer added.
static unsigned int calculate_fork_degree(unsigned int hops_taken, unsigned int neighbour_count, unsigned int eligible_count)
Computes the number of neighbours we should forward a DVInit message to given that it has so far take...
static void dv_key_clean(struct DVKeyState *key)
Clean up key material in key.
static struct GNUNET_SCHEDULER_Task * dvlearn_task
Task run to initiate DV learning.
static int check_reliability_box(void *cls, const struct TransportReliabilityBoxMessage *rb)
Communicator gave us a reliability box.
static void handle_communicator_available(void *cls, const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
Communicator started.
static int check_fragment_box(void *cls, const struct TransportFragmentBoxMessage *fb)
Communicator gave us a fragment box.
static unsigned int get_age()
Get an offset into the transmission history buffer for struct PerformanceData.
static void free_validation_state(struct ValidationState *vs)
Free validation state.
static struct PendingAcknowledgement * prepare_pending_acknowledgement(struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
Setup data structure waiting for acknowledgements.
static int check_request_hello_validation(void *cls, const struct RequestHelloValidationMessage *m)
Check GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION messages.
static void hello_for_incoming_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
#define MAX_DV_DISCOVERY_SELECTION
Maximum number of peers we select for forwarding DVInit messages at the same time (excluding initiato...
#define QUEUE_ENTRY_TIMEOUT
static struct LearnLaunchEntry * lle_tail
Tail of a DLL sorted by launch time.
static struct GNUNET_CONTAINER_Heap * validation_heap
MIN Heap sorted by "next_challenge" to struct ValidationState entries sorting addresses we are aware ...
static void core_send_connect_info(struct TransportClient *tc, const struct GNUNET_PeerIdentity *pid)
Send message to CORE clients that we lost a connection.
static void send_dv_to_neighbour(void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Wrapper around route_via_neighbour() that matches the DVMessageHandler structure.
static void harmonize_flight_round(struct PendingMessage *pm)
#define ACK_CUMMULATOR_TIMEOUT
How long until we forget about historic accumulators and thus reset the ACK counter?...
void pils_sign_address(struct AddressListEntry *ale, struct GNUNET_TIME_Absolute mono_time)
Build address record by signing raw information with private key of the peer identity.
static void free_queue(struct Queue *queue)
Free queue.
static void handle_del_address(void *cls, const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
Address of our peer deleted.
static struct LearnLaunchEntry * lle_head
Head of a DLL sorted by launch time.
#define EPHEMERAL_VALIDITY
How long are ephemeral keys valid?
static void free_fragment_tree(struct PendingMessage *root)
Free fragment tree below root, excluding root itself.
static unsigned int is_ring_buffer_full
Is the ring buffer filled up to RING_BUFFER_SIZE.
static struct IncomingRequest * ir_tail
Tail of DLL starting at ir_head.
static void pils_pid_change_cb(void *cls, const struct GNUNET_HELLO_Parser *parser, const struct GNUNET_HashCode *hash)
Callback called when pils service updates us with our new peer identity.
static int free_pending_ack_cb(void *cls, const struct GNUNET_Uuid *key, void *value)
Free pending acknowledgement.
static int check_dv_box(void *cls, const struct TransportDVBoxMessage *dvb)
Communicator gave us a DV box.
static void completed_pending_message(struct PendingMessage *pm)
We have completed transmission of pm, remove it from the transmission queues (and if it is a fragment...
static void update_dvh_performance(struct DistanceVectorHop *dvh, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
We have successfully transmitted data via dvh, update metrics.
struct GNUNET_NAT_Handle * nh
Handle for connect to the NAT service.
static int check_add_queue_message(void *cls, const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
New queue became available.
static struct GNUNET_SCHEDULER_Task * pils_feed_task
Task to feed addresses to PILS.
static void client_send_response(struct PendingMessage *pm)
Send a response to the pm that we have processed a "send" request.
static void start_dv_learn(void *cls)
Task run when we CONSIDER initiating a DV learn process.
static int dv_neighbour_selection(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Function called for each neighbour during handle_dv_learn.
static void start_address_validation(const struct GNUNET_PeerIdentity *pid, const char *address)
Start address validation.
static void handle_del_queue_message(void *cls, const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
Queue to a peer went down.
#define QUEUE_LENGTH_LIMIT
How many messages can we have pending for a given queue (queue to a particular peer via a communicato...
static void update_backtalker_monotime(struct Backtalker *b)
The backtalker b monotonic time changed.
#define MAX_CUMMULATIVE_ACKS
Maximum number of messages we acknowledge together in one cumulative ACK.
#define MAX_DV_HOPS_ALLOWED
Maximum DV distance allowed ever.
static 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 void dv_hmac(const struct DVKeyState *key, struct GNUNET_HashCode *hmac, const void *data, size_t data_size)
Do HMAC calculation for backchannel messages over data using key material from key.
static struct PilsRequest * pils_requests_head
PILS Operation DLL.
#define COMMUNICATOR_TOTAL_QUEUE_LIMIT
How many messages can we have pending for a given communicator process before we start to throttle th...
static void free_reassembly_context(struct ReassemblyContext *rc)
Free rc.
static struct VirtualLink * lookup_virtual_link(const struct GNUNET_PeerIdentity *pid)
Lookup virtual link for peer pid.
static int check_connection_quality(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Check whether any queue to the given neighbour is of a good "quality" and if so, increment the counte...
static void reorder_root_pm(struct PendingMessage *pm, struct GNUNET_TIME_Absolute next_attempt)
static void core_env_sent_cb(void *cls)
Function called when we are done giving a message of a certain size to CORE and should thus decrement...
static unsigned int ir_total
Length of the DLL starting at ir_head.
static int in_shutdown
Indication if we have received a shutdown signal and are in the process of cleaning up.
static void select_best_pending_from_link(struct PendingMessageScoreContext *sc, struct Queue *queue, struct VirtualLink *vl, struct DistanceVectorHop *dvh, size_t overhead)
Select the best pending message from vl for transmission via queue.
static void suggest_to_connect(const struct GNUNET_PeerIdentity *pid, const char *address)
Signature of a function called with a communicator address of a peer pid that an application wants us...
static void free_timedout_queue_entry(void *cls)
static void sign_t_validation_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
static void handle_send_message_ack(void *cls, const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
Message was transmitted.
static void update_pd_age(struct PerformanceData *pd, unsigned int age)
Check if we have advanced to another age since the last time.
#define DV_LEARN_BASE_FREQUENCY
What is the non-randomized base frequency at which we would initiate DV learn messages?
struct GNUNET_SCHEDULER_Task * burst_timeout_task
static void free_pending_acknowledgement(struct PendingAcknowledgement *pa)
Release pa data structure.
static struct GNUNET_CONTAINER_MultiUuidmap * pending_acks
Map of pending acknowledgements, mapping struct AcknowledgementUUID to a struct PendingAcknowledgemen...
static struct GNUNET_CONTAINER_MultiShortmap * dvlearn_map
Map from challenges to struct LearnLaunchEntry values.
#define DV_FORWARD_TIMEOUT
If a DVBox could not be forwarded after this number of seconds we drop it.
static void finish_handling_raw_message(struct VirtualLink *vl, const struct GNUNET_MessageHeader *mh, struct CommunicatorMessageContext *cmc, unsigned int free_cmc)
static void handle_add_queue_message(void *cls, const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
New queue became available.
static void update_queue_performance(struct Queue *q, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
We have successfully transmitted data via q, update metrics.
static void schedule_transmit_on_queue(struct GNUNET_TIME_Relative delay, struct Queue *queue, enum GNUNET_SCHEDULER_Priority p)
Called whenever something changed that might effect when we try to do the next transmission on queue ...
static void set_pending_message_uuid(struct PendingMessage *pm)
If necessary, generates the UUID for a pm.
static void free_pending_message(struct PendingMessage *pm)
Release memory associated with pm and remove pm from associated data structures.
static void revalidation_start_cb(void *cls)
static void backtalker_monotime_store_cb(void *cls, int success)
Function called by PEERSTORE when the store operation of a backtalker's monotonic time is complete.
static int free_reassembly_cb(void *cls, uint32_t key, void *value)
function called to free_reassembly_context().
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
Called whenever a client connects.
#define DV_PATH_VALIDITY_TIMEOUT
How long do we consider a DV path valid if we see no further updates on it? Note: the value chosen he...
#define RING_BUFFER_SIZE
Size of ring buffer to cache CORE and forwarded DVBox messages.
static void check_vl_transmission(struct VirtualLink *vl)
There is a message at the head of the pending messages for vl which may be ready for transmission.
static int find_by_message_uuid(void *cls, uint32_t key, void *value)
Iterator called to find a reassembly context by the message UUID in the multihashmap32.
static struct TransportClient * lookup_communicator(const char *prefix)
Find transport client providing communication service for the protocol prefix.
static unsigned int ring_buffer_head
Head of the ring buffer.
#define MAX_ADDRESS_VALID_UNTIL
When do we forget an invalid address for sure?
static void handle_hello_for_client(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called by PEERSTORE for each matching record.
static void sign_dhp_cp(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
static void handle_suggest_cancel(void *cls, const struct ExpressPreferenceMessage *msg)
We have received a struct ExpressPreferenceMessage from an application client.
static void update_performance_data(struct PerformanceData *pd, struct GNUNET_TIME_Relative rtt, uint16_t bytes_transmitted_ok)
Update pd based on the latest rtt and the number of bytes that were confirmed to be successfully tran...
static void forward_dv_box(struct Neighbour *next_hop, struct TransportDVBoxMessage *hdr, uint16_t total_hops, uint16_t num_hops, const struct GNUNET_PeerIdentity *hops, const void *enc_payload, uint16_t enc_payload_size)
Create a DV Box message and queue it for transmission to next_hop.
static void handle_validation_response(void *cls, const struct TransportValidationResponseMessage *tvr)
Communicator gave us a transport address validation response.
static void handle_reliability_ack(void *cls, const struct TransportReliabilityAckMessage *ra)
Communicator gave us a reliability ack.
static void send_msg_from_cache(struct VirtualLink *vl)
static void free_address_list_entry(struct AddressListEntry *ale)
Free ale.
static unsigned int pick_random_dv_hops(const struct DistanceVector *dv, enum RouteMessageOptions options, struct DistanceVectorHop **hops_array, unsigned int hops_array_length)
Pick hops_array_length random DV paths satisfying options.
static void handle_burst_finished(void *cls, const struct GNUNET_TRANSPORT_BurstFinished *bf)
The burst finished.
static void hello_for_incoming_sync_cb(void *cls)
static enum GNUNET_GenericReturnValue resume_communicators(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
static struct PilsRequest * pils_requests_tail
PILS Operation DLL.
static struct GNUNET_CONTAINER_MultiPeerMap * neighbours
Map from PIDs to struct Neighbour entries.
static void transmit_on_queue(void *cls)
We believe we are ready to transmit a message on a queue.
static void handle_dv_learn(void *cls, const struct TransportDVLearnMessage *dvl)
Communicator gave us a DV learn message.
static void iterate_address_start_burst(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static struct Queue * find_queue(const struct GNUNET_PeerIdentity *pid, const char *address)
Find the queue matching pid and address.
static void activate_core_visible_dv_path(struct DistanceVectorHop *hop)
The hop is a validated path to the respective target peer and we should tell core about it – and sche...
static void free_dv_route(struct DistanceVector *dv)
Free entry in dv_routes.
static unsigned int is_ring_buffer_dv_full
Is the ring buffer filled up to RING_BUFFER_SIZE.
static int check_communicator_backchannel(void *cls, const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
Communicator requests backchannel transmission.
#define DEFAULT_WINDOW_SIZE
How big is the flow control window size by default; limits per-neighbour RAM utilization.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Initiate transport service.
#define MAX_VALIDATION_CHALLENGE_FREQ
What is the slowest rate at which we send challenges?
static void handle_queue_create_ok(void *cls, const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
Communicator tells us that our request to create a queue "worked", that is setting up the queue is no...
static int notify_client_connect_info(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Iterator telling new CORE client about all existing connections to peers.
static void shc_cont(void *cls, int success)
static void handle_raw_message(void *cls, const struct GNUNET_MessageHeader *mh)
Communicator gave us an unencapsulated message to pass as-is to CORE.
static void handle_communicator_backchannel(void *cls, const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
Communicator requests backchannel transmission.
static unsigned long long logging_uuid_gen
Generator of logging_uuid in struct PendingMessage.
static int check_incoming_msg(void *cls, const struct GNUNET_TRANSPORT_IncomingMessage *im)
Client notified us about transmission from a peer.
#define REASSEMBLY_EXPIRATION
How long do we keep partially reassembled messages around before giving up?
static void update_next_challenge_time(struct ValidationState *vs, struct GNUNET_TIME_Absolute new_time)
Set the time for next_challenge of vs to new_time.
static struct Neighbour * lookup_neighbour(const struct GNUNET_PeerIdentity *pid)
Lookup neighbour for peer pid.
static void peerstore_store_own_cb(void *cls, int success)
Function called when peerstore is done storing our address.
static struct RingBufferEntry * ring_buffer[RING_BUFFER_SIZE]
Ring buffer for a CORE message we did not deliver to CORE, because of missing virtual link to sender.
#define MIN_DELAY_ADDRESS_VALIDATION
What is the maximum frequency at which we do address validation? A random value between 0 and this va...
static void handle_acknowledged(struct PendingAcknowledgement *pa, struct GNUNET_TIME_Relative ack_delay)
The pa was acknowledged, process the acknowledgement.
static struct GNUNET_CONTAINER_MultiPeerMap * backtalkers
Map from PIDs to struct Backtalker entries.
static struct GNUNET_TIME_Absolute hello_mono_time
Monotonic time we use for HELLOs generated at this time.
static int check_communicator_available(void *cls, const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
Communicator started.
static void handle_backchannel_encapsulation(void *cls, const struct TransportBackchannelEncapsulationMessage *be)
Communicator gave us a backchannel encapsulation.
static struct GNUNET_CONTAINER_MultiHashMap * revalidation_map
Map from addresses to struct ValidationState entries describing addresses we are aware of and their v...
static const struct GNUNET_CONFIGURATION_Handle * GST_cfg
Configuration handle.
static enum GNUNET_GenericReturnValue revalidate_map_it(void *cls, const struct GNUNET_HashCode *key, void *value)
#define DEFAULT_ACK_WAIT_DURATION
Default value for how long we wait for reliability ack.
static struct PendingMessage * reliability_box_message(struct Queue *queue, struct DistanceVectorHop *dvh, struct PendingMessage *pm)
Reliability-box the given pm.
static int free_backtalker_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Callback to free backtalker records.
static enum GNUNET_GenericReturnValue contains_address(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
static void path_cleanup_cb(void *cls)
Task called when we should check if any of the DV paths we have learned to a target are due for garba...
#define FAST_VALIDATION_CHALLENGE_FREQ
What is the fastest rate at which we send challenges if we keep learning an address (gossip,...
static int check_add_address(void *cls, const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
Address of our peer added.
static void demultiplex_with_cmc(struct CommunicatorMessageContext *cmc)
Given an inbound message msg from a communicator cmc, demultiplex it based on the type calling the ri...
#define MAX_DV_LEARN_PENDING
Maximum number of DV learning activities we may have pending at the same time.
static void hello_for_client_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static void validation_start_cb(void *cls)
Task run periodically to validate some address based on validation_heap.
#define VALIDATION_RTT_BUFFER_FACTOR
How many network RTTs before an address validation expires should we begin trying to revalidate?...
static void handle_client_recv_ok(void *cls, const struct RecvOkMessage *rom)
Client confirms that it is done handling message(s) to a particular peer.
static void feed_addresses_to_pils(void *cls)
static struct GNUNET_CONTAINER_MultiPeerMap * links
Map from PIDs to struct VirtualLink entries describing links CORE knows to exist.
static int check_client_send(void *cls, const struct OutboundMessage *obm)
Client asked for transmission to a peer.
static int check_backchannel_encapsulation(void *cls, const struct TransportBackchannelEncapsulationMessage *be)
Communicator gave us a backchannel encapsulation.
static struct TransportClient * clients_tail
Tail of linked list of all clients to this service.
static struct GNUNET_CONTAINER_MultiPeerMap * ack_cummulators
Map from PIDs to struct AcknowledgementCummulators.
static void transmit_cummulative_ack_cb(void *cls)
Do the transmission of a cumulative acknowledgement now.
static int check_validation_request_pending(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
A new queue has been created, check if any address validation requests have been waiting for it.
static struct GNUNET_STATISTICS_Handle * GST_stats
Statistics handle.
static struct GNUNET_SCHEDULER_Task * burst_task
The task to start the burst.
void print_address_list(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static struct GNUNET_TIME_Relative encapsulate_for_dv(struct DistanceVector *dv, unsigned int num_dvhs, struct DistanceVectorHop **dvhs, const struct GNUNET_MessageHeader *hdr, DVMessageHandler use, void *use_cls, enum RouteMessageOptions options, enum GNUNET_GenericReturnValue without_fc)
Pick a path of dv under constraints options and schedule transmission of hdr.
static void neighbour_store_dvmono_cb(void *cls, int success)
Function called when peerstore is done storing a DV monotonic time.
static void handle_request_hello_validation(void *cls, const struct RequestHelloValidationMessage *m)
A client encountered an address of another peer.
static void free_queue_entry(struct QueueEntry *qe, struct TransportClient *tc)
static void pils_sign_hello_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
Get HELLO signature and create message to store in PEERSTORE.
static void check_for_global_natted_sync_cb(void *cls)
static void handle_reliability_box(void *cls, const struct TransportReliabilityBoxMessage *rb)
Communicator gave us a reliability box.
static void notify_monitor(struct TransportClient *tc, const struct GNUNET_PeerIdentity *peer, const char *address, enum GNUNET_NetworkType nt, const struct MonitorEvent *me)
Notify monitor tc about an event.
static void check_for_burst_address(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
static unsigned int check_next_attempt_tree(struct PendingMessage *pm, struct PendingMessage *root)
static void hello_for_incoming_error_cb(void *cls)
static void queue_send_msg(struct Queue *queue, struct PendingMessage *pm, const void *payload, size_t payload_size)
Send the message payload on queue.
static void dv_setup_key_state_from_km(const struct GNUNET_ShortHashCode *km, const struct GNUNET_ShortHashCode *iv, struct DVKeyState *key)
Given the key material in km and the initialization vector iv, setup the key material for the backcha...
static void handle_flow_control(void *cls, const struct TransportFlowControlMessage *fc)
Communicator gave us a transport address validation response.
static int check_dv_learn(void *cls, const struct TransportDVLearnMessage *dvl)
Communicator gave us a DV learn message.
static void handle_hello_for_incoming(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called by PEERSTORE for each matching record.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
Called whenever a client is disconnected.
static int check_reliability_ack(void *cls, const struct TransportReliabilityAckMessage *ra)
Communicator gave us a reliability ack.
static void sign_dv_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig)
static void dv_encrypt(struct DVKeyState *key, const void *in, void *dst, size_t in_size)
Perform backchannel encryption using symmetric secret in key to encrypt data from in to dst.
static void iterate_address_and_compare_cb(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static struct GNUNET_CONTAINER_MultiPeerMap * validation_map
Map from PIDs to struct ValidationState entries describing addresses we are aware of and their validi...
static int free_dv_routes_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free DV route entry.
static enum GNUNET_GenericReturnValue add_global_addresses(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
#define MIN_DV_PATH_LENGTH_FOR_INITIATOR
Minimum number of hops we should forward DV learn messages even if they are NOT useful for us in hope...
static void handle_queue_create_fail(void *cls, const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
Communicator tells us that our request to create a queue failed.
static void check_link_down(void *cls)
Task run to check whether the hops of the cls still are validated, or if we need to core about discon...
static void check_for_global_natted_error_cb(void *cls)
static void finish_cmc_handling_with_continue(struct CommunicatorMessageContext *cmc, unsigned int free_cmc)
Send ACK to communicator (if requested) and free cmc.
static void forward_dv_learn(const struct GNUNET_PeerIdentity *next_hop, const struct TransportDVLearnMessage *msg, uint16_t bi_history, uint16_t nhops, const struct DVPathEntryP *hops, struct GNUNET_TIME_Absolute in_time)
Build and forward a DV learn message to next_hop.
static void handle_incoming_msg(void *cls, const struct GNUNET_TRANSPORT_IncomingMessage *im)
Incoming message.
static void validation_transmit_on_queue(struct Queue *q, struct ValidationState *vs)
The queue q (which matches the peer and address in vs) is ready for queueing.
static int free_ack_cummulator_cb(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Free acknowledgement cummulator.
static void update_pm_next_attempt(struct PendingMessage *pm, struct GNUNET_TIME_Absolute next_attempt)
Change the value of the next_attempt field of pm to next_attempt and re-order pm in the transmission ...
#define PILS_FEED_ADDRESSES_DELAY
Delay between added/removed addresses and PILS feed call.
static int check_known_address(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
Test if the validation state in value matches the address from cls.
enum GNUNET_GenericReturnValue use_burst
static struct GNUNET_CONTAINER_MultiPeerMap * dv_routes
Map from PIDs to struct DistanceVector entries describing known paths to the peer.
static struct GNUNET_TIME_Relative route_control_message_without_fc(struct VirtualLink *vl, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
We need to transmit hdr to target.
static void free_incoming_request(struct IncomingRequest *ir)
Release ir data structure.
#define MAX_INCOMING_REQUEST
For how many incoming connections do we try to create a virtual link for (at the same time!...
static void neighbour_dv_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Function called with the monotonic time of a DV initiator by PEERSTORE.
static struct GNUNET_PILS_Handle * pils
Service that manages our peer id.
void(* DVMessageHandler)(void *cls, struct Neighbour *next_hop, const struct GNUNET_MessageHeader *hdr, enum RouteMessageOptions options)
Function to call to further operate on the now DV encapsulated message hdr, forwarding it via next_ho...
static void decaps_dv_box_cb(void *cls, const struct GNUNET_ShortHashCode *km)
static char * get_address_without_port(const char *address)
Get the IP address without the port number.
ClientType
What type of client is the struct TransportClient about?
@ CT_APPLICATION
"Application" telling us where to connect (i.e.
@ CT_MONITOR
It is a monitor, forward monitor data.
@ CT_NONE
We do not know yet (client is fresh).
@ CT_CORE
Is the CORE service, we need to forward traffic to it.
@ CT_COMMUNICATOR
It is a communicator, use for communication.
static int validate_dv_initiator_signature(struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time, const struct GNUNET_PeerIdentity *init, const struct GNUNET_CRYPTO_ChallengeNonceP *challenge, const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
Check signature of type GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
static struct IncomingRequest * ir_head
List of incoming connections where we are trying to get a connection back established.
static void free_backtalker(struct Backtalker *b)
Free data structures associated with b.
static void hello_for_client_sync_cb(void *cls)
static void destroy_ack_cummulator(void *cls)
Clean up an idle cumulative acknowledgement data structure.
static void consider_sending_fc(void *cls)
Something changed on the virtual link with respect to flow control.
static unsigned int bsize
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
static struct GNUNET_TRANSPORT_PluginMonitor * pm
Handle if we are monitoring plugin session activity.
static struct GNUNET_Process * p
Helper process we started.
Definition gnunet-uri.c:38
static struct GNUNET_TIME_Relative duration
Option '-d': duration of the mapping.
Definition gnunet-vpn.c:90
struct GNUNET_PILS_Handle * GNUNET_PILS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_PILS_PidChangeCallback pid_change_cb, void *cls)
Connect to the PILS service.
Definition pils_api.c: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(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Generate a random unsigned 64-bit value.
void GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_encaps(const struct GNUNET_CRYPTO_EddsaPublicKey *pub, struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Encapsulate key material for a EdDSA public key.
#define GNUNET_CRYPTO_eddsa_verify(purp, ps, sig, pub)
Verify EdDSA signature.
void GNUNET_CRYPTO_zero_keys(void *buffer, size_t length)
Zero out buffer, securely against compiler optimizations.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
#define GNUNET_CONTAINER_MDLL_remove(mdll, head, tail, element)
Remove an element from a MDLL.
#define GNUNET_CONTAINER_MDLL_insert_tail(mdll, head, tail, element)
Insert an element at the tail of a MDLL.
#define GNUNET_CONTAINER_MDLL_insert_after(mdll, head, tail, other, element)
Insert an element into a MDLL after the given other element.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_MDLL_insert(mdll, head, tail, element)
Insert an element at the head of a MDLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:41
void GNUNET_CRYPTO_hmac(const struct GNUNET_CRYPTO_AuthKey *key, const void *plaintext, size_t plaintext_len, struct GNUNET_HashCode *hmac)
Calculate HMAC of a message (RFC 2104)
#define GNUNET_CRYPTO_hkdf_expand(result, out_len, prk,...)
HKDF-Expand using SHA256.
struct GNUNET_CONTAINER_MultiUuidmap * GNUNET_CONTAINER_multiuuidmap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL).
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
int GNUNET_CONTAINER_multihashmap32_get_multiple(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, GNUNET_CONTAINER_MultiHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map that match a particular key.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap32_put(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multipeermap_contains(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Check if the map contains any value under the given key (including values that are NULL).
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap32 * GNUNET_CONTAINER_multihashmap32_create(unsigned int len)
Create a 32-bit key multi hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap32_remove(struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
struct GNUNET_CONTAINER_MultiShortmap * GNUNET_CONTAINER_multishortmap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multishortmap_put(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multiuuidmap_remove(struct GNUNET_CONTAINER_MultiUuidmap *map, const struct GNUNET_Uuid *key, const void *value)
Remove the given key-value pair from the map.
void GNUNET_CONTAINER_multiuuidmap_destroy(struct GNUNET_CONTAINER_MultiUuidmap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
void GNUNET_CONTAINER_multishortmap_destroy(struct GNUNET_CONTAINER_MultiShortmap *map)
Destroy a hash map.
void GNUNET_CONTAINER_multihashmap32_destroy(struct GNUNET_CONTAINER_MultiHashMap32 *map)
Destroy a 32-bit key hash map.
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
unsigned int GNUNET_CONTAINER_multishortmap_size(const struct GNUNET_CONTAINER_MultiShortmap *map)
Get the number of key-value pairs in the map.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
int GNUNET_CONTAINER_multihashmap32_iterate(struct GNUNET_CONTAINER_MultiHashMap32 *map, GNUNET_CONTAINER_MultiHashMapIterator32Callback it, void *it_cls)
Iterate over all entries in the map.
int GNUNET_CONTAINER_multishortmap_remove(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multiuuidmap_iterate(struct GNUNET_CONTAINER_MultiUuidmap *map, GNUNET_CONTAINER_MultiUuidmapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multiuuidmap_put(struct GNUNET_CONTAINER_MultiUuidmap *map, const struct GNUNET_Uuid *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
void * GNUNET_CONTAINER_multiuuidmap_get(const struct GNUNET_CONTAINER_MultiUuidmap *map, const struct GNUNET_Uuid *key)
Given a key find a value in the map matching the key.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
void * GNUNET_CONTAINER_heap_peek(const struct GNUNET_CONTAINER_Heap *heap)
Get element stored at the root of heap.
void GNUNET_CONTAINER_heap_update_cost(struct GNUNET_CONTAINER_HeapNode *node, GNUNET_CONTAINER_HeapCostType new_cost)
Updates the cost of any node in the tree.
struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert(struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost)
Inserts a new element into the heap.
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
@ GNUNET_CONTAINER_HEAP_ORDER_MIN
Heap with the minimum cost at the root.
void GNUNET_HELLO_parser_free(struct GNUNET_HELLO_Parser *parser)
Release resources of a builder.
Definition hello-uri.c: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)
#define GNUNET_CRYPTO_kdf_arg_string(d)
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
GNUNET_SCHEDULER_Priority
Valid task priorities.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_CRYPTO_kdf_arg_auto(d)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
#define GNUNET_MIN(a, b)
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
#define GNUNET_PACKED
gcc-ism to get packed structs.
@ GNUNET_SCHEDULER_PRIORITY_BACKGROUND
Run as background job (higher than idle, lower than default).
@ GNUNET_SCHEDULER_PRIORITY_DEFAULT
Run with the default priority (normal P2P operations).
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
const char * GNUNET_uuid2s(const struct GNUNET_Uuid *uuid)
Convert a UUID to a string (for printing debug messages).
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
const char * GNUNET_sh2s(const struct GNUNET_ShortHashCode *shc)
Convert a short hash value to a string (for printing debug messages).
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
const char * GNUNET_i2s2(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_EXTRA_LOGGING
define GNUNET_EXTRA_LOGGING if using this header outside the GNUnet source tree where gnunet_config....
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition mq.c:305
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_check_zero_termination(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
#define GNUNET_MQ_check_boxed_message(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
GNUNET_MQ_PriorityPreferences
Per envelope preferences and priorities.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
enum GNUNET_GenericReturnValue GNUNET_MQ_handle_message(const struct GNUNET_MQ_MessageHandler *handlers, const struct GNUNET_MessageHeader *mh)
Call the message message handler that was registered for the type of the given message in the given h...
Definition mq.c:205
void GNUNET_MQ_notify_sent(struct GNUNET_MQ_Envelope *ev, GNUNET_SCHEDULER_TaskCallback cb, void *cb_cls)
Call a callback once the envelope has been sent, that is, sending it can not be canceled anymore.
Definition mq.c:655
const struct GNUNET_MessageHeader * GNUNET_MQ_env_get_msg(const struct GNUNET_MQ_Envelope *env)
Obtain message contained in envelope.
Definition mq.c:896
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
@ GNUNET_MQ_PRIO_BACKGROUND
Lowest priority, i.e.
@ GNUNET_MQ_PREF_UNRELIABLE
Flag to indicate that unreliable delivery is acceptable.
@ GNUNET_MQ_PREF_LOW_LATENCY
Flag to indicate that low latency is important.
void GNUNET_is_burst_ready(struct GNUNET_TIME_Relative rtt_average, struct GNUNET_BurstSync *burst_sync, GNUNET_SCHEDULER_TaskCallback task, struct GNUNET_StartBurstCls *task_cls)
Checks if we are ready and starts burst when we and the other peer is ready.
Definition nat.c:89
struct GNUNET_NAT_Handle * GNUNET_NAT_register(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on...
Definition nat_api.c:366
void GNUNET_NAT_unregister(struct GNUNET_NAT_Handle *nh)
Stop port redirection and public IP address detection for the given handle.
Definition nat_api.c:703
void GNUNET_NAT_add_global_address(struct GNUNET_NAT_Handle *nh, char *addr, unsigned int address_length)
Add global address to the list of addresses and notify clients.
Definition nat_api.c:460
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
void GNUNET_PEERSTORE_monitor_stop(struct GNUNET_PEERSTORE_Monitor *zm)
Stop monitoring.
struct GNUNET_PEERSTORE_IterateContext * GNUNET_PEERSTORE_iteration_start(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_PEERSTORE_Processor callback, void *callback_cls)
Iterate over peerstore entries.
void GNUNET_PEERSTORE_iteration_next(struct GNUNET_PEERSTORE_IterateContext *ic, uint64_t limit)
Continue an iteration.
void GNUNET_PEERSTORE_store_cancel(struct GNUNET_PEERSTORE_StoreContext *sc)
Cancel a store request.
#define GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME
Key used to store sender's monotonic time from backchannel messages.
void GNUNET_PEERSTORE_disconnect(struct GNUNET_PEERSTORE_Handle *h)
Disconnect from the PEERSTORE service.
#define GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY
Key used for storing addresses in URL format in the peerstore.
struct GNUNET_PEERSTORE_Monitor * GNUNET_PEERSTORE_monitor_start(const struct GNUNET_CONFIGURATION_Handle *cfg, int iterate_first, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_SCHEDULER_TaskCallback sync_cb, void *sync_cb_cls, GNUNET_PEERSTORE_Processor callback, void *callback_cls)
Request watching a given key The monitoring can be filtered to contain only records matching peer and...
#define GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME
Key used to store sender's monotonic time from DV learn messages.
struct GNUNET_PEERSTORE_Handle * GNUNET_PEERSTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the PEERSTORE service.
void GNUNET_PEERSTORE_monitor_next(struct GNUNET_PEERSTORE_Monitor *zm, uint64_t limit)
Calls the monitor processor specified in GNUNET_PEERSTORE_monitor_start for the next record(s).
struct GNUNET_PEERSTORE_StoreContext * GNUNET_PEERSTORE_store(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, const void *value, size_t size, struct GNUNET_TIME_Absolute expiry, enum GNUNET_PEERSTORE_StoreOption options, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Store a new entry in the PEERSTORE.
#define GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY
Key used for storing HELLOs in the peerstore.
void GNUNET_PEERSTORE_iteration_stop(struct GNUNET_PEERSTORE_IterateContext *ic)
Cancel an iteration.
#define GNUNET_PEERSTORE_HELLO_KEY
Key used for storing HELLO in the peerstore.
struct GNUNET_PEERSTORE_StoreHelloContext * GNUNET_PEERSTORE_hello_add(struct GNUNET_PEERSTORE_Handle *h, const struct GNUNET_MessageHeader *msg, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Add hello to peerstore.
@ GNUNET_PEERSTORE_STOREOPTION_MULTIPLE
Possibly store multiple values under given key.
@ GNUNET_PEERSTORE_STOREOPTION_REPLACE
Delete any previous values for the given key before storing the given value.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE
P2P message: transport requests confirmation that an address works.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK
transport acknowledges processing an incoming message
#define GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT
Message from TRANSPORT notifying about a client that connected to us.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN
inform transport that a queue was torn down
#define GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION
Type of the 'struct RequestHelloValidationMessage' send by clients to TRANSPORT to trigger validation...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_START
Message from the core saying that the transport server should start giving it messages.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA
Message sent to indicate to a monitor about events.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR
Message sent to indicate to the transport which address prefix is supported by a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RECV_OK
Message telling transport to limit its receive rate.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT
Type of a fragment of a CORE message created by transport to adjust message length to a queue's MTU.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL
Response from communicator: address bogus, will not try to create queue.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX
Source-routed transport message based DV information gathered.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX
Wrapper around non-fragmented CORE message used to measure RTT and ensure reliability.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST_CANCEL
Type of the 'struct ExpressPreferenceMessage' send by clients to TRANSPORT to abandon bandwidth prefe...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RECV
Message from TRANSPORT notifying about a message that was received.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION
Message type used between transport services when they internally forward communicator backchannel me...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE
transport tells communicator it wants a queue
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN
Message sent for topology discovery at transport level.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_BURST_FINISHED
Burst message we send to another peer for hole punching.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL
Tell transport that it should assist with exchanging a message between communicators.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT
Message from TRANSPORT notifying about a client that disconnected from us.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG
inform transport about an incoming message
#define GNUNET_MESSAGE_TYPE_TRANSPORT_START_BURST
Burst message we send to another peer for hole punching.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK
Response from communicator: will try to create queue.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING
Transport signalling incoming backchannel message to a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK
communicator tells transports that message was sent
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS
inform transport to add an address of this peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START
Message sent to indicate to the transport that a monitor wants to observe certain events.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS
inform transport to delete an address of this peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE
P2P message: transport proves that an address worked.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL
Transport signalling incoming backchannel message to a communicator.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG
transport tells communicator it wants to transmit
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND
Request to TRANSPORT to transmit a message.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK
Confirmation from TRANSPORT that message for transmission has been queued (and that the next message ...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK
Confirmation for a GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP
inform transport that a queue was setup to talk to some peer
#define GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST
Type of the 'struct ExpressPreferenceMessage' send by clients to TRANSPORT to establish bandwidth pre...
#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_UPDATE
inform transport that a queue was updated
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition scheduler.c:572
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_at(struct GNUNET_TIME_Absolute at, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run at the specified time.
Definition scheduler.c:1260
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition scheduler.c:1345
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1310
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1283
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1213
#define GNUNET_SERVICE_MAIN(pd, service_name, service_options, init_cb, connect_cb, disconnect_cb, cls,...)
Creates the "main" function for a GNUnet service.
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the 'monitor' flag on this client.
Definition service.c: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:1623
struct GNUNET_TIME_Relative GNUNET_TIME_relative_min(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the minimum of two relative time values.
Definition time.c:344
const char * GNUNET_TIME_relative2s(struct GNUNET_TIME_Relative delta, bool do_round)
Give relative time in human-readable fancy format.
Definition time.c:264
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_TIME_Relative GNUNET_TIME_relative_ntoh(struct GNUNET_TIME_RelativeNBO a)
Convert relative time from network byte order.
Definition time.c:626
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition time.c:438
#define GNUNET_TIME_relative_cmp(t1, op, t2)
Compare two relative times.
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition time.c:406
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_max(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the maximum of two absolute time values.
Definition time.c:368
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition strings.c:604
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
struct GNUNET_TIME_Relative GNUNET_TIME_randomized_backoff(struct GNUNET_TIME_Relative rt, struct GNUNET_TIME_Relative threshold)
Randomized exponential back-off, starting at 1 ms and going up by a factor of 2+r,...
Definition time.c:830
struct GNUNET_TIME_Relative GNUNET_TIME_relative_subtract(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Subtract relative timestamp from the other.
Definition time.c:601
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition time.c:111
#define GNUNET_TIME_UNIT_MINUTES
One minute.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply_double(struct GNUNET_TIME_Relative rel, double factor)
Multiply relative time by a given factor.
Definition time.c:506
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition time.c:737
struct GNUNET_TIME_Relative GNUNET_TIME_relative_add(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Add relative times together.
Definition time.c:583
struct GNUNET_TIME_Relative GNUNET_TIME_randomize(struct GNUNET_TIME_Relative r)
Return a random time value between 0.5*r and 1.5*r.
Definition time.c:851
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_subtract(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Subtract a given relative duration from the given start time.
Definition time.c:471
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition time.c:316
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition time.c:486
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_min(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the minimum of two absolute time values.
Definition time.c:360
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
struct GNUNET_TIME_RelativeNBO GNUNET_TIME_relative_hton(struct GNUNET_TIME_Relative a)
Convert relative time to network byte order.
Definition time.c:616
#define GNUNET_TIME_absolute_cmp(t1, op, t2)
Compare two absolute times.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Add a given relative duration to the given start time.
Definition time.c:452
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get_monotonic(const struct GNUNET_CONFIGURATION_Handle *cfg)
Obtain the current time and make sure it is monotonically increasing.
Definition time.c:860
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition time.c:548
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_difference(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end)
Compute the time difference between the given start and end times.
Definition time.c:423
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition time.c:636
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition strings.c:665
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
static unsigned int size
Size of the "table".
Definition peer.c:68
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition scheduler.c:436
void receiver(void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode)
Callback to read from the SOCKS5 proxy.
Definition socks.c:330
static struct GNUNET_TIME_Relative delta
Definition speedup.c:36
Data structure in which we track acknowledgements still to be sent to the.
struct GNUNET_SCHEDULER_Task * task
Task scheduled either to transmit the cumulative ACK message, or to clean up this data structure afte...
struct GNUNET_TIME_Absolute min_transmission_time
When is task run (only used if num_acks is non-zero)?
struct TransportCummulativeAckPayload ack_uuids[64]
ACK data being accumulated.
struct GNUNET_PeerIdentity target
Target peer for which we are accumulating ACKs here.
unsigned int num_acks
Number of entries used in ack_uuids.
uint32_t ack_counter
Counter to produce the ack_counter in the struct TransportReliabilityAckMessage.
Unique identifier to map an acknowledgement to a transmission.
struct GNUNET_Uuid value
The UUID value.
One of the addresses of this peer.
struct GNUNET_TIME_Relative expiration
What is a typical lifetime the communicator expects this address to have? (Always from now....
uint32_t aid
Address identifier used by the communicator.
size_t signed_address_len
Signed address length.
enum GNUNET_NetworkType nt
Network type offered by this address.
struct AddressListEntry * prev
Kept in a DLL.
struct TransportClient * tc
Which communicator provides this address?
struct AddressListEntry * next
Kept in a DLL.
struct GNUNET_PEERSTORE_StoreHelloContext * shc
Store hello handle.
void * signed_address
Signed address.
const char * address
The actual address.
struct GNUNET_SCHEDULER_Task * st
Task to periodically do st operation.
struct GNUNET_PEERSTORE_StoreContext * sc
Current context for storing this address in the peerstore.
A Backtalker is a peer sending us backchannel messages.
struct GNUNET_TIME_Absolute timeout
When will this entry time out?
struct CommunicatorMessageContext * cmc
Communicator context waiting on this backchannel's get, or NULL.
struct GNUNET_CRYPTO_HpkeEncapsulation last_ephemeral
Last (valid) ephemeral key received from this sender.
struct GNUNET_PEERSTORE_StoreContext * sc
Handle to a PEERSTORE store operation for this pid's monotonic_time.
struct GNUNET_SCHEDULER_Task * task
Task associated with this backtalker.
size_t body_size
Number of bytes of the original message body that follows after this struct.
struct GNUNET_TIME_Absolute monotonic_time
Last (valid) monotonic time received from this sender.
struct GNUNET_PEERSTORE_IterateContext * get
Handle for an operation to fetch monotonic_time information from the PEERSTORE, or NULL.
struct GNUNET_PeerIdentity pid
Peer this is about.
Closure for check_known_address.
struct ValidationState * vs
Set to a matching validation state, if one was found.
const char * address
Set to the address we are looking for.
Closure for check_known_challenge.
struct ValidationState * vs
Set to a matching validation state, if one was found.
const struct GNUNET_CRYPTO_ChallengeNonceP * challenge
Set to the challenge we are looking for.
Context from handle_incoming_msg().
struct CommunicatorMessageContext * next
Kept in a DLL of struct VirtualLink if waiting for CORE flow control to unchoke.
uint16_t total_hops
Number of hops the message has travelled (if DV-routed).
struct GNUNET_TRANSPORT_IncomingMessage im
Additional information for flow control and about the sender.
unsigned int continue_send
Did we already call GNUNET_SERVICE_client_continue and send ACK to communicator?
const struct GNUNET_MessageHeader * mh
The message to demultiplex.
struct CommunicatorMessageContext * prev
Kept in a DLL of struct VirtualLink if waiting for CORE flow control to unchoke.
struct TransportClient * tc
Which communicator provided us with the message.
Message from the transport service to the library informing about neighbors.
Definition transport.h:89
struct GNUNET_PeerIdentity id
Identity of the new neighbour.
Definition transport.h:112
Closure for core_env_sent_cb.
uint16_t isize
By how much should we increment vl's incoming_fc_window_size_used once we are done sending to CORE?...
struct CoreSentContext * next
Kept in a DLL to clear vl in case vl is lost.
struct VirtualLink * vl
Virtual link this is about.
struct CoreSentContext * prev
Kept in a DLL to clear vl in case vl is lost.
uint16_t size
How big was the message.
Structure of the key material used to encrypt backchannel messages.
struct GNUNET_CRYPTO_AuthKey hmac_key
Key used for HMAC calculations (via GNUNET_CRYPTO_hmac()).
gcry_cipher_hd_t cipher
State of our block cipher.
char aes_key[256/8]
Symmetric key to use for encryption.
char aes_ctr[128/8]
Counter value to use during setup.
struct DVKeyState::@73 material
Actual key material.
An entry describing a peer on a path in a struct TransportDVLearnMessage message.
struct GNUNET_CRYPTO_EddsaSignature hop_sig
Signature of this hop over the path, of purpose GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP.
struct GNUNET_PeerIdentity hop
Identity of a peer on the path.
const struct TransportDVBoxMessage * dvb
struct PilsRequest * pr
struct CommunicatorMessageContext * cmc
Message from the transport service to the library informing about disconnects.
Definition transport.h:121
One possible hop towards a DV target.
struct PerformanceData pd
Performance data for this transmission possibility.
struct PendingAcknowledgement * pa_head
Head of DLL of PAs that used our path.
unsigned int distance
Number of hops in total to the target (excluding next_hop and target itself).
struct DistanceVectorHop * next_neighbour
Kept in a MDLL.
struct Neighbour * next_hop
What would be the next hop to target?
struct GNUNET_TIME_Absolute timeout
At what time do we forget about this path unless we see it again while learning?
struct DistanceVector * dv
Distance vector entry this hop belongs with.
const struct GNUNET_PeerIdentity * path
Array of distance hops to the target, excluding next_hop.
struct DistanceVectorHop * next_dv
Kept in a MDLL, sorted by timeout.
struct GNUNET_TIME_Absolute path_valid_until
For how long is the validation of this path considered valid? Set to ZERO if the path is learned by s...
struct DistanceVectorHop * prev_dv
Kept in a MDLL, sorted by timeout.
struct DistanceVectorHop * prev_neighbour
Kept in a MDLL.
struct PendingAcknowledgement * pa_tail
Tail of DLL of PAs that used our path.
Entry in our dv_routes table, representing a (set of) distance vector routes to a particular peer.
struct DistanceVectorHop * dv_head
Known paths to target.
struct VirtualLink * vl
Do we have a confirmed working queue and are thus visible to CORE? If so, this is the virtual link,...
struct GNUNET_TIME_Absolute monotime
What time was sender_sig created.
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Signature affirming ephemeral_key of type GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct DistanceVectorHop * dv_tail
Known paths to target.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Our ephemeral key.
struct GNUNET_ShortHashCode * km
Master secret for the setup of the Key material for the backchannel.
struct GNUNET_PeerIdentity target
To which peer is this a route?
struct GNUNET_TIME_Absolute ephemeral_validity
How long is sender_sig valid.
struct GNUNET_SCHEDULER_Task * timeout_task
Task scheduled to purge expired paths from dv_head MDLL.
Content signed by each peer during DV learning.
struct GNUNET_PeerIdentity pred
Identity of the previous peer on the path.
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
struct GNUNET_PeerIdentity succ
Identity of the next peer on the path.
Content signed by the initiator during DV learning.
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Time at the initiator when generating the signature.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
Body by which a peer confirms that it is using an ephemeral key.
struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time
How long is this signature over the ephemeral key valid?
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct GNUNET_PeerIdentity target
Target's peer identity.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Ephemeral key setup by the sender for target, used to encrypt the payload.
Application client to TRANSPORT service: we would like to have address suggestions for this peer.
Definition transport.h:807
Closure for find_by_message_uuid.
struct ReassemblyContext * rc
Set to the reassembly context if found.
struct MessageUUIDP message_uuid
UUID to look for.
32-bit bandwidth used for network exchange by GNUnet, in bytes per second.
Wrapper struct with the average RTT of message to some peer and if this peer und us is ready to sync.
Handle to a node in a heap.
Internal representation of the hash map.
Internal representation of the hash map.
Internal representation of the hash map.
Internal representation of the hash map.
Internal representation of the hash map.
type for (message) authentication keys
Type of a nonce used for challenges.
struct GNUNET_ShortHashCode value
The value of the nonce.
an ECC signature using EdDSA.
HPKE DHKEM encapsulation (X25519) See RFC 9180.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
Context for building (or parsing) HELLO URIs.
Definition hello-uri.c: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_HashCode hmac
HMAC over the ciphertext of the encrypted, variable-size body that follows.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX.
uint16_t num_hops
Number of hops this messages includes.
uint16_t orig_size
Size this msg had initially.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_key
Ephemeral key setup by the sender for target, used to encrypt the payload.
unsigned int without_fc
Flag if the payload is a control message.
struct GNUNET_ShortHashCode iv
We use an IV here as the ephemeral_key is reused for EPHEMERAL_VALIDITY time to avoid re-signing it a...
uint16_t total_hops
Number of total hops this messages travelled.
Plaintext of the variable-size payload that is encrypted within a struct TransportBackchannelEncapsul...
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Signature of the sender over an GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Current monotonic time of the sending transport service.
struct GNUNET_PeerIdentity sender
Sender's peer identity.
Internal message used by transport for distance vector learning.
struct GNUNET_PeerIdentity initiator
Identity of the peer that started this learning activity.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used by the initiator to re-identify the path.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN.
struct GNUNET_TIME_RelativeNBO non_network_delay
Peers receiving this message and delaying forwarding to other peers for any reason should increment t...
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Time at the initiator when generating the signature.
struct GNUNET_CRYPTO_EddsaSignature init_sig
Signature of this hop over the path, of purpose GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR.
uint16_t num_hops
Number of hops this messages has travelled, in NBO.
uint16_t bidirectional
Bitmask of the last 16 hops indicating whether they are confirmed available (without DV) in both dire...
Message for Transport-to-Transport Flow control.
uint64_t outbound_window_size
Latest flow control window size we learned from the other peer, in bytes, in NBO.
unsigned int number_of_addresses
Number of TransportGlobalNattedAddress following the struct.
size_t size_of_addresses
Size of all the addresses attached to all TransportGlobalNattedAddress.
uint64_t inbound_window_size
Flow control window size in bytes, in NBO.
struct GNUNET_TIME_AbsoluteNBO sender_time
Timestamp of the sender.
uint32_t seq
Sequence number of the flow control message.
uint64_t outbound_sent
How many bytes has the sender sent that count for flow control at this time.
struct GNUNET_TIME_RelativeNBO rtt
Average RTT for the DistanceVector of the VirtualLink we tell the target.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL.
unsigned int sync_ready
We tell the target, if we are ready to start the burst.
Outer layer of an encapsulated fragmented application message.
uint16_t frag_off
Offset of this fragment in the overall message.
struct MessageUUIDP msg_uuid
Original message ID for of the message that all the fragments belong to.
struct AcknowledgementUUIDP ack_uuid
Unique ID of this fragment (and fragment transmission!).
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT.
uint16_t msg_size
Total size of the message that is being fragmented.
struct TransportGlobalNattedAddress * tgna
The struct TransportGlobalNattedAddress to set.
unsigned int address_length
Length of the address following the struct in NBO.
Confirmation that the receiver got a GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX.
uint32_t ack_counter
Counter of ACKs transmitted by the sender to us.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK.
Outer layer of an encapsulated unfragmented application message sent over an unreliable channel.
uint32_t ack_countdown
Number of messages still to be sent before a commulative ACK is requested.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX.
struct AcknowledgementUUIDP ack_uuid
Unique ID of the message used for signalling receipt of messages sent over possibly unreliable channe...
Message send to another peer to validate that it can indeed receive messages at a particular address.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge to be signed by the receiving peer.
struct GNUNET_TIME_AbsoluteNBO sender_time
Timestamp of the sender, to be copied into the reply to allow sender to calculate RTT.
Message signed by a peer to confirm that it can indeed receive messages at a particular address.
struct GNUNET_TIME_RelativeNBO validity_duration
How long does the sender believe the address on which the challenge was received to remain valid?
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose is GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge signed by the receiving peer.
Message send to a peer to respond to a #GNUNET_MESSAGE_TYPE_ADDRESS_VALIDATION_CHALLENGE.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
The challenge that was signed by the receiving peer.
struct GNUNET_CRYPTO_EddsaSignature signature
The peer's signature matching the GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE purpose.
struct GNUNET_PEERSTORE_StoreHelloContext * sc
State we keep for validation activities.
struct GNUNET_TIME_Absolute valid_until
How long did the peer claim this address to be valid? Capped at minimum of MAX_ADDRESS_VALID_UNTIL re...
struct GNUNET_PeerIdentity pid
For which peer is address to be validated (or possibly valid)? Serves as key in the validation_map.
struct GNUNET_TIME_Absolute validated_until
How long do we consider this address to be valid? In the past or zero if we have not yet validated it...

◆ DELAY_WARN_THRESHOLD

#define DELAY_WARN_THRESHOLD    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)

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

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

Definition at line 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 5222 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 11457 of file gnunet-service-transport.c.

11458{
11459 struct Queue *queue = cls;
11460 struct Neighbour *n = queue->neighbour;
11462 struct PendingMessage *pm;
11463
11464 queue->transmit_task = NULL;
11465 if (NULL == n->vl)
11466 {
11468 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
11469 GNUNET_i2s (&n->pid),
11470 queue->address);
11471 queue->idle = GNUNET_YES;
11472 return;
11473 }
11474 memset (&sc, 0, sizeof(sc));
11475 select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
11476 if (NULL == sc.best)
11477 {
11478 /* Also look at DVH that have the n as first hop! */
11479 for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
11480 dvh = dvh->next_neighbour)
11481 {
11483 queue,
11484 dvh->dv->vl,
11485 dvh,
11486 sizeof(struct GNUNET_PeerIdentity)
11487 * (1 + dvh->distance)
11488 + sizeof(struct TransportDVBoxMessage)
11489 + sizeof(struct TransportDVBoxPayloadP));
11490 }
11491 }
11492 if (NULL == sc.best)
11493 {
11494 /* no message pending, nothing to do here! */
11496 "No pending messages, queue `%s' to %s now idle\n",
11497 queue->address,
11498 GNUNET_i2s (&n->pid));
11499 if (GNUNET_YES == sc.to_early)
11500 schedule_transmit_on_queue (sc.to_early_retry_delay,
11501 queue,
11503 queue->idle = GNUNET_YES;
11504 return;
11505 }
11506 /* There is a message pending, we are certainly not idle */
11507 queue->idle = GNUNET_NO;
11508
11509 /* Given selection in `sc`, do transmission */
11510 pm = sc.best;
11512 "Selected message <%" PRIu64 ">\n",
11513 pm->logging_uuid);
11514 if (NULL != sc.dvh)
11515 {
11517 "Is this %u a DV box?\n",
11518 pm->pmt);
11519 GNUNET_assert (PMT_DV_BOX != pm->pmt);
11520 if ((NULL != sc.best->bpm) && (sc.best->bpm->used_dvh != sc.dvh))
11521 {
11523 "Discard old box, because we have a new DV path.\n");
11524 free_pending_message (sc.best->bpm);
11525 sc.best->bpm = NULL;
11526 }
11527
11528 if (NULL == sc.best->bpm)
11529 {
11531 "encapsulate_for_dv 2\n");
11532 encapsulate_for_dv (sc.dvh->dv,
11533 1,
11534 &sc.dvh,
11535 (const struct GNUNET_MessageHeader *) &sc.best[1],
11537 &sc,
11538 RMO_NONE,
11539 GNUNET_NO);
11540 GNUNET_assert (NULL != sc.best->bpm);
11542 "%lu %lu %lu %lu %u\n",
11543 sizeof(struct GNUNET_PeerIdentity),
11544 sizeof(struct TransportDVBoxMessage),
11545 sizeof(struct TransportDVBoxPayloadP),
11546 sizeof(struct TransportFragmentBoxMessage),
11547 ((const struct GNUNET_MessageHeader *) &sc.best[1])->size);
11548 sc.best->bpm->used_dvh = sc.dvh;
11549 }
11550 pm = sc.best->bpm;
11551 }
11552 if (GNUNET_YES == sc.frag)
11553 {
11554 pm = fragment_message (queue, sc.dvh, pm);
11555 if (NULL == pm)
11556 {
11558 "Fragmentation failed queue %s to %s for <%" PRIu64
11559 ">, trying again\n",
11560 queue->address,
11561 GNUNET_i2s (&n->pid),
11562 sc.best->logging_uuid);
11564 queue,
11566 return;
11567 }
11568 }
11569 else if (GNUNET_YES == sc.relb)
11570 {
11572 if (NULL == pm)
11573 {
11574 /* Reliability boxing failed, try next message... */
11575 GNUNET_log (
11577 "Reliability boxing failed queue %s to %s for <%" PRIu64
11578 ">, trying again\n",
11579 queue->address,
11580 GNUNET_i2s (&n->pid),
11581 sc.best->logging_uuid);
11583 queue,
11585 return;
11586 }
11587 }
11588
11589 /* Pass 'pm' for transission to the communicator */
11590 GNUNET_log (
11592 "Passing message <%" PRIu64
11593 "> to queue %s for peer %s (considered %u others)\n",
11594 pm->logging_uuid,
11595 queue->address,
11596 GNUNET_i2s (&n->pid),
11597 sc.consideration_counter);
11598
11599 /* Flow control: increment amount of traffic sent; if we are routing
11600 via DV (and thus the ultimate target of the pending message is for
11601 a different virtual link than the one of the queue), then we need
11602 to use up not only the window of the direct link but also the
11603 flow control window for the DV link! */
11604 pm->vl->outbound_fc_window_size_used += pm->bytes_msg;
11605
11606 if (pm->vl != queue->neighbour->vl)
11607 {
11608 /* If the virtual link of the queue differs, this better be distance
11609 vector routing! */
11610 GNUNET_assert (NULL != sc.dvh);
11611 /* If we do distance vector routing, we better not do this for a
11612 message that was itself DV-routed */
11613 GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
11614 /* We use the size of the unboxed message here, to avoid counting
11615 the DV-Box header which is eaten up on the way by intermediaries */
11616 queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
11617 }
11618 else
11619 {
11620 GNUNET_assert (NULL == sc.dvh);
11621 }
11622
11623 queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
11624
11625 /* Check if this transmission somehow conclusively finished handing 'pm'
11626 even without any explicit ACKs */
11627 if ((PMT_CORE == pm->pmt) ||
11628 (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
11629 {
11631 }
11632 else
11633 {
11634 struct GNUNET_TIME_Relative wait_duration;
11635 unsigned int wait_multiplier;
11636
11637 if (PMT_FRAGMENT_BOX == pm->pmt)
11638 {
11639 struct PendingMessage *root;
11640
11641 root = pm->frag_parent;
11642 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11643 root = root->frag_parent;
11644
11645 wait_multiplier = (unsigned int) ceil ((double) root->bytes_msg
11646 / ((double) root->frag_off
11647 / (double) root->frag_count))
11648 * 4;
11649 }
11650 else
11651 {
11652 // No fragments, we use 4 RTT before retransmitting.
11653 wait_multiplier = 4;
11654 }
11655
11656 // Depending on how much pending message the VirtualLink is queueing, we wait longer.
11657 // wait_multiplier = wait_multiplier * pm->vl->pending_msg_num;
11658
11660 "Wait multiplier %u\n",
11661 wait_multiplier);
11662
11663 /* Message not finished, waiting for acknowledgement.
11664 Update time by which we might retransmit 's' based on queue
11665 characteristics (i.e. RTT); it takes one RTT for the message to
11666 arrive and the ACK to come back in the best case; but the other
11667 side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
11668 retransmitting.
11669
11670 OPTIMIZE: Note that in the future this heuristic should likely
11671 be improved further (measure RTT stability, consider message
11672 urgency and size when delaying ACKs, etc.) */
11673
11674 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
11675 queue->pd.aged_rtt.rel_value_us)
11676 wait_duration = queue->pd.aged_rtt;
11677 else
11678 {
11679 wait_duration = DEFAULT_ACK_WAIT_DURATION;
11680 wait_multiplier = 4;
11681 }
11682 {
11685 wait_duration, wait_multiplier));
11687 wait_duration, wait_multiplier);
11689 "Waiting %s for ACK until %s\n",
11694 GNUNET_TIME_relative_multiply (wait_duration,
11695 wait_multiplier))
11696 );
11697 }
11698 }
11699 /* finally, re-schedule queue transmission task itself */
11701 queue,
11703}

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

13445{
13446 struct LearnLaunchEntry *lle;
13447 struct PilsRequest *pr;
13448 (void) cls;
13449
13451 "shutdown logic\n");
13454 &free_neighbour_cb, NULL);
13455 if (NULL != validation_task)
13456 {
13458 validation_task = NULL;
13459 }
13460 if (NULL != dvlearn_task)
13461 {
13463 dvlearn_task = NULL;
13464 }
13465 if (NULL != burst_task)
13466 {
13468 burst_task = NULL;
13469 }
13470 if (NULL != burst_timeout_task)
13471 {
13473 burst_timeout_task = NULL;
13474 }
13477 dvlearn_map = NULL;
13480 dv_routes = NULL;
13481 if (NULL != GST_stats)
13482 {
13484 GST_stats = NULL;
13485 }
13486 if (NULL != GST_my_hello)
13487 {
13489 GST_my_hello = NULL;
13490 }
13493 NULL);
13495 ack_cummulators = NULL;
13498 NULL);
13500 pending_acks = NULL;
13503 neighbours = NULL;
13506 links = NULL;
13509 NULL);
13511 backtalkers = NULL;
13514 NULL);
13516 validation_map = NULL;
13518 validation_heap = NULL;
13520 revalidation_map = NULL;
13521 while (NULL != ir_head)
13523 GNUNET_assert (0 == ir_total);
13524 while (NULL != (lle = lle_head))
13525 {
13527 GNUNET_free (lle);
13528 }
13529 while (NULL != (pr = pils_requests_head))
13530 {
13533 pr);
13534 if (NULL != pr->op)
13535 GNUNET_PILS_cancel (pr->op);
13536 GNUNET_free (pr);
13537 }
13538 if (NULL != pils_feed_task)
13539 {
13541 pils_feed_task = NULL;
13542 }
13543 if (NULL != pils)
13544 {
13546 pils = NULL;
13547 }
13548 if (NULL != peerstore)
13549 {
13551 "Disconnecting from PEERSTORE service\n");
13553 peerstore = NULL;
13554 }
13556}

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] =
4508 ok = GNUNET_YES;
4509 for (unsigned int j = 0; j < i; j++)
4510 if (choices[i] == choices[j])
4511 {
4512 ok = GNUNET_NO;
4513 break;
4514 }
4515 }
4516 }
4517 dv_count = 0;
4518 num_dv = 0;
4519 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4520 pos = pos->next_dv)
4521 {
4522 uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance;
4523
4524 if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
4525 (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
4526 .rel_value_us == 0))
4527 continue; /* pos unconfirmed and confirmed required */
4528 for (unsigned int i = 0; i < hops_array_length; i++)
4529 if ((num_dv <= choices[i]) && (num_dv + delta > choices[i]))
4530 hops_array[dv_count++] = pos;
4531 num_dv += delta;
4532 }
4533 return dv_count;
4534}

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

Referenced by route_control_message_without_fc().

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

◆ check_communicator_available()

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

Communicator started.

Test message is well-formed.

Parameters
clsthe client
camthe send message that was sent

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

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

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

◆ finish_cmc_handling()

static void finish_cmc_handling ( struct CommunicatorMessageContext cmc)
static

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

References finish_cmc_handling_with_continue(), and GNUNET_YES.

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

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

◆ handle_client_recv_ok()

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

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

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

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

Parameters
clsthe client
romthe message that was sent

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

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

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

Here is the call graph for this function:

◆ handle_communicator_available()

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

Communicator started.

Process the request.

Parameters
clsthe client
camthe send message that was sent

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

4668{
4669 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 11746 of file gnunet-service-transport.c.

11748{
11749 struct PendingMessage *pm;
11750
11751 GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
11752 qe->queue->queue_tail,
11753 qe);
11754 qe->queue->queue_length--;
11755 tc->details.communicator.total_queue_length--;
11757 "Received ACK on queue %s (QID %u) to peer %s (new length: %u/%u)\n",
11758 qe->queue->address,
11759 qe->queue->qid,
11760 GNUNET_i2s (&qe->queue->neighbour->pid),
11761 qe->queue->queue_length,
11762 tc->details.communicator.total_queue_length);
11763
11764 /* if applicable, resume transmissions that waited on ACK */
11766 tc->details.communicator.total_queue_length)
11767 {
11768 /* Communicator dropped below threshold, resume all queues
11769 incident with this client! */
11771 GST_stats,
11772 "# Transmission throttled due to communicator queue limit",
11773 -1,
11774 GNUNET_NO);
11775 for (struct Queue *queue = tc->details.communicator.queue_head;
11776 NULL != queue;
11777 queue = queue->next_client)
11778 {
11780 queue,
11782 }
11783 }
11784 else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
11785 {
11786 /* queue dropped below threshold; only resume this one queue */
11788 "# Transmission throttled due to queue queue limit",
11789 -1,
11790 GNUNET_NO);
11792 qe->queue,
11794 }
11795 else if (1 == qe->queue->q_capacity)
11796 {
11797 // TODO I guess this will never happen, because the communicator triggers this by updating its queue length itself.
11799 "Transmission rescheduled due to communicator message queue with qid %u has capacity %"
11800 PRIu64 ".\n",
11801 qe->queue->qid,
11802 qe->queue->q_capacity);
11803 /* message queue has capacity; only resume this one queue */
11804 /* queue dropped below threshold; only resume this one queue */
11806 "# Transmission throttled due to message queue capacity",
11807 -1,
11808 GNUNET_NO);
11810 qe->queue,
11812 }
11813
11814 if (NULL != (pm = qe->pm))
11815 {
11816 struct VirtualLink *vl;
11817
11818 // GNUNET_assert (qe == pm->qe);
11819 pm->qe = NULL;
11820 /* If waiting for this communicator may have blocked transmission
11821 of pm on other queues for this neighbour, force schedule
11822 transmit on queue for queues of the neighbour */
11823 if (NULL == pm->frag_parent)
11824 {
11825 vl = pm->vl;
11826 if ((NULL != vl) &&
11827 (NULL != vl->pending_msg_head) &&
11828 (vl->pending_msg_head == pm))
11830 }
11831 }
11832 GNUNET_free (qe);
11833}

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
5038 if (0 == (options & RMO_REDUNDANT))
5039 sel2 = candidates; /* picks none! */
5040 else
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_QUALITY_WEAK, GNUNET_CRYPTO_random_u32(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_min(), GNUNET_TIME_UNIT_FOREVER_REL, GST_stats, options, queue_send_msg(), RMO_REDUNDANT, RMO_UNCONFIRMED_ALLOWED, GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

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

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

◆ dv_setup_key_state_from_km()

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

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

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

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

5112{
5113 /* must match what we defive from decapsulated key */
5116 &key->material,
5117 sizeof(key->material),
5118 km,
5119 GNUNET_CRYPTO_kdf_arg_string ("gnunet-transport-dv-key"),
5123 "Deriving backchannel key based on KM %s and IV %s\n",
5124 GNUNET_sh2s (km),
5125 GNUNET_sh2s (iv));
5126 GNUNET_assert (0 == gcry_cipher_open (&key->cipher,
5127 GCRY_CIPHER_AES256 /* low level: go for speed */
5128 ,
5129 GCRY_CIPHER_MODE_CTR,
5130 0 /* flags */));
5131 GNUNET_assert (0 == gcry_cipher_setkey (key->cipher,
5132 &key->material.aes_key,
5133 sizeof(key->material.aes_key)));
5134 gcry_cipher_setctr (key->cipher,
5135 &key->material.aes_ctr,
5136 sizeof(key->material.aes_ctr));
5137}

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

Referenced by decaps_dv_box_cb(), and encapsulate_for_dv().

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

◆ dv_hmac()

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

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

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

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

5154{
5155 GNUNET_CRYPTO_hmac (&key->material.hmac_key, data, data_size, hmac);
5156}

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

Referenced by decaps_dv_box_cb(), and encapsulate_for_dv().

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

◆ dv_encrypt()

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

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

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

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

5170{
5171 GNUNET_assert (0 ==
5172 gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size));
5173}

References GNUNET_assert, and key.

Referenced by encapsulate_for_dv().

Here is the caller graph for this function:

◆ dv_decrypt()

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

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

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

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

5191{
5192 return (0 ==
5193 gcry_cipher_decrypt (key->cipher,
5194 out, out_size,
5195 ciph, out_size)) ? GNUNET_OK : GNUNET_SYSERR;
5196}

References GNUNET_OK, GNUNET_SYSERR, and key.

Referenced by decaps_dv_box_cb().

Here is the caller graph for this function:

◆ dv_key_clean()

static void dv_key_clean ( struct DVKeyState key)
static

Clean up key material in key.

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

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

5206{
5207 gcry_cipher_close (key->cipher);
5208 GNUNET_CRYPTO_zero_keys (&key->material, sizeof(key->material));
5209}

References GNUNET_CRYPTO_zero_keys(), and key.

Referenced by decaps_dv_box_cb(), and encapsulate_for_dv().

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

◆ encapsulate_for_dv()

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

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

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

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

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

References PerformanceData::aged_rtt, DistanceVectorHop::distance, dv_encrypt(), dv_hmac(), dv_key_clean(), dv_setup_key_state_from_km(), enc, TransportDVBoxMessage::ephemeral_key, GNUNET_ALIGN, GNUNET_asprintf(), GNUNET_assert, GNUNET_CRYPTO_eddsa_kem_encaps(), GNUNET_CRYPTO_QUALITY_NONCE, GNUNET_CRYPTO_random_block(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_EXTRA_LOGGING, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX, GNUNET_new, GNUNET_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::hmac, TransportDVBoxMessage::iv, key, 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 5364 of file gnunet-service-transport.c.

5368{
5369 (void) cls;
5370 (void) route_via_neighbour (next_hop, hdr, RMO_UNCONFIRMED_ALLOWED);
5371}

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

5390{
5391 // struct VirtualLink *vl;
5392 struct Neighbour *n;
5393 struct DistanceVector *dv;
5394 struct GNUNET_TIME_Relative rtt1;
5395 struct GNUNET_TIME_Relative rtt2;
5396 const struct GNUNET_PeerIdentity *target = &vl->target;
5397
5399 "Trying to route message of type %u to %s without fc\n",
5400 ntohs (hdr->type),
5401 GNUNET_i2s (target));
5402
5403 // TODO Do this elsewhere. vl should be given as parameter to method.
5404 // vl = lookup_virtual_link (target);
5405 GNUNET_assert (NULL != vl && GNUNET_YES == vl->confirmed);
5406 if (NULL == vl)
5408 n = vl->n;
5409 dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
5410 if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
5411 {
5412 /* if confirmed is required, and we do not have anything
5413 confirmed, drop respective options */
5414 if (NULL == n)
5415 n = lookup_neighbour (target);
5416 if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
5418 }
5419 if ((NULL == n) && (NULL == dv))
5420 {
5422 "Cannot route message of type %u to %s: no route\n",
5423 ntohs (hdr->type),
5424 GNUNET_i2s (target));
5426 "# Messages dropped in routing: no acceptable method",
5427 1,
5428 GNUNET_NO);
5430 }
5432 "Routing message of type %u to %s with options %X\n",
5433 ntohs (hdr->type),
5434 GNUNET_i2s (target),
5435 (unsigned int) options);
5436 /* If both dv and n are possible and we must choose:
5437 flip a coin for the choice between the two; for now 50/50 */
5438 if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
5439 {
5441 n = NULL;
5442 else
5443 dv = NULL;
5444 }
5445 if ((NULL != n) && (NULL != dv))
5446 options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
5447 enough for redundancy, so clear the flag. */
5450 if (NULL != n)
5451 {
5453 "Try to route message of type %u to %s without fc via neighbour\n",
5454 ntohs (hdr->type),
5455 GNUNET_i2s (target));
5456 rtt1 = route_via_neighbour (n, hdr, options);
5457 }
5458 if (NULL != dv)
5459 {
5460 struct DistanceVectorHop *hops[2];
5461 unsigned int res;
5462
5464 options,
5465 hops,
5466 (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
5467 if (0 == res)
5468 {
5470 "Failed to route message, could not determine DV path\n");
5471 return rtt1;
5472 }
5474 "encapsulate_for_dv 1\n");
5475 rtt2 = encapsulate_for_dv (dv,
5476 res,
5477 hops,
5478 hdr,
5480 NULL,
5482 GNUNET_YES);
5483 }
5484 return GNUNET_TIME_relative_min (rtt1, rtt2);
5485}

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

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

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

◆ consider_sending_fc()

static void consider_sending_fc ( void *  cls)
static

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

Consider retransmitting the FC window size.

Parameters
clsa struct VirtualLink to work with

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

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

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

5499{
5500 struct VirtualLink *vl = cls;
5501 vl->fc_retransmit_task = NULL;
5502 consider_sending_fc (cls);
5503}

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

12435{
12436 const char *colon;
12437 char *colon_rest;
12438 size_t colon_rest_length;
12439 char *address_without_port;
12440
12441 colon = strchr (address,':');
12442 colon_rest = GNUNET_strndup (address, colon - address);
12443 colon_rest_length = strlen (colon_rest);
12444 address_without_port = GNUNET_strndup (&colon_rest[4], colon_rest_length - 4);
12445 GNUNET_free (colon_rest);
12446
12447 return address_without_port;
12448}

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

5521{
5522 struct AddGlobalAddressesContext *ctx = cls;
5523 struct TransportGlobalNattedAddress *tgna = value;
5524 char *addr = (char *) &tgna[1];
5525
5527 "sending address %s length %u\n",
5528 addr,
5529 ntohl (tgna->address_length));
5530 GNUNET_memcpy (&(ctx->tgnas[ctx->off]), tgna, sizeof (struct
5532 + ntohl (tgna->address_length));
5533 ctx->off += sizeof(struct TransportGlobalNattedAddress) + ntohl (tgna->
5535
5536 return GNUNET_OK;
5537}

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

10249{
10251 unsigned int n_hops = 0;
10252
10254 "calculate_rtt\n");
10255 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
10256 pos = pos->next_dv)
10257 {
10259 "calculate_rtt %lu\n",
10260 (unsigned long) pos->pd.aged_rtt.rel_value_us);
10261 n_hops++;
10263 aged_rtt, pos
10264 ->distance
10265 + 2), ret);
10266 }
10267
10268 GNUNET_assert (0 != n_hops);
10269
10270 return ret;
10271}

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

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

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

5807{
5808 struct TransportClient *tc = cls;
5809 struct PendingMessage *pm;
5810 const struct GNUNET_MessageHeader *obmm;
5811 uint32_t bytes_msg;
5812 struct VirtualLink *vl;
5814
5815 GNUNET_assert (CT_CORE == tc->type);
5816 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
5817 bytes_msg = ntohs (obmm->size);
5818 pp = ntohl (obm->priority);
5819 vl = lookup_virtual_link (&obm->peer);
5820 if ((NULL == vl) || (GNUNET_NO == vl->confirmed))
5821 {
5823 "Don't have %s as a neighbour (anymore).\n",
5824 GNUNET_i2s (&obm->peer));
5825 /* Failure: don't have this peer as a neighbour (anymore).
5826 Might have gone down asynchronously, so this is NOT
5827 a protocol violation by CORE. Still count the event,
5828 as this should be rare. */
5831 "# messages dropped (neighbour unknown)",
5832 1,
5833 GNUNET_NO);
5834 return;
5835 }
5836
5837 pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
5839 "1 created pm %p storing vl %p\n",
5840 pm,
5841 vl);
5842 pm->logging_uuid = logging_uuid_gen++;
5843 pm->prefs = pp;
5844 pm->client = tc;
5845 pm->vl = vl;
5846 pm->bytes_msg = bytes_msg;
5847 memcpy (&pm[1], obmm, bytes_msg);
5849 "Sending message of type %u with %u bytes as <%" PRIu64
5850 "> to %s\n",
5851 ntohs (obmm->type),
5852 bytes_msg,
5853 pm->logging_uuid,
5854 GNUNET_i2s (&obm->peer));
5856 tc->details.core.pending_msg_head,
5857 tc->details.core.pending_msg_tail,
5858 pm);
5860 vl->pending_msg_head,
5861 vl->pending_msg_tail,
5862 pm);
5865}

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

5881{
5882 struct Neighbour *n;
5883 struct VirtualLink *vl;
5884 struct TransportClient *tc = cls;
5885 const struct GNUNET_MessageHeader *inbox =
5886 (const struct GNUNET_MessageHeader *) &cb[1];
5887 uint16_t isize = ntohs (inbox->size);
5888 const char *is = ((const char *) &cb[1]) + isize;
5889 size_t slen = strlen (is) + 1;
5890 char
5891 mbuf[slen + isize
5892 + sizeof(struct
5896
5897 /* 0-termination of 'is' was checked already in
5898 #check_communicator_backchannel() */
5900 "Preparing backchannel transmission to %s:%s of type %u and size %u\n",
5901 GNUNET_i2s (&cb->pid),
5902 is,
5903 ntohs (inbox->type),
5904 ntohs (inbox->size));
5905 /* encapsulate and encrypt message */
5906 be->header.type =
5908 be->header.size = htons (sizeof(mbuf));
5909 memcpy (&be[1], inbox, isize);
5910 memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
5911 + isize],
5912 is,
5913 strlen (is) + 1);
5914 // route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
5915 vl = lookup_virtual_link (&cb->pid);
5916 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
5917 {
5919 }
5920 else
5921 {
5922 /* Use route via neighbour */
5923 n = lookup_neighbour (&cb->pid);
5924 if (NULL != n)
5926 n,
5927 &be->header,
5928 RMO_NONE);
5929 }
5931}

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

5944{
5945 struct TransportClient *tc = cls;
5946
5947 if (CT_COMMUNICATOR != tc->type)
5948 {
5949 GNUNET_break (0);
5950 return GNUNET_SYSERR;
5951 }
5953 return GNUNET_OK;
5954}

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

6210{
6211 struct AddressListEntry *ale = cls;
6212 const char *dash;
6213 char *address_uri;
6214 char *prefix;
6215 unsigned int add_success;
6216
6217 if (NULL == GNUNET_PILS_get_identity (pils))
6218 {
6220 &store_pi,
6221 ale);
6222 return;
6223 }
6225 dash = strchr (ale->address, '-');
6226 GNUNET_assert (NULL != dash);
6227 dash++;
6228 GNUNET_asprintf (&address_uri,
6229 "%s://%s",
6230 prefix,
6231 dash);
6233 ale->st = NULL;
6235 "Storing our address `%s' in peerstore until %s!\n",
6236 ale->address,
6239 address_uri);
6240 if (GNUNET_OK != add_success)
6241 {
6243 "Storing our address `%s' %s\n",
6244 address_uri,
6245 GNUNET_NO == add_success ? "not done" : "failed");
6246 GNUNET_free (address_uri);
6247 return;
6248 }
6249 else
6250 {
6251
6253 "Storing our address `%s'\n",
6254 address_uri);
6255 }
6256 // FIXME hello_mono_time used here?? What about expiration in ale?
6257 pils_sign_address (ale,
6259 // TODO keep track of op and potentially cancel/clean
6260 GNUNET_free (address_uri);
6261}

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

5992{
5993 struct PilsAddressSignContext *pc = cls;
5994
5995 GNUNET_assert (NULL == pc->req);
5996 if (GNUNET_OK != success)
5997 {
5999 "Failed to store our address `%s' with peerstore\n",
6000 pc->ale->address);
6001 if (NULL == pc->ale->st)
6002 {
6004 &store_pi,
6005 pc->ale);
6006 }
6007 }
6008 GNUNET_free (pc);
6009}

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

6019{
6020 struct PilsAddressSignContext *pc = cls;
6021 struct GNUNET_MQ_Envelope *env;
6022 const struct GNUNET_MessageHeader *msg;
6023
6024 pc->req->op = NULL;
6027 pc->req);
6028 GNUNET_free (pc->req);
6029 pc->req = NULL;
6032 pid,
6033 sig,
6034 pc->et);
6037 "store_pi 1\n");
6039 msg,
6040 shc_cont,
6041 pc);
6042 GNUNET_free (env);
6043}

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

6054{
6055 struct PilsAddressSignContext *pc = cls;
6056
6057 pc->ale->sc = NULL;
6058 if (GNUNET_YES != success)
6060 "Failed to store our own address `%s' in peerstore!\n",
6061 pc->ale->address);
6062 else
6064 "Successfully stored our own address `%s' in peerstore!\n",
6065 pc->ale->address);
6066 /* refresh period is 1/4 of expiration time, that should be plenty
6067 without being excessive. */
6068 if (NULL == pc->ale->st)
6069 {
6070 pc->ale->st =
6072 GNUNET_TIME_relative_divide (pc->ale->expiration,
6073 4ULL),
6074 &store_pi,
6075 pc->ale);
6076 }
6077
6078 /* Now we have to update our HELLO! */
6080 pc->req = GNUNET_new (struct PilsRequest);
6083 pc->req);
6084 pc->req->op = GNUNET_PILS_sign_hello (pils,
6086 pc->et,
6088 pc);
6089}

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

6097{
6098 struct PilsAddressSignContext *pc = cls;
6099 char *sig_str;
6100 void *result;
6101 size_t result_size;
6102
6103 pc->req->op = NULL;
6106 pc->req);
6107 GNUNET_free (pc->req);
6108 sig_str = NULL;
6109 (void) GNUNET_STRINGS_base64_encode (sig, sizeof(*sig), &sig_str);
6110 result_size =
6111 1 + GNUNET_asprintf (
6112 (char **) &result,
6113 "%s;%llu;%u;%s",
6114 sig_str,
6115 (unsigned long long) pc->et.abs_value_us,
6116 (unsigned int) pc->ale->nt,
6117 pc->ale->address);
6118 GNUNET_free (sig_str);
6119
6121 "Build our HELLO URI `%s'\n",
6122 (char*) result);
6123
6124 pc->ale->signed_address = result;
6125 pc->ale->signed_address_len = result_size;
6127
6128 expiration = GNUNET_TIME_relative_to_absolute (pc->ale->expiration);
6130 "transport",
6131 pid,
6133 result,
6134 result_size,
6135 expiration,
6138 pc);
6139}

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

6181{
6182 struct SignedAddress sa;
6183 struct PilsAddressSignContext *pc;
6184
6185 sa.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS);
6186 sa.purpose.size = htonl (sizeof(sa));
6187 sa.mono_time = GNUNET_TIME_absolute_hton (mono_time);
6188 GNUNET_CRYPTO_hash (ale->address, strlen (ale->address), &sa.addr_hash);
6190 pc->ale = ale;
6191 pc->et = mono_time;
6192 pc->req = GNUNET_new (struct PilsRequest);
6194 &sa.purpose,
6196 pc);
6199 pc->req);
6200}

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

6271{
6272 struct AddressListEntry *ale;
6273 char *address_without_port;
6274
6275 ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
6276 ale->tc = tc;
6277 ale->address = (const char *) &ale[1];
6278 ale->expiration = expiration;
6279 ale->aid = aid;
6280 ale->nt = nt;
6281 memcpy (&ale[1], address, slen);
6282 address_without_port = get_address_without_port (ale->address);
6284 "Is this %s a local address (%s)\n",
6285 address_without_port,
6286 ale->address);
6287 if (0 != strcmp ("127.0.0.1", address_without_port))
6288 {
6289 if (NULL != ale->st)
6290 {
6292 }
6293 ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
6294 }
6295 GNUNET_free (address_without_port);
6296
6297 return ale;
6298}

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

6303{
6304
6306 "Feeding addresses to PILS\n");
6307 pils_feed_task = NULL;
6308
6310 GST_my_hello);
6311}

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

6323{
6324 struct TransportClient *tc = cls;
6325 struct AddressListEntry *ale;
6326 size_t slen;
6327 char *address;
6328
6329 /* 0-termination of &aam[1] was checked in #check_add_address */
6331 "Communicator added address `%s'!\n",
6332 (const char *) &aam[1]);
6333 slen = ntohs (aam->header.size) - sizeof(*aam);
6334 address = GNUNET_malloc (slen);
6335 memcpy (address, &aam[1], slen);
6336 ale = create_address_entry (tc,
6338 ntohl (aam->nt),
6339 address,
6340 aam->aid,
6341 slen);
6342 GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
6343 tc->details.communicator.addr_tail,
6344 ale);
6345 {
6346 for (struct AddressListEntry *iter = tc->details.communicator.addr_head;
6347 (NULL != iter && NULL != iter->next);
6348 iter = iter->next)
6349 {
6350 char *address_uri;
6351 const char *dash = strchr (ale->address, '-');
6353 GNUNET_assert (NULL != dash);
6354 dash++;
6355 GNUNET_asprintf (&address_uri,
6356 "%s://%s",
6357 prefix,
6358 dash);
6361 GNUNET_free (address_uri);
6362 }
6363 if (NULL != pils_feed_task)
6367 NULL);
6368 }
6371}

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

6383{
6384 struct TransportClient *tc = cls;
6385 struct AddressListEntry *alen;
6386
6387 if (CT_COMMUNICATOR != tc->type)
6388 {
6389 GNUNET_break (0);
6391 return;
6392 }
6393 for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
6394 NULL != ale;
6395 ale = alen)
6396 {
6397 alen = ale->next;
6398 if (dam->aid != ale->aid)
6399 continue;
6400 GNUNET_assert (ale->tc == tc);
6402 "Communicator deleted address `%s'!\n",
6403 ale->address);
6405 ale->address);
6406 if (NULL != pils_feed_task)
6410 NULL);
6413 return;
6414 }
6416 "Communicator removed address we did not even have.\n");
6418 // GNUNET_SERVICE_client_drop (tc->client);
6419}

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

10640{
10642 { GNUNET_MQ_hd_var_size (fragment_box,
10645 cmc),
10646 GNUNET_MQ_hd_var_size (reliability_box,
10649 cmc),
10650 GNUNET_MQ_hd_var_size (reliability_ack,
10653 cmc),
10654 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
10657 cmc),
10658 GNUNET_MQ_hd_var_size (dv_learn,
10661 cmc),
10662 GNUNET_MQ_hd_var_size (dv_box,
10664 struct TransportDVBoxMessage,
10665 cmc),
10666 GNUNET_MQ_hd_var_size (flow_control,
10669 cmc),
10671 validation_challenge,
10674 cmc),
10676 validation_response,
10679 cmc),
10681 int ret;
10682 const struct GNUNET_MessageHeader *msg = cmc->mh;
10683
10685 "Handling message of type %u with %u bytes\n",
10686 (unsigned int) ntohs (msg->type),
10687 (unsigned int) ntohs (msg->size));
10689 if (GNUNET_SYSERR == ret)
10690 {
10691 GNUNET_break (0);
10693 GNUNET_free (cmc);
10694 return;
10695 }
10696 if (GNUNET_NO == ret)
10697 {
10698 /* unencapsulated 'raw' message */
10699 handle_raw_message (cmc, msg);
10700 }
10701}

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

6442{
6443 struct CoreSentContext *ctx = cls;
6444 struct VirtualLink *vl = ctx->vl;
6445
6446 if (NULL == vl)
6447 {
6448 /* lost the link in the meantime, ignore */
6449 GNUNET_free (ctx);
6450 return;
6451 }
6454 vl->incoming_fc_window_size_ram -= ctx->size;
6455 vl->incoming_fc_window_size_used += ctx->isize;
6457 GNUNET_free (ctx);
6458}

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

6466{
6467 uint16_t size = ntohs (mh->size);
6468 int have_core;
6469
6470 if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
6471 {
6473 "# CORE messages dropped (FC arithmetic overflow)",
6474 1,
6475 GNUNET_NO);
6477 "CORE messages of type %u with %u bytes dropped (FC arithmetic overflow)\n",
6478 (unsigned int) ntohs (mh->type),
6479 (unsigned int) ntohs (mh->size));
6480 if (GNUNET_YES == free_cmc)
6482 return;
6483 }
6485 {
6487 "# CORE messages dropped (FC window overflow)",
6488 1,
6489 GNUNET_NO);
6491 "CORE messages of type %u with %u bytes dropped (FC window overflow)\n",
6492 (unsigned int) ntohs (mh->type),
6493 (unsigned int) ntohs (mh->size));
6494 if (GNUNET_YES == free_cmc)
6496 return;
6497 }
6498
6499 /* Forward to all CORE clients */
6500 have_core = GNUNET_NO;
6501 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
6502 {
6503 struct GNUNET_MQ_Envelope *env;
6504 struct InboundMessage *im;
6505 struct CoreSentContext *ctx;
6506
6507 if (CT_CORE != tc->type)
6508 continue;
6511 ctx = GNUNET_new (struct CoreSentContext);
6512 ctx->vl = vl;
6513 ctx->size = size;
6514 ctx->isize = (GNUNET_NO == have_core) ? size : 0;
6515 have_core = GNUNET_YES;
6518 im->peer = cmc->im.sender;
6519 memcpy (&im[1], mh, size);
6520 GNUNET_MQ_send (tc->mq, env);
6522 }
6523 if (GNUNET_NO == have_core)
6524 {
6526 "Dropped message to CORE: no CORE client connected!\n");
6527 /* Nevertheless, count window as used, as it is from the
6528 perspective of the other peer! */
6530 /* TODO-M1 */
6532 "Dropped message of type %u with %u bytes to CORE: no CORE client connected!\n",
6533 (unsigned int) ntohs (mh->type),
6534 (unsigned int) ntohs (mh->size));
6535 if (GNUNET_YES == free_cmc)
6537 return;
6538 }
6540 "Delivered message from %s of type %u to CORE recv window %d\n",
6541 GNUNET_i2s (&cmc->im.sender),
6542 ntohs (mh->type),
6544 if (vl->core_recv_window > 0)
6545 {
6546 if (GNUNET_YES == free_cmc)
6548 return;
6549 }
6550 /* Wait with calling #finish_cmc_handling(cmc) until the message
6551 was processed by CORE MQs (for CORE flow control)! */
6552 if (GNUNET_YES == free_cmc)
6554}

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

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

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

6670{
6671 uint16_t size = ntohs (fb->header.size);
6672 uint16_t bsize = size - sizeof(*fb);
6673
6674 (void) cls;
6675 if (0 == bsize)
6676 {
6677 GNUNET_break_op (0);
6678 return GNUNET_SYSERR;
6679 }
6680 if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
6681 {
6682 GNUNET_break_op (0);
6683 return GNUNET_SYSERR;
6684 }
6685 if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
6686 {
6687 GNUNET_break_op (0);
6688 return GNUNET_SYSERR;
6689 }
6690 return GNUNET_YES;
6691}

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

6701{
6702 struct AcknowledgementCummulator *ac = cls;
6703
6704 ac->task = NULL;
6705 GNUNET_assert (0 == ac->num_acks);
6707 GNUNET_YES ==
6709 GNUNET_free (ac);
6710}

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

6720{
6721 struct Neighbour *n;
6722 struct VirtualLink *vl;
6723 struct AcknowledgementCummulator *ac = cls;
6724 char buf[sizeof(struct TransportReliabilityAckMessage)
6725 + ac->num_acks
6727 struct TransportReliabilityAckMessage *ack =
6728 (struct TransportReliabilityAckMessage *) buf;
6730
6731 ac->task = NULL;
6733 "Sending ACK with %u components to %s\n",
6734 ac->num_acks,
6735 GNUNET_i2s (&ac->target));
6736 GNUNET_assert (0 < ac->num_acks);
6738 ack->header.size =
6739 htons (sizeof(*ack)
6740 + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP));
6741 ack->ack_counter = htonl (ac->ack_counter += ac->num_acks);
6742 ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
6743 for (unsigned int i = 0; i < ac->num_acks; i++)
6744 {
6745 ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
6748 }
6749 /*route_control_message_without_fc (
6750 &ac->target,
6751 &ack->header,
6752 RMO_DV_ALLOWED);*/
6753 vl = lookup_virtual_link (&ac->target);
6754 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
6755 {
6757 vl,
6758 &ack->header,
6760 }
6761 else
6762 {
6763 /* Use route via neighbour */
6764 n = lookup_neighbour (&ac->target);
6765 if (NULL != n)
6767 n,
6768 &ack->header,
6769 RMO_NONE);
6770 }
6771 ac->num_acks = 0;
6774 ac);
6775}

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

6790{
6791 struct AcknowledgementCummulator *ac;
6792
6794 "Scheduling ACK %s for transmission to %s\n",
6795 GNUNET_uuid2s (&ack_uuid->value),
6796 GNUNET_i2s (pid));
6798 if (NULL == ac)
6799 {
6801 ac->target = *pid;
6802 ac->min_transmission_time = max_delay;
6806 &ac->target,
6807 ac,
6809 }
6810 else
6811 {
6812 if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
6813 {
6814 /* must run immediately, ack buffer full! */
6816 }
6820 }
6823 ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
6824 ac->num_acks++;
6827 ac);
6828}

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

6859{
6860 struct FindByMessageUuidContext *fc = cls;
6861 struct ReassemblyContext *rc = value;
6862
6863 (void) key;
6864 if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
6865 {
6866 fc->rc = rc;
6867 return GNUNET_NO;
6868 }
6869 return GNUNET_YES;
6870}

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

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

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

7053{
7054 const struct GNUNET_MessageHeader *box = (const struct
7055 GNUNET_MessageHeader *) &rb[1];
7056 (void) cls;
7057
7059 "check_send_msg with size %u: inner msg type %u and size %u (%lu %lu)\n",
7060 ntohs (rb->header.size),
7061 ntohs (box->type),
7062 ntohs (box->size),
7063 sizeof (struct TransportReliabilityBoxMessage),
7064 sizeof (struct GNUNET_MessageHeader));
7066 return GNUNET_YES;
7067}

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

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

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

7120{
7121 unsigned int sage;
7122
7123 if (age == pd->last_age)
7124 return; /* nothing to do */
7125 sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
7126 for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
7127 {
7128 struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
7129
7130 the->bytes_sent = 0;
7131 the->bytes_received = 0;
7132 }
7133 pd->last_age = age;
7134}

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

7149{
7150 uint64_t nval = rtt.rel_value_us;
7151 uint64_t oval = pd->aged_rtt.rel_value_us;
7152 unsigned int age = get_age ();
7153 struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
7154
7155 if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
7156 pd->aged_rtt = rtt;
7157 else
7158 pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
7159 update_pd_age (pd, age);
7160 the->bytes_received += bytes_transmitted_ok;
7161}

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

7175{
7176 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
7177}

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

7191{
7192 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
7193}

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

7205{
7206 struct PendingMessage *pos;
7207
7209 "Complete transmission of message %" PRIu64 " %u\n",
7210 pm->logging_uuid,
7211 pm->pmt);
7212 switch (pm->pmt)
7213 {
7214 case PMT_CORE:
7216 /* Full message sent, we are done */
7218 return;
7219
7220 case PMT_FRAGMENT_BOX:
7221 /* Fragment sent over reliable channel */
7222 pos = pm->frag_parent;
7226 "pos frag_off %lu pos bytes_msg %lu pmt %u parent %u\n",
7227 (unsigned long) pos->frag_off,
7228 (unsigned long) pos->bytes_msg,
7229 pos->pmt,
7230 NULL == pos->frag_parent ? 1 : 0);
7231 /* check if subtree is done */
7232 while ((NULL == pos->head_frag) && (pos->frag_off == (pos->bytes_msg
7233 - sizeof(struct
7235 &&
7236 (NULL != pos->frag_parent))
7237 {
7238 pm = pos;
7239 pos = pm->frag_parent;
7240 if ((NULL == pos) && (PMT_DV_BOX == pm->pmt))
7241 {
7243 return;
7244 }
7245 else if (PMT_DV_BOX == pm->pmt)
7246 {
7248 return;
7249 }
7252 }
7253
7254 /* Was this the last applicable fragment? */
7255 if ((NULL == pos->head_frag) && (NULL == pos->frag_parent || PMT_DV_BOX ==
7256 pos->pmt) &&
7257 (pos->frag_off == pos->bytes_msg))
7259 return;
7260
7261 case PMT_DV_BOX:
7263 "Completed transmission of message %" PRIu64 " (DV Box)\n",
7264 pm->logging_uuid);
7265 if (NULL != pm->frag_parent)
7266 {
7267 pos = pm->frag_parent;
7269 pos->bpm = NULL;
7271 }
7272 else
7274 return;
7275 }
7276}

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

7289{
7290 struct GNUNET_TIME_Relative delay;
7291
7293 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
7294 if (NULL != pa->queue && 1 == pa->num_send)
7296 if (NULL != pa->dvh && 1 == pa->num_send)
7297 update_dvh_performance (pa->dvh, delay, pa->message_size);
7298 if (NULL != pa->pm)
7301}

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

7314{
7315 unsigned int n_acks;
7316
7317 (void) cls;
7318 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7319 / sizeof(struct TransportCummulativeAckPayloadP);
7320 if (0 == n_acks)
7321 {
7322 GNUNET_break_op (0);
7323 return GNUNET_SYSERR;
7324 }
7325 if ((ntohs (ra->header.size) - sizeof(*ra)) !=
7326 n_acks * sizeof(struct TransportCummulativeAckPayloadP))
7327 {
7328 GNUNET_break_op (0);
7329 return GNUNET_SYSERR;
7330 }
7331 return GNUNET_OK;
7332}

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

7345{
7346 struct CommunicatorMessageContext *cmc = cls;
7347 const struct TransportCummulativeAckPayloadP *ack;
7348 unsigned int n_acks;
7349 uint32_t ack_counter;
7350
7351 n_acks = (ntohs (ra->header.size) - sizeof(*ra))
7352 / sizeof(struct TransportCummulativeAckPayloadP);
7353 ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
7354 for (unsigned int i = 0; i < n_acks; i++)
7355 {
7356 struct PendingAcknowledgement *pa =
7358 if (NULL == pa)
7359 {
7361 "Received ACK from %s with UUID %s which is unknown to us!\n",
7362 GNUNET_i2s (&cmc->im.sender),
7363 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7365 GST_stats,
7366 "# FRAGMENT_ACKS dropped, no matching pending message",
7367 1,
7368 GNUNET_NO);
7369 continue;
7370 }
7372 "Received ACK from %s with UUID %s\n",
7373 GNUNET_i2s (&cmc->im.sender),
7374 GNUNET_uuid2s (&ack[i].ack_uuid.value));
7375 handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
7376 }
7377
7378 ack_counter = htonl (ra->ack_counter);
7379 (void) ack_counter; /* silence compiler warning for now */
7380 // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
7381 // (DV and/or Neighbour?)
7382 finish_cmc_handling (cmc);
7383}

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

7397{
7398 uint16_t size = ntohs (be->header.size) - sizeof(*be);
7399 const struct GNUNET_MessageHeader *inbox =
7400 (const struct GNUNET_MessageHeader *) &be[1];
7401 const char *is;
7402 uint16_t isize;
7403
7404 (void) cls;
7405 if (ntohs (inbox->size) >= size)
7406 {
7407 GNUNET_break_op (0);
7408 return GNUNET_SYSERR;
7409 }
7410 isize = ntohs (inbox->size);
7411 is = ((const char *) inbox) + isize;
7412 size -= isize;
7413 if ('\0' != is[size - 1])
7414 {
7415 GNUNET_break_op (0);
7416 return GNUNET_SYSERR;
7417 }
7418 return GNUNET_YES;
7419}

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

7434{
7435 const struct GNUNET_PeerIdentity *my_identity;
7436 struct CommunicatorMessageContext *cmc = cls;
7438 struct GNUNET_MQ_Envelope *env;
7439 struct TransportClient *tc;
7440 const struct GNUNET_MessageHeader *inbox =
7441 (const struct GNUNET_MessageHeader *) &be[1];
7442 uint16_t isize = ntohs (inbox->size);
7443 const char *target_communicator = ((const char *) inbox) + isize;
7444 char *sender;
7445 char *self;
7446
7449
7450 GNUNET_asprintf (&sender,
7451 "%s",
7452 GNUNET_i2s (&cmc->im.sender));
7453 GNUNET_asprintf (&self,
7454 "%s",
7456
7457 /* Find client providing this communicator */
7458 for (tc = clients_head; NULL != tc; tc = tc->next)
7459 if ((CT_COMMUNICATOR == tc->type) &&
7460 (0 ==
7461 strcmp (tc->details.communicator.address_prefix, target_communicator)))
7462 break;
7463 if (NULL == tc)
7464 {
7465 char *stastr;
7466
7468 &stastr,
7469 "# Backchannel message dropped: target communicator `%s' unknown",
7470 target_communicator);
7472 GNUNET_free (stastr);
7473 finish_cmc_handling (cmc);
7474 return;
7475 }
7476 /* Finally, deliver backchannel message to communicator */
7478 "Delivering backchannel message from %s to %s of type %u to %s\n",
7479 sender,
7480 self,
7481 ntohs (inbox->type),
7482 target_communicator);
7484 cbi,
7485 isize,
7487 cbi->pid = cmc->im.sender;
7488 memcpy (&cbi[1], inbox, isize);
7489 GNUNET_MQ_send (tc->mq, env);
7490 finish_cmc_handling (cmc);
7491}

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

7505{
7506 struct DistanceVector *dv = cls;
7507 struct DistanceVectorHop *pos;
7508
7509 dv->timeout_task = NULL;
7510 while (NULL != (pos = dv->dv_head))
7511 {
7512 GNUNET_assert (dv == pos->dv);
7514 break;
7516 }
7517 if (NULL == pos)
7518 {
7519 free_dv_route (dv);
7520 return;
7521 }
7522 dv->timeout_task =
7524}

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

7529{
7530
7531 const struct GNUNET_PeerIdentity target = vl->target;
7532
7533
7535 {
7536 struct RingBufferEntry *ring_buffer_copy[RING_BUFFER_SIZE];
7537 unsigned int tail = GNUNET_YES == is_ring_buffer_full ? ring_buffer_head :
7538 0;
7539 unsigned int head = GNUNET_YES == is_ring_buffer_full ? RING_BUFFER_SIZE :
7542 struct CommunicatorMessageContext *cmc;
7543 struct RingBufferEntry *rbe;
7544 struct GNUNET_MessageHeader *mh;
7545
7547 "Sending from ring buffer, which has %u items\n",
7548 head);
7549
7550 ring_buffer_head = 0;
7551 for (unsigned int i = 0; i < head; i++)
7552 {
7553 rbe = ring_buffer[(i + tail) % RING_BUFFER_SIZE];
7554 cmc = rbe->cmc;
7555 mh = rbe->mh;
7556
7557 im = cmc->im;
7558 // mh = cmc->mh;
7560 "Sending message of type %u to ring buffer target %s using vl target %s index %u\n",
7561 mh->type,
7562 GNUNET_i2s (&im.sender),
7563 GNUNET_i2s2 (&target),
7564 (i + tail) % RING_BUFFER_SIZE);
7565 if (0 == GNUNET_memcmp (&target, &im.sender))
7566 {
7568 "Finish handling message of type %u and size %u\n",
7569 (unsigned int) ntohs (mh->type),
7570 (unsigned int) ntohs (mh->size));
7572 GNUNET_free (mh);
7573 GNUNET_free (rbe->cmc);
7574 GNUNET_free (rbe);
7575 }
7576 else
7577 {
7578 ring_buffer_copy[ring_buffer_head] = rbe;
7580 }
7581 }
7582
7585 {
7587 }
7588
7589 for (unsigned int i = 0; i < ring_buffer_head; i++)
7590 {
7591 ring_buffer[i] = ring_buffer_copy[i];
7593 "ring_buffer_copy[i]->mh->type for i %u %u\n",
7594 i,
7595 ring_buffer_copy[i]->mh->type);
7597 "ring_buffer[i]->mh->type for i %u %u\n",
7598 i,
7599 ring_buffer[i]->mh->type);
7600 }
7601
7603 "%u items still in ring buffer\n",
7605 }
7606
7608 {
7609 struct PendingMessage *ring_buffer_dv_copy[RING_BUFFER_SIZE];
7610 struct PendingMessage *pm;
7611 unsigned int tail = GNUNET_YES == is_ring_buffer_dv_full ?
7613 0;
7614 unsigned int head = GNUNET_YES == is_ring_buffer_dv_full ?
7617
7619 "Sending from ring buffer dv, which has %u items\n",
7620 head);
7621
7623 for (unsigned int i = 0; i < head; i++)
7624 {
7625 pm = ring_buffer_dv[(i + tail) % RING_BUFFER_SIZE];
7626
7628 "Sending to ring buffer target %s using vl target %s\n",
7629 GNUNET_i2s (&pm->target),
7630 GNUNET_i2s2 (&target));
7631 if (0 == GNUNET_memcmp (&target, &pm->target))
7632 {
7634 "Adding PendingMessage to vl, checking transmission.\n");
7635 pm->vl = vl;
7639 pm);
7640
7642 }
7643 else
7644 {
7645 ring_buffer_dv_copy[ring_buffer_dv_head] = pm;
7647 }
7648 }
7649
7651 {
7653 }
7654
7655 for (unsigned int i = 0; i < ring_buffer_dv_head; i++)
7656 ring_buffer_dv[i] = ring_buffer_dv_copy[i];
7657
7659 "%u items still in ring buffer dv.\n",
7661
7662 }
7663}

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

7675{
7676 struct DistanceVector *dv = hop->dv;
7677 struct VirtualLink *vl;
7678
7679 vl = lookup_virtual_link (&dv->target);
7680 if (NULL == vl)
7681 {
7682
7683 vl = GNUNET_new (struct VirtualLink);
7685 "Creating new virtual link %p to %s using DV!\n",
7686 vl,
7687 GNUNET_i2s (&dv->target));
7688 vl->burst_addr = NULL;
7689 vl->confirmed = GNUNET_YES;
7690 vl->message_uuid_ctr =
7692 vl->target = dv->target;
7698 links,
7699 &vl->target,
7700 vl,
7702 vl->dv = dv;
7703 dv->vl = vl;
7704 vl->visibility_task =
7707 /* We lacked a confirmed connection to the target
7708 before, so tell CORE about it (finally!) */
7711 }
7712 else
7713 {
7714 /* Link was already up, remember dv is also now available and we are done */
7715 vl->dv = dv;
7716 dv->vl = vl;
7717 if (GNUNET_NO == vl->confirmed)
7718 {
7719 vl->confirmed = GNUNET_YES;
7720 vl->visibility_task =
7723 /* We lacked a confirmed connection to the target
7724 before, so tell CORE about it (finally!) */
7727 }
7728 else
7730 "Virtual link to %s could now also use DV!\n",
7731 GNUNET_i2s (&dv->target));
7732 }
7733}

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

Referenced by learn_dv_path().

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

◆ learn_dv_path()

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

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

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

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

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

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

7766{
7767 const struct GNUNET_PeerIdentity *my_identity;
7768 struct DistanceVectorHop *hop;
7769 struct DistanceVector *dv;
7770 struct Neighbour *next_hop;
7771 unsigned int shorter_distance;
7772
7773 if (path_len < 3)
7774 {
7775 /* what a boring path! not allowed! */
7776 GNUNET_break (0);
7777 return GNUNET_SYSERR;
7778 }
7779
7782
7783 GNUNET_assert (0 == GNUNET_memcmp (my_identity, &path[0]));
7784 next_hop = lookup_neighbour (&path[1]);
7785 if (NULL == next_hop)
7786 {
7787 /* next hop must be a neighbour, otherwise this whole thing is useless! */
7788 GNUNET_break (0);
7789 return GNUNET_SYSERR;
7790 }
7791 for (unsigned int i = 2; i < path_len; i++)
7792 {
7793 struct Neighbour *n = lookup_neighbour (&path[i]);
7794 struct GNUNET_TIME_Absolute q_timeout;
7795
7796 if (NULL != n)
7797 {
7798 q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
7799 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
7800 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
7802 "remaining %lu to %s\n",
7803 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout)
7804 .rel_value_us,
7805 GNUNET_i2s (&n->pid));
7806 if (0 != GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
7807 {
7808 /* Useless path: we have a direct active connection to some hop
7809 in the middle of the path, so this one is not even
7810 terribly useful for redundancy */
7812 "Path of %u hops useless: directly link to hop %u (%s)\n",
7813 path_len,
7814 i,
7815 GNUNET_i2s (&path[i]));
7817 "# Useless DV path ignored: hop is neighbour",
7818 1,
7819 GNUNET_NO);
7820 return GNUNET_SYSERR;
7821 }
7822 }
7823 }
7824 dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
7825 if (NULL == dv)
7826 {
7827 dv = GNUNET_new (struct DistanceVector);
7828 dv->target = path[path_len - 1];
7831 dv);
7834 dv_routes,
7835 &dv->target,
7836 dv,
7838 }
7839 /* Check if we have this path already! */
7840 shorter_distance = 0;
7841 for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
7842 pos = pos->next_dv)
7843 {
7844 if (pos->distance < path_len - 3)
7845 shorter_distance++;
7846 /* Note that the distances in 'pos' excludes us (path[0]),
7847 the next_hop (path[1]) and the target so we need to subtract three
7848 and check next_hop explicitly */
7849 if ((pos->distance == path_len - 3) && (pos->next_hop == next_hop))
7850 {
7851 int match = GNUNET_YES;
7852
7853 for (unsigned int i = 0; i < pos->distance; i++)
7854 {
7855 if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
7856 {
7857 match = GNUNET_NO;
7858 break;
7859 }
7860 }
7861 if (GNUNET_YES == match)
7862 {
7863 struct GNUNET_TIME_Relative last_timeout;
7864
7865 /* Re-discovered known path, update timeout */
7867 "# Known DV path refreshed",
7868 1,
7869 GNUNET_NO);
7870 last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
7871 pos->timeout =
7873 pos->path_valid_until =
7874 GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
7875 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
7876 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
7877 if (0 <
7880 if (last_timeout.rel_value_us <
7883 .rel_value_us)
7884 {
7885 /* Some peer send DV learn messages too often, we are learning
7886 the same path faster than it would be useful; do not forward! */
7888 "Rediscovered path too quickly, not forwarding further\n")
7889 ;
7890 return GNUNET_NO;
7891 }
7893 "Refreshed known path to %s valid until %s, forwarding further\n",
7894 GNUNET_i2s (&dv->target),
7896 pos->path_valid_until));
7897 return GNUNET_YES;
7898 }
7899 }
7900 }
7901 /* Count how many shorter paths we have (incl. direct
7902 neighbours) before simply giving up on this one! */
7903 if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
7904 {
7905 /* We have a shorter path already! */
7907 "Have many shorter DV paths %s, not forwarding further\n",
7908 GNUNET_i2s (&dv->target));
7909 return GNUNET_NO;
7910 }
7911 /* create new DV path entry */
7913 "Discovered new DV path to %s valid until %s\n",
7914 GNUNET_i2s (&dv->target),
7915 GNUNET_STRINGS_absolute_time_to_string (path_valid_until));
7916 hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
7917 + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7918 hop->next_hop = next_hop;
7919 hop->dv = dv;
7920 hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
7921 memcpy (&hop[1],
7922 &path[2],
7923 sizeof(struct GNUNET_PeerIdentity) * (path_len - 3));
7925 hop->path_valid_until = path_valid_until;
7926 hop->distance = path_len - 3;
7927 hop->pd.aged_rtt = network_latency;
7928 GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
7930 next_hop->dv_head,
7931 next_hop->dv_tail,
7932 hop);
7933 if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
7935 return GNUNET_YES;
7936}

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

7948{
7949 const struct GNUNET_PeerIdentity *my_identity;
7950 uint16_t size = ntohs (dvl->header.size);
7951 uint16_t num_hops = ntohs (dvl->num_hops);
7952 const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
7953
7954 (void) cls;
7955 if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
7956 {
7957 GNUNET_break_op (0);
7958 return GNUNET_SYSERR;
7959 }
7960 if (num_hops > MAX_DV_HOPS_ALLOWED)
7961 {
7962 GNUNET_break_op (0);
7963 return GNUNET_SYSERR;
7964 }
7965
7968
7969 for (unsigned int i = 0; i < num_hops; i++)
7970 {
7971 if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
7972 {
7973 GNUNET_break_op (0);
7974 return GNUNET_SYSERR;
7975 }
7976 if (0 == GNUNET_memcmp (my_identity, &hops[i].hop))
7977 {
7978 GNUNET_break_op (0);
7979 return GNUNET_SYSERR;
7980 }
7981 }
7982 return GNUNET_YES;
7983}

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

8000{
8001 struct SignDhpCls *sign_dhp_cls = cls;
8002 struct VirtualLink *vl;
8003 struct DVPathEntryP *dhops = sign_dhp_cls->dhops;
8004 uint16_t nhops = sign_dhp_cls->nhops;
8005 const struct GNUNET_PeerIdentity *next_hop = sign_dhp_cls->next_hop;
8006 struct TransportDVLearnMessage *fwd = sign_dhp_cls->fwd;
8007 struct Neighbour *n;
8008
8009 sign_dhp_cls->pr->op = NULL;
8012 sign_dhp_cls->pr);
8013 GNUNET_free (sign_dhp_cls->pr);
8014 dhops[nhops].hop_sig = *sig;
8015
8016 /*route_control_message_without_fc (next_hop,
8017 &fwd->header,
8018 RMO_UNCONFIRMED_ALLOWED);*/
8019 vl = lookup_virtual_link (next_hop);
8020 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
8021 {
8023 &fwd->header,
8025 }
8026 else
8027 {
8028 /* Use route via neighbour */
8029 n = lookup_neighbour (next_hop);
8030 if (NULL != n)
8032 n,
8033 &fwd->header,
8035 }
8036 GNUNET_free (sign_dhp_cls);
8037}

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

8058{
8059 struct DVPathEntryP *dhops;
8060 char buf[sizeof(struct TransportDVLearnMessage)
8061 + (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
8062 struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
8063 struct GNUNET_TIME_Relative nnd;
8064 const struct GNUNET_PeerIdentity *my_identity;
8065
8066 /* compute message for forwarding */
8068 "Forwarding DV learn message originating from %s to %s\n",
8069 GNUNET_i2s (&msg->initiator),
8070 GNUNET_i2s2 (next_hop));
8073 fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
8074 + (nhops + 1) * sizeof(struct DVPathEntryP));
8075 fwd->num_hops = htons (nhops + 1);
8076 fwd->bidirectional = htons (bi_history);
8079 msg->non_network_delay));
8081 fwd->init_sig = msg->init_sig;
8082 fwd->initiator = msg->initiator;
8083 fwd->challenge = msg->challenge;
8084 fwd->monotonic_time = msg->monotonic_time;
8085
8088
8089 dhops = (struct DVPathEntryP *) &fwd[1];
8090 GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
8091 dhops[nhops].hop = *my_identity;
8092 {
8093 struct DvHopPS dhp = {
8095 .purpose.size = htonl (sizeof(dhp)),
8096 .pred = (0 == nhops) ? msg->initiator : dhops[nhops - 1].hop,
8097 .succ = *next_hop,
8099 };
8100 struct SignDhpCls *sign_dhp_cls = GNUNET_new (struct SignDhpCls);
8101 sign_dhp_cls->dhops = dhops;
8102 sign_dhp_cls->nhops = nhops;
8103 sign_dhp_cls->next_hop = next_hop;
8104 sign_dhp_cls->fwd = fwd;
8105 sign_dhp_cls->pr = GNUNET_new (struct PilsRequest);
8108 sign_dhp_cls->pr);
8109 sign_dhp_cls->pr->op =
8111 &dhp.purpose,
8113 sign_dhp_cls);
8114 }
8115}

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

8133{
8134 struct DvInitPS ip = { .purpose.purpose = htonl (
8136 .purpose.size = htonl (sizeof(ip)),
8137 .monotonic_time = sender_monotonic_time,
8138 .challenge = *challenge };
8139
8140 if (
8141 GNUNET_OK !=
8143 &ip,
8144 init_sig,
8145 &init->public_key))
8146 {
8147 GNUNET_break_op (0);
8148 return GNUNET_SYSERR;
8149 }
8150 return GNUNET_OK;
8151}

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

8213{
8214 struct NeighbourSelectionContext *nsc = cls;
8215
8216 (void) value;
8217 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8218 return GNUNET_YES; /* skip initiator */
8219 for (unsigned int i = 0; i < nsc->nhops; i++)
8220 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8221 return GNUNET_YES;
8222 /* skip peers on path */
8223 nsc->num_eligible++;
8224 return GNUNET_YES;
8225}

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

8242{
8243 struct NeighbourSelectionContext *nsc = cls;
8244
8246 "transmission %s\n",
8247 GNUNET_i2s (pid));
8248 (void) value;
8249 if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
8250 return GNUNET_YES; /* skip initiator */
8251 for (unsigned int i = 0; i < nsc->nhops; i++)
8252 if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
8253 return GNUNET_YES;
8254 /* skip peers on path */
8255 for (unsigned int i = 0; i < nsc->num_selections; i++)
8256 {
8257 if (nsc->selections[i] == nsc->num_eligible)
8258 {
8260 nsc->dvl,
8261 nsc->bi_history,
8262 nsc->nhops,
8263 nsc->hops,
8264 nsc->in_time);
8265 break;
8266 }
8267 }
8268 nsc->num_eligible++;
8269 return GNUNET_YES;
8270}

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

8320{
8321 double target_total = 50.0; /* FIXME: use LOG(NSE)? */
8322 double eligible_ratio =
8323 ((double) eligible_count) / ((double) neighbour_count);
8324 double boost_factor = eligible_ratio * eligible_ratio;
8325 unsigned int rnd;
8326 double left;
8327
8328 if (hops_taken >= 64)
8329 {
8330 GNUNET_break (0);
8331 return 0; /* precaution given bitshift below */
8332 }
8333 for (unsigned int i = 1; i < hops_taken; i++)
8334 {
8335 /* For each hop, subtract the expected number of targets
8336 reached at distance d (so what remains divided by 2^d) */
8337 target_total -= (target_total * boost_factor / (1LLU << i));
8338 }
8339 rnd =
8340 (unsigned int) floor (target_total * boost_factor / (1LLU << hops_taken));
8341 /* round up or down probabilistically depending on how close we were
8342 when floor()ing to rnd */
8343 left = target_total - (double) rnd;
8344 if (UINT32_MAX * left >
8346 rnd++; /* round up */
8348 "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
8349 hops_taken,
8350 rnd,
8351 eligible_count,
8352 neighbour_count);
8353 return rnd;
8354}

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

Referenced by handle_dv_learn().

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

◆ neighbour_store_dvmono_cb()

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

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

Parameters
clsa struct Neighbour
successGNUNET_YES if peerstore was successful

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

8365{
8366 struct Neighbour *n = cls;
8367
8368 n->sc = NULL;
8369 if (GNUNET_YES != success)
8371 "Failed to store other peer's monotonic time in peerstore!\n");
8372}

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

8377{
8378 struct GNUNET_TIME_Relative host_latency_sum;
8379 struct GNUNET_TIME_Relative latency;
8380 struct GNUNET_TIME_Relative network_latency;
8381 uint16_t nhops = ntohs (dvl->num_hops);;
8382
8383 /* We initiated this, learn the forward path! */
8384 host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
8385
8386 // Need also something to lookup initiation time
8387 // to compute RTT! -> add RTT argument here?
8389 dvl->monotonic_time));
8390 GNUNET_assert (latency.rel_value_us >= host_latency_sum.rel_value_us);
8391 // latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
8392 // (based on dvl->challenge, we can identify time of origin!)
8393
8394 network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
8395 /* assumption: latency on all links is the same */
8396 network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
8397
8398 return network_latency;
8399}

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

8411{
8412 struct CommunicatorMessageContext *cmc = cls;
8414 int bi_hop;
8415 uint16_t nhops;
8416 uint16_t bi_history;
8417 const struct DVPathEntryP *hops;
8418 int do_fwd;
8419 int did_initiator;
8420 struct GNUNET_TIME_Absolute in_time;
8421 struct Neighbour *n;
8422 const struct GNUNET_PeerIdentity *my_identity;
8423
8424 nhops = ntohs (dvl->num_hops); /* 0 = sender is initiator */
8425 bi_history = ntohs (dvl->bidirectional);
8426 hops = (const struct DVPathEntryP *) &dvl[1];
8427 if (0 == nhops)
8428 {
8429 /* sanity check */
8430 if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
8431 {
8432 GNUNET_break (0);
8433 finish_cmc_handling (cmc);
8434 return;
8435 }
8436 }
8437 else
8438 {
8440 "handle dv learn message last hop %s\n",
8441 GNUNET_i2s (&hops[nhops - 1].hop));
8442 /* sanity check */
8443 if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
8444 {
8445 GNUNET_break (0);
8446 finish_cmc_handling (cmc);
8447 return;
8448 }
8449 }
8450
8452 cc = cmc->tc->details.communicator.cc;
8453 bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
8454 cc); // FIXME: add bi-directional flag to cc?
8455 in_time = GNUNET_TIME_absolute_get ();
8456
8457 /* continue communicator here, everything else can happen asynchronous! */
8458 finish_cmc_handling (cmc);
8459
8460 n = lookup_neighbour (&dvl->initiator);
8461 if (NULL != n)
8462 {
8463 if ((n->dv_monotime_available == GNUNET_YES) &&
8466 {
8468 "DV learn from %s discarded due to time travel",
8469 GNUNET_i2s (&dvl->initiator));
8471 "# DV learn discarded due to time travel",
8472 1,
8473 GNUNET_NO);
8474 return;
8475 }
8477 &dvl->initiator,
8478 &dvl->challenge,
8479 &dvl->init_sig))
8480 {
8482 "DV learn signature from %s invalid\n",
8483 GNUNET_i2s (&dvl->initiator));
8484 GNUNET_break_op (0);
8485 return;
8486 }
8489 {
8490 if (NULL != n->sc)
8491 {
8493 "store cancel\n");
8495 }
8496 n->sc =
8498 "transport",
8499 &dvl->initiator,
8501 &dvl->monotonic_time,
8502 sizeof(dvl->monotonic_time),
8506 n);
8507 }
8508 }
8509
8512
8513 /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
8514 If signature verification load too high, implement random drop strategy */
8515 for (unsigned int i = 0; i < nhops; i++)
8516 {
8517 struct DvHopPS dhp = { .purpose.purpose =
8519 .purpose.size = htonl (sizeof(dhp)),
8520 .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
8521 .succ = (nhops == i + 1) ? *my_identity
8522 : hops[i + 1].hop,
8523 .challenge = dvl->challenge };
8524
8525 if (GNUNET_OK !=
8527 &dhp,
8528 &hops[i].hop_sig,
8529 &hops[i].hop.public_key))
8530 {
8532 "DV learn from %s signature of hop %u invalid\n",
8533 GNUNET_i2s (&dvl->initiator),
8534 i);
8536 "signature of hop %s invalid\n",
8537 GNUNET_i2s (&hops[i].hop));
8539 "pred %s\n",
8540 GNUNET_i2s (&dhp.pred));
8542 "succ %s\n",
8543 GNUNET_i2s (&dhp.succ));
8545 "hash %s\n",
8546 GNUNET_sh2s (&dhp.challenge.value));
8547 GNUNET_break_op (0);
8548 return;
8549 }
8550 }
8551 if (GNUNET_EXTRA_LOGGING > 0)
8552 {
8553 char *path;
8554
8555 path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
8556 for (unsigned int i = 0; i < nhops; i++)
8557 {
8558 char *tmp;
8559
8560 GNUNET_asprintf (&tmp,
8561 "%s%s%s",
8562 path,
8563 (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
8564 GNUNET_i2s (&hops[i].hop));
8565 GNUNET_free (path);
8566 path = tmp;
8567 }
8569 "Received DVInit via %s%s%s\n",
8570 path,
8571 bi_hop ? "<->" : "-->",
8573 GNUNET_free (path);
8574 }
8575 do_fwd = GNUNET_YES;
8576 if (0 == GNUNET_memcmp (my_identity, &dvl->initiator))
8577 {
8578 struct GNUNET_PeerIdentity path[nhops + 1];
8579 struct GNUNET_TIME_Relative network_latency;
8580
8581 /* We initiated this, learn the forward path! */
8582 path[0] = *my_identity;
8583 path[1] = hops[0].hop;
8584
8585 network_latency = get_network_latency (dvl);
8586
8587 for (unsigned int i = 2; i <= nhops; i++)
8588 {
8589 struct GNUNET_TIME_Relative ilat;
8590
8591 /* assumption: linear latency increase per hop */
8592 ilat = GNUNET_TIME_relative_multiply (network_latency, i);
8593 path[i] = hops[i - 1].hop;
8595 "Learned path with %u hops to %s with latency %s\n",
8596 i,
8597 GNUNET_i2s (&path[i]),
8599 learn_dv_path (path,
8600 i + 1,
8601 ilat,
8604 }
8605 /* as we initiated, do not forward again (would be circular!) */
8606 do_fwd = GNUNET_NO;
8607 return;
8608 }
8609 if (bi_hop)
8610 {
8611 /* last hop was bi-directional, we could learn something here! */
8612 struct GNUNET_PeerIdentity path[nhops + 2];
8613 struct GNUNET_TIME_Relative ilat;
8614 struct GNUNET_TIME_Relative network_latency;
8615
8616 path[0] = *my_identity;
8617 path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
8618 for (unsigned int i = 0; i < nhops; i++)
8619 {
8620 int iret;
8621
8622 if (0 == (bi_history & (1 << i)))
8623 break; /* i-th hop not bi-directional, stop learning! */
8624 if (i == nhops - 1)
8625 {
8626 path[i + 2] = dvl->initiator;
8627 }
8628 else
8629 {
8630 path[i + 2] = hops[nhops - i - 2].hop;
8631 }
8632
8634 "Learned inverse path with %u hops to %s\n",
8635 i + 2,
8636 GNUNET_i2s (&path[i + 2]));
8637 network_latency = get_network_latency (dvl);
8638 ilat = GNUNET_TIME_relative_multiply (network_latency, i + 2);
8639 iret = learn_dv_path (path,
8640 i + 3,
8641 ilat,
8644 if (GNUNET_SYSERR == iret)
8645 {
8646 /* path invalid or too long to be interesting for US, thus should also
8647 not be interesting to our neighbours, cut path when forwarding to
8648 'i' hops, except of course for the one that goes back to the
8649 initiator */
8651 "# DV learn not forwarded due invalidity of path",
8652 1,
8653 GNUNET_NO);
8654 do_fwd = GNUNET_NO;
8655 break;
8656 }
8657 if ((GNUNET_NO == iret) && (nhops == i + 1))
8658 {
8659 /* we have better paths, and this is the longest target,
8660 so there cannot be anything interesting later */
8662 "# DV learn not forwarded, got better paths",
8663 1,
8664 GNUNET_NO);
8665 do_fwd = GNUNET_NO;
8666 break;
8667 }
8668 }
8669 }
8670 if (MAX_DV_HOPS_ALLOWED == nhops)
8671 {
8672 /* At limit, we're out of here! */
8673 return;
8674 }
8675
8676 /* Forward to initiator, if path non-trivial and possible */
8677 bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
8678 did_initiator = GNUNET_NO;
8679 if ((1 <= nhops) &&
8680 (GNUNET_YES ==
8682 {
8683 /* send back to origin! */
8685 "Sending DVL back to initiator %s\n",
8686 GNUNET_i2s (&dvl->initiator));
8687 forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
8688 did_initiator = GNUNET_YES;
8689 }
8690 /* We forward under two conditions: either we still learned something
8691 ourselves (do_fwd), or the path was darn short and thus the initiator is
8692 likely to still be very interested in this (and we did NOT already
8693 send it back to the initiator) */
8694 if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
8695 (GNUNET_NO == did_initiator)))
8696 {
8697 /* Pick random neighbours that are not yet on the path */
8698 struct NeighbourSelectionContext nsc;
8699 unsigned int n_cnt;
8700
8702 nsc.nhops = nhops;
8703 nsc.dvl = dvl;
8704 nsc.bi_history = bi_history;
8705 nsc.hops = hops;
8706 nsc.in_time = in_time;
8707 nsc.num_eligible = 0;
8710 &nsc);
8711 if (0 == nsc.num_eligible)
8712 return; /* done here, cannot forward to anyone else */
8713 nsc.num_selections = calculate_fork_degree (nhops, n_cnt, nsc.num_eligible);
8714 nsc.num_selections =
8715 GNUNET_MIN (MAX_DV_DISCOVERY_SELECTION, nsc.num_selections);
8717 "Forwarding DVL to %u other peers\n",
8718 nsc.num_selections);
8719 for (unsigned int i = 0; i < nsc.num_selections; i++)
8720 nsc.selections[i] =
8721 (nsc.num_selections == n_cnt)
8722 ? i /* all were selected, avoid collisions by chance */
8724 nsc.num_eligible = 0;
8727 &nsc);
8728 }
8729}

References GNUNET_TIME_Absolute::abs_value_us, ADDRESS_VALIDATION_LIFETIME, NeighbourSelectionContext::bi_history, TransportDVLearnMessage::bidirectional, calculate_fork_degree(), TransportClient::cc, DvHopPS::challenge, TransportDVLearnMessage::challenge, TransportClient::communicator, CT_COMMUNICATOR, TransportClient::details, Neighbour::dv_monotime_available, dv_neighbour_selection(), dv_neighbour_transmission(), NeighbourSelectionContext::dvl, finish_cmc_handling(), forward_dv_learn(), get_network_latency(), GNUNET_asprintf(), GNUNET_assert, GNUNET_break, GNUNET_break_op, GNUNET_CONTAINER_multipeermap_contains(), GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_CONTAINER_multipeermap_size(), GNUNET_CRYPTO_eddsa_verify, GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u32(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_EXTRA_LOGGING, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_memcmp, GNUNET_MIN, GNUNET_NO, GNUNET_OK, GNUNET_PEERSTORE_store(), GNUNET_PEERSTORE_store_cancel(), GNUNET_PEERSTORE_STOREOPTION_REPLACE, GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME, GNUNET_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 8740 of file gnunet-service-transport.c.

8741{
8742 uint16_t size = ntohs (dvb->header.size);
8743 uint16_t num_hops = ntohs (dvb->num_hops);
8744 const struct GNUNET_PeerIdentity *hops =
8745 (const struct GNUNET_PeerIdentity *) &dvb[1];
8746 const struct GNUNET_PeerIdentity *my_identity;
8747
8748 (void) cls;
8749 if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
8750 + sizeof(struct GNUNET_MessageHeader))
8751 {
8752 GNUNET_break_op (0);
8753 return GNUNET_SYSERR;
8754 }
8755
8758
8759 /* This peer must not be on the path */
8760 for (unsigned int i = 0; i < num_hops; i++)
8761 if (0 == GNUNET_memcmp (&hops[i], my_identity))
8762 {
8763 GNUNET_break_op (0);
8764 return GNUNET_SYSERR;
8765 }
8766 return GNUNET_YES;
8767}

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

8790{
8791 struct VirtualLink *vl = next_hop->vl;
8792 struct PendingMessage *pm;
8793 size_t msg_size = sizeof(struct TransportDVBoxMessage)
8794 + num_hops * sizeof(struct GNUNET_PeerIdentity)
8795 + enc_payload_size;
8796 char *buf;
8797 char msg_buf[msg_size] GNUNET_ALIGN;
8798 struct GNUNET_PeerIdentity *dhops;
8799
8800 hdr->num_hops = htons (num_hops);
8801 hdr->total_hops = htons (total_hops);
8802 hdr->header.size = htons (msg_size);
8803 memcpy (msg_buf, hdr, sizeof(*hdr));
8804 dhops = (struct GNUNET_PeerIdentity *) &msg_buf[sizeof(struct
8806 ;
8807 memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
8808 memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
8809
8810 if (GNUNET_YES == ntohs (hdr->without_fc))
8811 {
8813 "Forwarding control message (payload size %u) in DV Box to next hop %s (%u/%u) \n",
8814 enc_payload_size,
8815 GNUNET_i2s (&next_hop->pid),
8816 (unsigned int) num_hops,
8817 (unsigned int) total_hops);
8818 route_via_neighbour (next_hop, (const struct
8819 GNUNET_MessageHeader *) msg_buf,
8821 }
8822 else
8823 {
8824 pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
8826 "2 created pm %p storing vl %p \n",
8827 pm,
8828 vl);
8829 pm->pmt = PMT_DV_BOX;
8830 pm->vl = vl;
8831 pm->target = next_hop->pid;
8833 pm->logging_uuid = logging_uuid_gen++;
8835 pm->bytes_msg = msg_size;
8836 buf = (char *) &pm[1];
8837 memcpy (buf, msg_buf, msg_size);
8838
8840 "Created pending message %" PRIu64
8841 " for DV Box with next hop %s (%u/%u)\n",
8842 pm->logging_uuid,
8843 GNUNET_i2s (&next_hop->pid),
8844 (unsigned int) num_hops,
8845 (unsigned int) total_hops);
8846
8847 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
8848 {
8850 vl->pending_msg_head,
8851 vl->pending_msg_tail,
8852 pm);
8853
8855 }
8856 else
8857 {
8859 "The virtual link is not ready for forwarding a DV Box with payload, storing PendingMessage in ring buffer.\n");
8860
8862 {
8864
8865 GNUNET_free (pm_old);
8866 }
8869 {
8872 }
8873 else
8875
8877 "%u items stored in DV ring buffer\n",
8880 }
8881 }
8882}

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

8892{
8893 if (NULL != b->get)
8894 {
8896 b->get = NULL;
8897 GNUNET_assert (NULL != b->cmc);
8899 b->cmc = NULL;
8900 }
8901 if (NULL != b->task)
8902 {
8904 b->task = NULL;
8905 }
8906 if (NULL != b->sc)
8907 {
8909 "store cancel\n");
8911 b->sc = NULL;
8912 }
8914 "Removing backtalker for %s\n",
8915 GNUNET_i2s (&b->pid));
8917 GNUNET_YES ==
8919 GNUNET_free (b);
8920}

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

8935{
8936 struct Backtalker *b = value;
8937
8938 (void) cls;
8939 (void) pid;
8940 free_backtalker (b);
8941 return GNUNET_OK;
8942}

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

8952{
8953 struct Backtalker *b = cls;
8954
8956 "backtalker timeout.\n");
8957 b->task = NULL;
8959 {
8961 return;
8962 }
8963 GNUNET_assert (NULL == b->sc);
8964 free_backtalker (b);
8965}

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

8980{
8981 struct Backtalker *b = cls;
8982 struct GNUNET_TIME_AbsoluteNBO *mtbe;
8983 struct GNUNET_TIME_Absolute mt;
8984
8985 (void) emsg;
8986 if (NULL == record)
8987 {
8988 /* we're done with #backtalker_monotime_cb() invocations,
8989 continue normal processing */
8990 b->get = NULL;
8991 GNUNET_assert (NULL != b->cmc);
8992 b->cmc->mh = (const struct GNUNET_MessageHeader *) &b[1];
8993 if (0 != b->body_size)
8995 else
8997 b->cmc = NULL;
8998 return;
8999 }
9000 if (sizeof(*mtbe) != record->value_size)
9001 {
9003 GNUNET_break (0);
9004 return;
9005 }
9006 mtbe = record->value;
9007 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
9008 if (mt.abs_value_us > b->monotonic_time.abs_value_us)
9009 {
9011 "Backtalker message from %s dropped, monotime in the past\n",
9012 GNUNET_i2s (&b->pid));
9014 GST_stats,
9015 "# Backchannel messages dropped: monotonic time not increasing",
9016 1,
9017 GNUNET_NO);
9018 b->monotonic_time = mt;
9019 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
9020 */
9021 b->body_size = 0;
9022 }
9024}

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

9036{
9037 struct Backtalker *b = cls;
9038
9039 if (GNUNET_OK != success)
9040 {
9042 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
9043 }
9044 b->sc = NULL;
9045 if (NULL != b->task)
9046 {
9048 b->task = NULL;
9049 }
9051}

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

9061{
9062 struct GNUNET_TIME_AbsoluteNBO mtbe;
9063
9064 if (NULL != b->sc)
9065 {
9067 "store cancel before store with sc %p\n",
9068 b->sc);
9069 /*GNUNET_PEERSTORE_store_cancel (b->sc);
9070 b->sc = NULL;*/
9072 "store cancel before store with sc %p is null\n",
9073 b->sc);
9074 }
9075 else
9076 {
9078 b->task = NULL;
9079 }
9081 b->sc =
9083 "transport",
9084 &b->pid,
9086 &mtbe,
9087 sizeof(mtbe),
9091 b);
9092}

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

9105{
9106 struct DecapsDvBoxCls *decaps_dv_box_cls = cls;
9107 struct CommunicatorMessageContext *cmc = decaps_dv_box_cls->cmc;
9108 const struct TransportDVBoxMessage *dvb = decaps_dv_box_cls->dvb;
9109 struct DVKeyState key;
9110 const char *hdr;
9111 size_t hdr_len;
9112 struct GNUNET_HashCode hmac;
9113
9114 decaps_dv_box_cls->pr->op = NULL;
9117 decaps_dv_box_cls->pr);
9118 GNUNET_free (decaps_dv_box_cls->pr);
9119 if (NULL == km)
9120 {
9121 GNUNET_break_op (0);
9122 finish_cmc_handling (cmc);
9123 return;
9124 }
9125 dv_setup_key_state_from_km (km, &dvb->iv, &key);
9126 hdr = (const char *) &dvb[1];
9127 hdr_len = ntohs (dvb->orig_size) - sizeof(*dvb) - sizeof(struct
9129 * ntohs (dvb->total_hops);
9130
9131 dv_hmac (&key, &hmac, hdr, hdr_len);
9132 if (0 != GNUNET_memcmp (&hmac, &dvb->hmac))
9133 {
9134 /* HMAC mismatch, discard! */
9135 GNUNET_break_op (0);
9136 finish_cmc_handling (cmc);
9137 return;
9138 }
9139 /* begin actual decryption */
9140 {
9141 struct Backtalker *b;
9142 struct GNUNET_TIME_Absolute monotime;
9143 struct TransportDVBoxPayloadP ppay = { 0 };
9144 char body[hdr_len - sizeof(ppay)] GNUNET_ALIGN;
9145 const struct GNUNET_MessageHeader *mh;
9146
9147 GNUNET_assert (hdr_len >=
9148 sizeof(ppay) + sizeof(struct GNUNET_MessageHeader));
9149 if (GNUNET_OK != dv_decrypt (&key, &ppay, hdr, sizeof(ppay)))
9150 {
9152 "Error decrypting DV payload header\n");
9153 GNUNET_break_op (0);
9154 finish_cmc_handling (cmc);
9155 return;
9156 }
9157 if (GNUNET_OK != dv_decrypt (&key, body,
9158 &hdr[sizeof(ppay)], hdr_len - sizeof(ppay)))
9159 {
9161 "Error decrypting DV payload\n");
9162 GNUNET_break_op (0);
9163 finish_cmc_handling (cmc);
9164 return;
9165 }
9166 mh = (const struct GNUNET_MessageHeader *) body;
9167 dv_key_clean (&key);
9168 if (ntohs (mh->size) != sizeof(body))
9169 {
9170 GNUNET_break_op (0);
9171 finish_cmc_handling (cmc);
9172 return;
9173 }
9174 /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
9175 switch (ntohs (mh->type))
9176 {
9178 GNUNET_break_op (0);
9179 finish_cmc_handling (cmc);
9180 return;
9181
9183 GNUNET_break_op (0);
9184 finish_cmc_handling (cmc);
9185 return;
9186
9187 default:
9188 /* permitted, continue */
9189 break;
9190 }
9191 monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time);
9193 "Decrypted backtalk from %s\n",
9194 GNUNET_i2s (&ppay.sender));
9196 if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
9197 {
9199 GST_stats,
9200 "# Backchannel messages dropped: monotonic time not increasing",
9201 1,
9202 GNUNET_NO);
9203 finish_cmc_handling (cmc);
9204 return;
9205 }
9206 if ((NULL == b) ||
9207 (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
9208 {
9209 /* Check signature */
9210 const struct GNUNET_PeerIdentity *my_identity;
9211 struct EphemeralConfirmationPS ec;
9212
9215
9216 ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL);
9217 ec.target = *my_identity;
9218 ec.ephemeral_key = dvb->ephemeral_key;
9219 ec.purpose.size = htonl (sizeof(ec));
9220 ec.sender_monotonic_time = ppay.monotonic_time;
9221 if (
9222 GNUNET_OK !=
9225 &ec,
9226 &ppay.sender_sig,
9227 &ppay.sender.public_key))
9228 {
9229 /* Signature invalid, discard! */
9230 GNUNET_break_op (0);
9231 finish_cmc_handling (cmc);
9232 return;
9233 }
9234 }
9235 /* Update sender, we now know the real origin! */
9237 "DVBox received for me from %s via %s\n",
9238 GNUNET_i2s2 (&ppay.sender),
9239 GNUNET_i2s (&cmc->im.sender));
9240 cmc->im.sender = ppay.sender;
9241
9242 if (NULL != b)
9243 {
9244 /* update key cache and mono time */
9245 b->last_ephemeral = dvb->ephemeral_key;
9246 b->monotonic_time = monotime;
9248 b->timeout =
9250 cmc->mh = mh;
9252 return;
9253 }
9254 /* setup data structure to cache signature AND check
9255 monotonic time with PEERSTORE before forwarding backchannel payload */
9256 b = GNUNET_malloc (sizeof(struct Backtalker) + sizeof(body));
9257 b->pid = ppay.sender;
9258 b->body_size = sizeof(body);
9259 memcpy (&b[1], body, sizeof(body));
9263 &b->pid,
9264 b,
9266 b->monotonic_time = monotime; /* NOTE: to be checked still! */
9267 b->cmc = cmc;
9268 b->timeout =
9271 b->get =
9273 "transport",
9274 &b->pid,
9277 b);
9278 } /* end actual decryption */
9279}

References GNUNET_TIME_Absolute::abs_value_us, BACKCHANNEL_INACTIVITY_TIMEOUT, backtalker_monotime_cb(), backtalker_timeout_cb(), backtalkers, Backtalker::body_size, Backtalker::cmc, DecapsDvBoxCls::cmc, demultiplex_with_cmc(), dv_decrypt(), dv_hmac(), dv_key_clean(), dv_setup_key_state_from_km(), DecapsDvBoxCls::dvb, EphemeralConfirmationPS::ephemeral_key, TransportDVBoxMessage::ephemeral_key, finish_cmc_handling(), Backtalker::get, GNUNET_ALIGN, GNUNET_assert, GNUNET_break_op, GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multipeermap_get(), GNUNET_CONTAINER_multipeermap_put(), GNUNET_CRYPTO_eddsa_verify, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_i2s(), GNUNET_i2s2(), GNUNET_log, GNUNET_malloc, GNUNET_memcmp, GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX, GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN, GNUNET_NO, GNUNET_OK, GNUNET_PEERSTORE_iteration_start(), GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME, GNUNET_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, TransportDVBoxMessage::hmac, CommunicatorMessageContext::im, TransportDVBoxMessage::iv, key, Backtalker::last_ephemeral, 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 9290 of file gnunet-service-transport.c.

9291{
9292 struct CommunicatorMessageContext *cmc = cls;
9293 uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
9294 uint16_t num_hops = ntohs (dvb->num_hops);
9295 const struct GNUNET_PeerIdentity *hops =
9296 (const struct GNUNET_PeerIdentity *) &dvb[1];
9297 const char *enc_payload = (const char *) &hops[num_hops];
9298 uint16_t enc_payload_size =
9299 size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
9300 struct DecapsDvBoxCls *decaps_dv_box_cls;
9301 const struct GNUNET_PeerIdentity *my_identity;
9302
9305
9306 if (GNUNET_EXTRA_LOGGING > 0)
9307 {
9308 char *path;
9309
9311 for (unsigned int i = 0; i < num_hops; i++)
9312 {
9313 char *tmp;
9314
9315 GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
9316 GNUNET_free (path);
9317 path = tmp;
9318 }
9320 "Received DVBox with remaining path %s\n",
9321 path);
9322 GNUNET_free (path);
9323 }
9324
9325 if (num_hops > 0)
9326 {
9327 /* We're trying from the end of the hops array, as we may be
9328 able to find a shortcut unknown to the origin that way */
9329 for (int i = num_hops - 1; i >= 0; i--)
9330 {
9331 struct Neighbour *n;
9332
9333 if (0 == GNUNET_memcmp (&hops[i], my_identity))
9334 {
9335 GNUNET_break_op (0);
9336 finish_cmc_handling (cmc);
9337 return;
9338 }
9339 n = lookup_neighbour (&hops[i]);
9340 if (NULL == n)
9341 continue;
9343 "Skipping %u/%u hops ahead while routing DV Box\n",
9344 i,
9345 num_hops);
9346
9347 forward_dv_box (n,
9348 (struct TransportDVBoxMessage *) dvb,
9349 ntohs (dvb->total_hops) + 1,
9350 num_hops - i - 1, /* number of hops left */
9351 &hops[i + 1], /* remaining hops */
9352 enc_payload,
9353 enc_payload_size);
9355 "# DV hops skipped routing boxes",
9356 i,
9357 GNUNET_NO);
9359 "# DV boxes routed (total)",
9360 1,
9361 GNUNET_NO);
9362 finish_cmc_handling (cmc);
9363 return;
9364 }
9365 /* Woopsie, next hop not in neighbours, drop! */
9367 "# DV Boxes dropped: next hop unknown",
9368 1,
9369 GNUNET_NO);
9370 finish_cmc_handling (cmc);
9371 return;
9372 }
9373 /* We are the target. Unbox and handle message. */
9375 "# DV boxes opened (ultimate target)",
9376 1,
9377 GNUNET_NO);
9378 cmc->total_hops = ntohs (dvb->total_hops);
9379
9380 {
9381 // DH key derivation with received DV, could be garbage.
9382 decaps_dv_box_cls = GNUNET_new (struct DecapsDvBoxCls);
9383 decaps_dv_box_cls->cmc = cmc;
9384 decaps_dv_box_cls->dvb = dvb;
9385 decaps_dv_box_cls->pr = GNUNET_new (struct PilsRequest);
9386
9389 decaps_dv_box_cls->pr);
9390 decaps_dv_box_cls->pr->op = GNUNET_PILS_kem_decaps (pils,
9391 &dvb->ephemeral_key,
9393 decaps_dv_box_cls);
9394 }
9395 // TODO keep track of cls and potentially clean
9396}

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

9409{
9410 struct TransportClient *tc = cls;
9411
9412 if (CT_COMMUNICATOR != tc->type)
9413 {
9414 GNUNET_break (0);
9415 return GNUNET_SYSERR;
9416 }
9418 return GNUNET_OK;
9419}

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

9452{
9453 struct CheckKnownAddressContext *ckac = cls;
9454 struct ValidationState *vs = value;
9455
9456 (void) pid;
9457 if (0 != strcmp (vs->address, ckac->address))
9458 return GNUNET_OK;
9459 ckac->vs = vs;
9460 return GNUNET_NO;
9461}

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

12121{
12122 struct ValidationState *vs;
12123 struct Queue *q;
12125 GST_cfg);
12126
12127 (void) cls;
12128 validation_task = NULL;
12130 /* drop validations past their expiration */
12131 while (
12132 (NULL != vs) &&
12134 {
12136 "Validation response %s cleaned up\n",
12137 GNUNET_sh2s (&vs->challenge.value));
12140 }
12141 if (NULL == vs)
12142 {
12144 "Address validation task not scheduled anymore, nothing to do\n");
12145 return; /* woopsie, no more addresses known, should only
12146 happen if we're really a lonely peer */
12147 }
12148 q = find_queue (&vs->pid, vs->address);
12149 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, >, now))
12150 {
12152 "To early to start next address validation for challenge %s\n",
12153 GNUNET_sh2s (&vs->challenge.value));
12154 return;
12155 }
12156 if (NULL == q)
12157 {
12158 vs->awaiting_queue = GNUNET_YES;
12159 suggest_to_connect (&vs->pid, vs->address);
12160 }
12161 else
12163 /* Finally, reschedule next attempt */
12164 vs->challenge_backoff =
12165 GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
12168 "Address validation task will run again in %s\n",
12169 GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
12170 GNUNET_YES));
12173 vs->challenge_backoff));
12174}

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

9483{
9485
9486 if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
9487 return; /* be lazy */
9488 vs->next_challenge = new_time;
9489 if (NULL == vs->hn)
9490 vs->hn =
9492 else
9495 (NULL != validation_task))
9496 return;
9497 if (NULL != validation_task)
9499 /* randomize a bit */
9502 MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
9503 new_time = GNUNET_TIME_absolute_add (new_time, delta);
9506}

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

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

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

◆ start_address_validation()

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

Start address validation.

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

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

9518{
9519 struct GNUNET_TIME_Absolute now;
9520 struct ValidationState *vs;
9521 struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
9522
9524 pid,
9526 &ckac);
9527 if (NULL != (vs = ckac.vs))
9528 {
9529 /* if 'vs' is not currently valid, we need to speed up retrying the
9530 * validation */
9531 if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
9532 {
9533 /* reduce backoff as we got a fresh advertisement */
9534 vs->challenge_backoff =
9537 vs->challenge_backoff,
9538 2));
9541 vs->challenge_backoff));
9542 }
9543 return;
9544 }
9546 vs = GNUNET_new (struct ValidationState);
9547 vs->pid = *pid;
9548 vs->valid_until =
9550 vs->first_challenge_use = now;
9551 vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
9553 &vs->challenge,
9554 sizeof(vs->challenge));
9555 vs->address = GNUNET_strdup (address);
9556 GNUNET_CRYPTO_hash (vs->address, strlen (vs->address), &vs->hc);
9558 "Starting address validation `%s' of peer %s using challenge %s\n",
9559 address,
9560 GNUNET_i2s (pid),
9561 GNUNET_sh2s (&vs->challenge.value));
9565 &vs->pid,
9566 vs,
9569}

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

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

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

◆ find_queue()

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

Find the queue matching pid and address.

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

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

9896{
9897 struct Neighbour *n;
9898
9899 n = lookup_neighbour (pid);
9900 if (NULL == n)
9901 return NULL;
9902 for (struct Queue *pos = n->queue_head; NULL != pos;
9903 pos = pos->next_neighbour)
9904 {
9905 if (0 == strcmp (pos->address, address))
9906 return pos;
9907 }
9908 return NULL;
9909}

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

12017{
12018 static uint32_t idgen = 0;
12019 struct TransportClient *tc;
12020 char *prefix;
12021 struct GNUNET_TRANSPORT_CreateQueue *cqm;
12022 struct GNUNET_MQ_Envelope *env;
12023 size_t alen;
12024
12026 if (NULL == prefix)
12027 {
12028 GNUNET_break (0); /* We got an invalid address!? */
12029 return;
12030 }
12032 if (NULL == tc)
12033 {
12035 "# Suggestions ignored due to missing communicator",
12036 1,
12037 GNUNET_NO);
12039 "Cannot connect to %s at `%s', no matching communicator present\n",
12040 GNUNET_i2s (pid),
12041 address);
12043 return;
12044 }
12045 /* forward suggestion for queue creation to communicator */
12047 "Request #%u for `%s' communicator to create queue to `%s' at `%s'\n",
12048 (unsigned int) idgen,
12049 prefix,
12050 GNUNET_i2s (pid),
12051 address);
12053 alen = strlen (address) + 1;
12054 env =
12056 cqm->request_id = htonl (idgen++);
12057 cqm->receiver = *pid;
12058 memcpy (&cqm[1], address, alen);
12059 GNUNET_MQ_send (tc->mq, env);
12060}

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

9584{
9585 struct Queue *q;
9586 int pfx_len;
9587 const char *eou;
9588 char *address;
9589 (void) cls;
9590
9591 eou = strstr (uri,
9592 "://");
9593 pfx_len = eou - uri;
9594 eou += 3;
9596 "%.*s-%s",
9597 pfx_len,
9598 uri,
9599 eou);
9600
9602 "helo for client %s\n",
9603 address);
9604 q = find_queue (pid, address);
9605 if (NULL == q)
9606 {
9608 }
9609 else
9612}

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

9626{
9627 struct IncomingRequest *ir = cls;
9629 struct GNUNET_MessageHeader *hello;
9630 const struct GNUNET_PeerIdentity *my_identity;
9631
9632 if (NULL != emsg)
9633 {
9635 "Got failure from PEERSTORE: %s\n",
9636 emsg);
9637 return;
9638 }
9639 hello = record->value;
9642 if (0 == GNUNET_memcmp (&record->peer, my_identity))
9643 {
9645 return;
9646 }
9647 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
9650 NULL);
9651 GNUNET_HELLO_parser_free (parser);
9652}

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

9657{
9659 "Error in PEERSTORE monitoring\n");
9660}

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

9665{
9667 "Done with initial PEERSTORE iteration during monitoring\n");
9668}

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

9683{
9684 struct SignTValidationCls *sign_t_validation_cls = cls;
9685 struct CommunicatorMessageContext *cmc = sign_t_validation_cls->cmc;
9686 struct TransportValidationResponseMessage tvr = sign_t_validation_cls->tvr;
9687 struct VirtualLink *vl;
9688 struct Neighbour *n;
9689 struct IncomingRequest *ir;
9690 struct GNUNET_PeerIdentity sender;
9691
9692 sign_t_validation_cls->pr->op = NULL;
9695 sign_t_validation_cls->pr);
9696 GNUNET_free (sign_t_validation_cls->pr);
9697 tvr.signature = *sig;
9698 sender = cmc->im.sender;
9699 vl = lookup_virtual_link (&sender);
9700 if ((NULL != vl) && (GNUNET_YES == vl->confirmed))
9701 {
9702 // route_control_message_without_fc (&cmc->im.sender,
9704 &tvr.header,
9706 }
9707 else
9708 {
9709 /* Use route via neighbour */
9710 n = lookup_neighbour (&sender);
9711 if (NULL != n)
9712 route_via_neighbour (n, &tvr.header,
9715 }
9716
9717 finish_cmc_handling (cmc);
9718 if (NULL != vl)
9719 return;
9720
9721 /* For us, the link is still down, but we need bi-directional
9722 connections (for flow-control and for this to be useful for
9723 CORE), so we must try to bring the link up! */
9724
9725 /* (1) Check existing queues, if any, we may be lucky! */
9726 n = lookup_neighbour (&sender);
9727 if (NULL != n)
9728 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
9729 start_address_validation (&sender, q->address);
9730 /* (2) Also try to see if we have addresses in PEERSTORE for this peer
9731 we could use */
9732 for (ir = ir_head; NULL != ir; ir = ir->next)
9733 if (0 == GNUNET_memcmp (&ir->pid, &sender))
9734 return;
9735 /* we are already trying */
9736 ir = GNUNET_new (struct IncomingRequest);
9737 ir->pid = sender;
9739
9741 GNUNET_YES,
9742 "peerstore",
9743 NULL,
9746 NULL,
9748 NULL,
9750 ir);
9751 ir_total++;
9752 /* Bound attempts we do in parallel here, might otherwise get excessive */
9755};

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

9770{
9771 struct CommunicatorMessageContext *cmc = cls;
9772 struct TransportValidationResponseMessage tvr = { 0 };
9773 struct GNUNET_TIME_RelativeNBO validity_duration;
9774
9775 /* DV-routed messages are not allowed for validation challenges */
9776 if (cmc->total_hops > 0)
9777 {
9778 GNUNET_break_op (0);
9779 finish_cmc_handling (cmc);
9780 return;
9781 }
9782 validity_duration = cmc->im.expected_address_validity;
9784 "Received address validation challenge %s\n",
9785 GNUNET_sh2s (&tvc->challenge.value));
9786 /* If we have a virtual link, we use this mechanism to signal the
9787 size of the flow control window, and to allow the sender
9788 to ask for increases. If for us the virtual link is still down,
9789 we will always give a window size of zero. */
9790 tvr.header.type =
9792 tvr.header.size = htons (sizeof(tvr));
9793 tvr.reserved = htonl (0);
9794 tvr.challenge = tvc->challenge;
9795 tvr.origin_time = tvc->sender_time;
9796 tvr.validity_duration = validity_duration;
9797 {
9798 /* create signature */
9799 struct TransportValidationPS tvp = {
9801 .purpose.size = htonl (sizeof(tvp)),
9802 .validity_duration = validity_duration,
9803 .challenge = tvc->challenge
9804 };
9805 struct SignTValidationCls *sign_t_validation_cls;
9806
9807 sign_t_validation_cls = GNUNET_new (struct SignTValidationCls);
9808 sign_t_validation_cls->cmc = cmc;
9809 sign_t_validation_cls->tvr = tvr;
9810 sign_t_validation_cls->pr = GNUNET_new (struct PilsRequest);
9813 sign_t_validation_cls->pr);
9814 sign_t_validation_cls->pr->op =
9816 &tvp.purpose,
9818 sign_t_validation_cls);
9819 }
9820}

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

9853{
9854 struct CheckKnownChallengeContext *ckac = cls;
9855 struct ValidationState *vs = value;
9856
9857 (void) pid;
9858 if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
9859 return GNUNET_OK;
9860 ckac->vs = vs;
9861 return GNUNET_NO;
9862}

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

9874{
9875 struct ValidationState *vs = cls;
9876
9877 vs->sc = NULL;
9878 if (GNUNET_YES == success)
9879 return;
9881 "# Peerstore failed to store foreign address",
9882 1,
9883 GNUNET_NO);
9884}

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

12072{
12074 struct GNUNET_TIME_Absolute monotonic_time;
12075
12076 if (NULL != vs->revalidation_task)
12077 {
12078 GNUNET_SCHEDULER_cancel (vs->revalidation_task);
12079 vs->revalidation_task = NULL;
12080 }
12081 /*memcpy (&hkey,
12082 &hc,
12083 sizeof (hkey));*/
12085 "Remove key %s for address %s map size %u contains %u\n",
12086 GNUNET_h2s (&vs->hc),
12087 vs->address,
12090 &vs->hc));
12092
12094 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us ==
12095 vs->last_challenge_use.abs_value_us)
12096 {
12097 vs->first_challenge_use = monotonic_time;
12098 }
12099 vs->last_challenge_use = monotonic_time;
12100 tvc.header.type =
12102 tvc.header.size = htons (sizeof(tvc));
12103 tvc.reserved = htonl (0);
12104 tvc.challenge = vs->challenge;
12105 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
12107 "Sending address validation challenge %s to %s\n",
12108 GNUNET_sh2s (&tvc.challenge.value),
12109 GNUNET_i2s (&q->neighbour->pid));
12110 queue_send_msg (q, NULL, &tvc, sizeof(tvc));
12111}

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

9917{
9918 struct ValidationState *vs = cls;
9919 struct Queue *q;
9920 struct GNUNET_TIME_Absolute now;
9921
9922 vs->revalidation_task = NULL;
9923 q = find_queue (&vs->pid, vs->address);
9924 if (NULL == q)
9925 {
9926 now = GNUNET_TIME_absolute_get ();
9927 vs->awaiting_queue = GNUNET_YES;
9928 suggest_to_connect (&vs->pid, vs->address);
9930 }
9931 else
9933}

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

9941{
9942 (void) cls;
9944 "Key in revalidate map %s \n",
9945 GNUNET_h2s (key));
9946 return GNUNET_YES;
9947}

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

9962{
9963 struct CommunicatorMessageContext *cmc = cls;
9964 struct ValidationState *vs;
9965 struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
9966 .vs = NULL};
9967 struct GNUNET_TIME_Absolute origin_time;
9968 struct Queue *q;
9969 struct Neighbour *n;
9970 struct VirtualLink *vl;
9972 GST_cfg);
9973
9974 /* check this is one of our challenges */
9976 &cmc->im.sender,
9978 &ckac);
9979 if (NULL == (vs = ckac.vs))
9980 {
9981 /* This can happen simply if we 'forgot' the challenge by now,
9982 i.e. because we received the validation response twice */
9984 "# Validations dropped, challenge unknown",
9985 1,
9986 GNUNET_NO);
9988 "Validation response %s dropped, challenge unknown\n",
9989 GNUNET_sh2s (&tvr->challenge.value));
9990 finish_cmc_handling (cmc);
9991 return;
9992 }
9993
9994 /* sanity check on origin time */
9995 origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
9996 if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
9997 (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
9998 {
10000 "Diff first use %" PRIu64 " and last use %" PRIu64 "\n",
10001 vs->first_challenge_use.abs_value_us - origin_time.abs_value_us,
10002 origin_time.abs_value_us - vs->last_challenge_use.abs_value_us);
10003 GNUNET_break_op (0);
10004 finish_cmc_handling (cmc);
10005 return;
10006 }
10007
10008 {
10009 /* check signature */
10010 struct TransportValidationPS tvp = {
10012 .purpose.size = htonl (sizeof(tvp)),
10013 .validity_duration = tvr->validity_duration,
10014 .challenge = tvr->challenge
10015 };
10016
10017 if (
10018 GNUNET_OK !=
10020 &tvp,
10021 &tvr->signature,
10022 &cmc->im.sender.public_key))
10023 {
10024 GNUNET_break_op (0);
10025 finish_cmc_handling (cmc);
10026 return;
10027 }
10028 }
10029
10030 /* validity is capped by our willingness to keep track of the
10031 validation entry and the maximum the other peer allows */
10034 tvr->validity_duration),
10036 vs->validated_until =
10040 vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
10041 vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
10043 &vs->challenge,
10044 sizeof(vs->challenge));
10045 vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
10046 vs->validated_until,
10047 GNUNET_TIME_relative_multiply (vs->validation_rtt,
10049 if (GNUNET_TIME_absolute_cmp (vs->first_challenge_use, <, now))
10050 {
10052 "First challenge use is now %" PRIu64 " %s \n",
10053 vs->first_challenge_use.abs_value_us,
10054 GNUNET_sh2s (&vs->challenge.value));
10055 vs->first_challenge_use = now;
10056 }
10057 else
10059 "First challenge use is later %" PRIu64 " %s \n",
10060 vs->first_challenge_use.abs_value_us,
10061 GNUNET_sh2s (&vs->challenge.value));
10062 vs->last_challenge_use =
10063 GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
10064 update_next_challenge_time (vs, vs->first_challenge_use);
10066 "Validation response %s from %s accepted, address valid until %s\n",
10067 GNUNET_sh2s (&tvr->challenge.value),
10068 GNUNET_i2s (&cmc->im.sender),
10070 /*memcpy (&hkey,
10071 &hc,
10072 sizeof (hkey));*/
10074 "Key %s for address %s map size %u contains %u\n",
10075 GNUNET_h2s (&vs->hc),
10076 vs->address,
10079 &vs->hc));
10083 &vs->hc,
10084 vs,
10088 NULL);
10089 vs->revalidation_task =
10094 "transport",
10095 &cmc->im.sender,
10097 vs->address,
10098 strlen (vs->address) + 1,
10099 vs->valid_until,
10102 vs);
10103 finish_cmc_handling (cmc);
10104
10105 /* Finally, we now possibly have a confirmed (!) working queue,
10106 update queue status (if queue still is around) */
10107 q = find_queue (&vs->pid, vs->address);
10108 if (NULL == q)
10109 {
10111 "# Queues lost at time of successful validation",
10112 1,
10113 GNUNET_NO);
10114 return;
10115 }
10116 q->validated_until = vs->validated_until;
10117 q->pd.aged_rtt = vs->validation_rtt;
10118 n = q->neighbour;
10119 vl = lookup_virtual_link (&vs->pid);
10120 if (NULL == vl)
10121 {
10122 vl = GNUNET_new (struct VirtualLink);
10124 "Creating new virtual link %p to %s using direct neighbour!\n",
10125 vl,
10126 GNUNET_i2s (&vs->pid));
10127 vl->burst_addr = NULL;
10128 vl->confirmed = GNUNET_YES;
10129 vl->message_uuid_ctr =
10131 vl->target = n->pid;
10137 links,
10138 &vl->target,
10139 vl,
10141 vl->n = n;
10142 n->vl = vl;
10143 q->idle = GNUNET_YES;
10144 vl->visibility_task =
10145 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
10147 /* We lacked a confirmed connection to the target
10148 before, so tell CORE about it (finally!) */
10151 }
10152 else
10153 {
10154 /* Link was already up, remember n is also now available and we are done */
10155 if (NULL == vl->n)
10156 {
10157 vl->n = n;
10158 n->vl = vl;
10159 if (GNUNET_YES == vl->confirmed)
10161 "Virtual link to %s could now also use direct neighbour!\n",
10162 GNUNET_i2s (&vs->pid));
10163 }
10164 else
10165 {
10166 GNUNET_assert (n == vl->n);
10167 }
10168 if (GNUNET_NO == vl->confirmed)
10169 {
10170 vl->confirmed = GNUNET_YES;
10171 q->idle = GNUNET_YES;
10172 vl->visibility_task =
10173 GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
10175 /* We lacked a confirmed connection to the target
10176 before, so tell CORE about it (finally!) */
10179 }
10180 }
10181}

References GNUNET_TIME_Absolute::abs_value_us, ADDRESS_VALIDATION_LIFETIME, VirtualLink::available_fc_window_size, VirtualLink::burst_addr, TransportValidationResponseMessage::challenge, CheckKnownChallengeContext::challenge, check_known_challenge(), check_link_down(), VirtualLink::confirmed, consider_sending_fc(), VirtualLink::core_recv_window, cores_send_connect_info(), DEFAULT_WINDOW_SIZE, find_queue(), finish_cmc_handling(), GNUNET_assert, GNUNET_break, GNUNET_break_op, GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_multihashmap_size(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multipeermap_get_multiple(), GNUNET_CONTAINER_multipeermap_put(), GNUNET_CRYPTO_eddsa_verify, GNUNET_CRYPTO_QUALITY_NONCE, GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_block(), GNUNET_CRYPTO_random_u64(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_i2s(), GNUNET_log, GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_PEERSTORE_store(), GNUNET_PEERSTORE_STOREOPTION_MULTIPLE, GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY, GNUNET_SCHEDULER_add_at(), GNUNET_sh2s(), GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE, GNUNET_STATISTICS_update(), GNUNET_STRINGS_absolute_time_to_string(), GNUNET_TIME_absolute_cmp, GNUNET_TIME_absolute_get_duration(), GNUNET_TIME_absolute_get_monotonic(), GNUNET_TIME_absolute_min(), GNUNET_TIME_absolute_ntoh(), GNUNET_TIME_absolute_subtract(), GNUNET_TIME_relative_min(), GNUNET_TIME_relative_multiply(), GNUNET_TIME_relative_ntoh(), GNUNET_TIME_relative_to_absolute(), GNUNET_TIME_UNIT_MINUTES, GNUNET_TIME_UNIT_ZERO, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_YES, GST_cfg, GST_stats, CommunicatorMessageContext::im, VirtualLink::incoming_fc_window_size, links, lookup_virtual_link(), MAX_ADDRESS_VALID_UNTIL, VirtualLink::message_uuid_ctr, VirtualLink::n, peerstore, peerstore_store_validation_cb(), Neighbour::pid, ValidationState::pid, GNUNET_PeerIdentity::public_key, GNUNET_CRYPTO_SignaturePurpose::purpose, TransportValidationPS::purpose, q, RECV_WINDOW_SIZE, revalidate_map_it(), revalidation_map, revalidation_start_cb(), send_msg_from_cache(), GNUNET_TRANSPORT_IncomingMessage::sender, TransportValidationResponseMessage::signature, VirtualLink::target, update_next_challenge_time(), ValidationState::valid_until, ValidationState::validated_until, validation_map, VALIDATION_RTT_BUFFER_FACTOR, GNUNET_CRYPTO_ChallengeNonceP::value, VirtualLink::visibility_task, Neighbour::vl, and CheckKnownChallengeContext::vs.

Here is the call graph for this function:

◆ handle_incoming_msg()

static void handle_incoming_msg ( void *  cls,
const struct GNUNET_TRANSPORT_IncomingMessage im 
)
static

Incoming message.

Process the request.

Parameters
imthe send message that was received

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

10192{
10193 struct TransportClient *tc = cls;
10194 struct CommunicatorMessageContext *cmc =
10196
10197 cmc->tc = tc;
10198 cmc->im = *im;
10200 "Received message with size %u and flow control id %" PRIu64
10201 " via communicator from peer %s\n",
10202 ntohs (im->header.size),
10203 im->fc_id,
10204 GNUNET_i2s (&im->sender));
10205 cmc->im.neighbour_sender = cmc->im.sender;
10206 cmc->mh = (const struct GNUNET_MessageHeader *) &im[1];
10208}

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

10221{
10222 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10223 (void) cls;
10224
10226 "Flow control header size %u size of addresses %u number of addresses %u size of message struct %lu second struct %lu\n",
10227 ntohs (fc->header.size),
10228 ntohl (fc->size_of_addresses),
10229 ntohl (fc->number_of_addresses),
10230 sizeof(struct TransportFlowControlMessage),
10231 sizeof (struct TransportGlobalNattedAddress));
10232
10233 if (0 == number_of_addresses || ntohs (fc->header.size) == sizeof(struct
10235 + ntohl (fc->number_of_addresses) * sizeof (struct
10237 + ntohl (fc->size_of_addresses))
10238 return GNUNET_OK;
10239 else
10240 {
10241 GNUNET_break_op (0);
10242 return GNUNET_SYSERR;
10243 }
10244}

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

10278{
10279 struct VirtualLink *vl = cls;
10280 const char *slash;
10281 char *address_uri;
10282 char *prefix;
10283 char *uri_without_port;
10284
10285 slash = strrchr (uri, '/');
10286 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
10287 GNUNET_assert (NULL != slash);
10288 slash++;
10289 GNUNET_asprintf (&address_uri,
10290 "%s-%s",
10291 prefix,
10292 slash);
10293
10294 uri_without_port = get_address_without_port (address_uri);
10296 "iterate_address_start_burst %s %s %s %s\n",
10297 uri_without_port,
10298 uri,
10299 address_uri,
10300 slash);
10301 if (0 == strcmp (uri_without_port, slash))
10302 {
10303 vl->burst_addr = GNUNET_strndup (uri_without_port, strlen (uri_without_port)
10304 );
10305 }
10306 else
10307 vl->burst_addr = NULL;
10308
10310 GNUNET_free (uri_without_port);
10311}

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

10318{
10319 struct GNUNET_StartBurstCls *sb_cls = cls;
10320 struct VirtualLink *vl = sb_cls->vl;
10321 struct GNUNET_MessageHeader *hello;
10323
10324 if (NULL != emsg)
10325 {
10327 "Got failure from PEERSTORE: %s\n",
10328 emsg);
10329 return;
10330 }
10331 if (NULL == record)
10332 {
10334 "Hello iteration end for %s\n",
10335 GNUNET_i2s (&vl->target));
10336 vl->ic = NULL;
10337 GNUNET_free (sb_cls);
10338 return;
10339 }
10340
10342 "check_for_burst_address\n");
10343 hello = record->value;
10344 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
10347 vl);
10348 GNUNET_HELLO_parser_free (parser);
10349
10351 GNUNET_free (sb_cls);
10352}

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

10357{
10359}

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

10364{
10365 struct GNUNET_StartBurstCls *sb_cls = cls;
10366 struct VirtualLink *vl = sb_cls->vl;
10367 struct GNUNET_TRANSPORT_StartBurst *sb;
10368 struct GNUNET_MQ_Envelope *env;
10369 char *uri_without_port = vl->burst_addr;
10370
10371 burst_task = NULL;
10372 /*char buf[strlen (uri_without_port) + 1];
10373
10374 GNUNET_memcpy (buf, uri_without_port, strlen (uri_without_port));
10375 buf[strlen (uri_without_port)] = '\0';*/
10376 env =
10378 strlen (uri_without_port) + 1,
10380 sb->rtt = GNUNET_TIME_relative_hton (sb_cls->rtt);
10381 sb->pid = vl->target;
10382 memcpy (&sb[1], uri_without_port, strlen (uri_without_port) + 1);
10383 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
10384 {
10386 "iterate_address_start_burst client tc prefix %s\n",
10387 tc->details.communicator.address_prefix);
10388 if (CT_COMMUNICATOR != tc->type)
10389 continue;
10390 if (GNUNET_YES == tc->details.communicator.can_burst)
10391 {
10393 "iterate_address_start_burst %s call %lu %u rtt %lu\n",
10394 uri_without_port,
10395 strlen (uri_without_port),
10396 ntohs (sb->header.size),
10397 (unsigned long) sb_cls->rtt.rel_value_us);
10398 GNUNET_MQ_send (tc->mq, env);
10402 60),
10404 NULL);
10405 // TODO We need some algo to choose from available communicators. Can we run two bursts at once? Atm we only implemented udp burst.
10406 break;
10407 }
10408 }
10409 GNUNET_free (env);
10410 GNUNET_free (sb_cls);
10411}

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

10416{
10417 struct GNUNET_StartBurstCls *sb_cls = cls;
10418 struct VirtualLink *vl = sb_cls->vl;
10419
10420 if (GNUNET_YES != use_burst)
10421 return;
10423 "burst_task %p ready %s burst addr %s (%p)\n",
10424 burst_task,
10425 sb_cls->sync_ready ? "yes" : "no",
10426 vl->burst_addr,
10427 vl->burst_addr);
10428 if (NULL != burst_task && GNUNET_NO == sb_cls->sync_ready)
10429 {
10431 burst_task = NULL;
10433 return;
10434 }
10435 if (GNUNET_NO == burst_running && NULL != vl->burst_addr && NULL == burst_task
10436 )
10437 {
10439 &start_burst,
10440 sb_cls);
10441 }
10442 else if (NULL == vl->burst_addr)
10443 {
10445 "peerstore",
10446 &vl->target,
10449 sb_cls);
10450 }
10451}

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

10464{
10465 struct CommunicatorMessageContext *cmc = cls;
10466 struct VirtualLink *vl;
10468 uint32_t seq;
10469 struct GNUNET_TIME_Absolute st;
10470 uint64_t os;
10471 uint64_t wnd;
10472 uint32_t random;
10473
10475 "Received FC from %s\n", GNUNET_i2s (&cmc->im.sender));
10476 vl = lookup_virtual_link (&cmc->im.sender);
10477 if (NULL == vl)
10478 {
10479 vl = GNUNET_new (struct VirtualLink);
10481 "No virtual link for %p FC creating new unconfirmed virtual link to %s!\n",
10482 vl,
10483 GNUNET_i2s (&cmc->im.sender));
10484 vl->burst_addr = NULL;
10485 vl->confirmed = GNUNET_NO;
10486 vl->message_uuid_ctr =
10488 vl->target = cmc->im.sender;
10494 links,
10495 &vl->target,
10496 vl,
10498 }
10499 if (NULL != vl->n)
10500 {
10501 for (struct Queue *q = vl->n->queue_head; NULL != q; q = q->next_neighbour)
10502 q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
10503 }
10504
10506 "remaining %lu timeout for neighbour %p\n",
10507 (unsigned long) GNUNET_TIME_absolute_get_remaining (q_timeout).
10508 rel_value_us,
10509 vl->n);
10510 if (NULL == vl->n ||
10511 0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
10512 {
10513 struct GNUNET_TIME_Relative rtt;
10514 struct GNUNET_BurstSync burst_sync;
10515 struct GNUNET_StartBurstCls *bcls;
10516
10517 bcls = GNUNET_new (struct GNUNET_StartBurstCls);
10518 bcls->vl = vl;
10519 vl->sb_cls = bcls;
10520 if (NULL != vl->dv)
10521 rtt = calculate_rtt (vl->dv);
10522 else
10524 burst_sync.rtt_average = fc->rtt;
10525 bcls->rtt = GNUNET_TIME_relative_ntoh (burst_sync.rtt_average);
10526 burst_sync.sync_ready = fc->sync_ready;
10527
10529 &burst_sync,
10530 &queue_burst,
10531 bcls);
10532 }
10533 if (0 != ntohl (fc->number_of_addresses))
10534 {
10535 unsigned int number_of_addresses = ntohl (fc->number_of_addresses);
10536 const char *tgnas;
10537 unsigned int off = 0;
10538
10539 tgnas = (const char *) &fc[1];
10540
10541 for (int i = 1; i <= number_of_addresses; i++)
10542 {
10543 struct TransportGlobalNattedAddress *tgna;
10544 char *addr;
10545 unsigned int address_length;
10546
10547 tgna = (struct TransportGlobalNattedAddress*) &tgnas[off];
10548 addr = (char *) &tgna[1];
10549 address_length = ntohl (tgna->address_length);
10550 off += sizeof(struct TransportGlobalNattedAddress) + address_length;
10551
10553 "received address %s length %u\n",
10554 addr,
10555 ntohl (tgna->address_length));
10556
10557 GNUNET_NAT_add_global_address (nh, addr, ntohl (tgna->address_length));
10558 }
10559 }
10561 if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
10562 {
10564 "FC dropped: Message out of order\n");
10565 /* out of order, drop */
10567 "# FC dropped: message out of order",
10568 1,
10569 GNUNET_NO);
10570 finish_cmc_handling (cmc);
10571 return;
10572 }
10573 seq = ntohl (fc->seq);
10574 if (seq < vl->last_fc_seq)
10575 {
10576 /* Wrap-around/reset of other peer; start all counters from zero */
10578 }
10579 vl->last_fc_seq = seq;
10580 vl->last_fc_timestamp = st;
10582 os = GNUNET_ntohll (fc->outbound_sent);
10584 (int64_t) (os - vl->incoming_fc_window_size_used);
10586 "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
10587 GNUNET_i2s (&vl->target),
10588 (unsigned int) seq,
10589 (unsigned long long) vl->outbound_fc_window_size,
10590 (long long) vl->incoming_fc_window_size_loss);
10593 UINT32_MAX);
10594 if ((GNUNET_YES == vl->confirmed) && ((wnd < vl->incoming_fc_window_size
10598 != wnd) ||
10599 (0 == random
10601 {
10603 "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",
10604 (unsigned long long) wnd,
10605 (unsigned long long) vl->incoming_fc_window_size,
10606 (unsigned long long) vl->last_outbound_window_size_received,
10609 }
10610 if ((wnd == vl->incoming_fc_window_size
10614 (NULL != vl->fc_retransmit_task))
10615 {
10617 "Stopping FC retransmission to %s: peer is current at window %llu\n",
10618 GNUNET_i2s (&vl->target),
10619 (unsigned long long) wnd);
10621 vl->fc_retransmit_task = NULL;
10622 vl->fc_retransmit_count = 0;
10623 }
10625 /* FC window likely increased, check transmission possibilities! */
10627 finish_cmc_handling (cmc);
10628}

References GNUNET_TIME_Absolute::abs_value_us, TransportGlobalNattedAddress::address_length, VirtualLink::available_fc_window_size, VirtualLink::burst_addr, calculate_rtt(), check_vl_transmission(), VirtualLink::confirmed, consider_sending_fc(), VirtualLink::core_recv_window, DEFAULT_WINDOW_SIZE, VirtualLink::dv, FC_NO_CHANGE_REPLY_PROBABILITY, VirtualLink::fc_retransmit_count, VirtualLink::fc_retransmit_task, finish_cmc_handling(), GNUNET_break, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multipeermap_put(), GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u32(), GNUNET_CRYPTO_random_u64(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_is_burst_ready(), GNUNET_log, GNUNET_NAT_add_global_address(), GNUNET_new, GNUNET_NO, GNUNET_ntohll(), GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_update(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_absolute_max(), GNUNET_TIME_absolute_ntoh(), GNUNET_TIME_relative_ntoh(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_YES, GST_stats, CommunicatorMessageContext::im, TransportFlowControlMessage::inbound_window_size, VirtualLink::incoming_fc_window_size, VirtualLink::incoming_fc_window_size_loss, VirtualLink::incoming_fc_window_size_used, VirtualLink::last_fc_seq, VirtualLink::last_fc_timestamp, VirtualLink::last_outbound_window_size_received, links, lookup_virtual_link(), VirtualLink::message_uuid_ctr, VirtualLink::n, nh, TransportFlowControlMessage::number_of_addresses, VirtualLink::outbound_fc_window_size, VirtualLink::outbound_fc_window_size_used, TransportFlowControlMessage::outbound_sent, TransportFlowControlMessage::outbound_window_size, q, queue_burst(), Neighbour::queue_head, RECV_WINDOW_SIZE, GNUNET_StartBurstCls::rtt, TransportFlowControlMessage::rtt, GNUNET_BurstSync::rtt_average, VirtualLink::sb_cls, GNUNET_TRANSPORT_IncomingMessage::sender, TransportFlowControlMessage::sender_time, TransportFlowControlMessage::seq, st, GNUNET_BurstSync::sync_ready, TransportFlowControlMessage::sync_ready, VirtualLink::target, and GNUNET_StartBurstCls::vl.

Here is the call graph for this function:

◆ check_add_queue_message()

static int check_add_queue_message ( void *  cls,
const struct GNUNET_TRANSPORT_AddQueueMessage aqm 
)
static

New queue became available.

Check message.

Parameters
clsthe client
aqmthe send message that was sent

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

10713{
10714 struct TransportClient *tc = cls;
10715
10716 if (CT_COMMUNICATOR != tc->type)
10717 {
10718 GNUNET_break (0);
10719 return GNUNET_SYSERR;
10720 }
10722 return GNUNET_OK;
10723}

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

10733{
10734 if (pm->msg_uuid_set)
10735 return;
10736 pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
10737 pm->msg_uuid_set = GNUNET_YES;
10738}

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

10753{
10754 struct PendingAcknowledgement *pa;
10755
10756 pa = GNUNET_new (struct PendingAcknowledgement);
10757 pa->queue = queue;
10758 pa->dvh = dvh;
10759 pa->pm = pm;
10760 do
10761 {
10763 &pa->ack_uuid,
10764 sizeof(pa->ack_uuid));
10765 }
10768 &pa->ack_uuid.value,
10769 pa,
10771 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
10772 GNUNET_CONTAINER_MDLL_insert (pm, pm->pa_head, pm->pa_tail, pa);
10773 if (NULL != dvh)
10776 pa->message_size = pm->bytes_msg;
10778 "Waiting for ACKnowledgment `%s' for <%" PRIu64 ">\n",
10780 pm->logging_uuid);
10781 return pa;
10782}

References PendingAcknowledgement::ack_uuid, PendingAcknowledgement::dvh, GNUNET_CONTAINER_MDLL_insert, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multiuuidmap_put(), GNUNET_CRYPTO_QUALITY_NONCE, GNUNET_CRYPTO_random_block(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_new, GNUNET_TIME_absolute_get(), GNUNET_uuid2s(), GNUNET_YES, PendingAcknowledgement::message_size, DistanceVectorHop::pa_head, DistanceVectorHop::pa_tail, pending_acks, PendingAcknowledgement::pm, pm, queue(), PendingAcknowledgement::queue, PendingAcknowledgement::transmission_time, and AcknowledgementUUIDP::value.

Referenced by fragment_message(), and reliability_box_message().

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

◆ fragment_message()

static struct PendingMessage * fragment_message ( struct Queue queue,
struct DistanceVectorHop dvh,
struct PendingMessage pm 
)
static

Fragment the given pm to the given mtu.

Adds additional fragments to the neighbour as well. If the mtu is too small, generates and error for the pm and returns NULL.

Parameters
queuewhich queue to fragment for
dvhpath the message will take, or NULL
pmpending message to fragment for transmission
Returns
new message to transmit

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

10800{
10801 struct PendingAcknowledgement *pa;
10802 struct PendingMessage *ff;
10803 uint16_t mtu;
10804 uint16_t msize;
10805
10806 mtu = (UINT16_MAX == queue->mtu)
10807 ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
10808 : queue->mtu;
10810 "Fragmenting message <%" PRIu64
10811 "> with size %u to %s for MTU %u\n",
10812 pm->logging_uuid,
10813 pm->bytes_msg,
10814 GNUNET_i2s (&pm->vl->target),
10815 (unsigned int) mtu);
10818 "Fragmenting message %" PRIu64 " <%" PRIu64
10819 "> with size %u to %s for MTU %u\n",
10820 pm->msg_uuid.uuid,
10821 pm->logging_uuid,
10822 pm->bytes_msg,
10823 GNUNET_i2s (&pm->vl->target),
10824 (unsigned int) mtu);
10825
10826 /* This invariant is established in #handle_add_queue_message() */
10827 GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
10828
10829 /* select fragment for transmission, descending the tree if it has
10830 been expanded until we are at a leaf or at a fragment that is small
10831 enough
10832 */
10833 ff = pm;
10834 msize = ff->bytes_msg;
10835
10836 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
10837 (ff->frag_off == msize) && (NULL != ff->head_frag))
10838 {
10839 ff = ff->head_frag; /* descent into fragmented fragments */
10840 msize = ff->bytes_msg - sizeof(struct TransportFragmentBoxMessage);
10841 }
10842
10843 if (((ff->bytes_msg > mtu) || (pm == ff)) && (ff->frag_off < msize))
10844 {
10845 /* Did not yet calculate all fragments, calculate next fragment */
10846 struct PendingMessage *frag;
10847 struct TransportFragmentBoxMessage tfb;
10848 const char *orig;
10849 char *msg;
10850 uint16_t fragmax;
10851 uint16_t fragsize;
10852 uint16_t msize_ff;
10853 uint16_t xoff = 0;
10854 pm->frag_count++;
10855
10856 orig = (const char *) &ff[1];
10857 msize_ff = ff->bytes_msg;
10858 if (pm != ff)
10859 {
10860 const struct TransportFragmentBoxMessage *tfbo;
10861
10862 tfbo = (const struct TransportFragmentBoxMessage *) orig;
10863 orig += sizeof(struct TransportFragmentBoxMessage);
10864 msize_ff -= sizeof(struct TransportFragmentBoxMessage);
10865 xoff = ntohs (tfbo->frag_off);
10866 }
10867 fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
10868 fragsize = GNUNET_MIN (msize_ff - ff->frag_off, fragmax);
10869 frag =
10870 GNUNET_malloc (sizeof(struct PendingMessage)
10871 + sizeof(struct TransportFragmentBoxMessage) + fragsize);
10873 "3 created pm %p from pm %p storing vl %p from pm %p\n",
10874 frag,
10875 ff,
10876 pm->vl,
10877 pm);
10879 frag->vl = pm->vl;
10880 frag->frag_parent = ff;
10881 frag->timeout = pm->timeout;
10882 frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
10883 frag->pmt = PMT_FRAGMENT_BOX;
10884 msg = (char *) &frag[1];
10885 tfb.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT);
10886 tfb.header.size =
10887 htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
10888 pa = prepare_pending_acknowledgement (queue, dvh, frag);
10889 tfb.ack_uuid = pa->ack_uuid;
10890 tfb.msg_uuid = pm->msg_uuid;
10891 tfb.frag_off = htons (ff->frag_off + xoff);
10892 tfb.msg_size = htons (pm->bytes_msg);
10893 memcpy (msg, &tfb, sizeof(tfb));
10894 memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
10896 ff->tail_frag, frag);
10897 ff->frag_off += fragsize;
10898 ff = frag;
10899 }
10900
10901 /* Move head to the tail and return it */
10905 ff);
10909 ff);
10910
10911 return ff;
10912}

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

10931{
10933 struct PendingAcknowledgement *pa;
10934 struct PendingMessage *bpm;
10935 char *msg;
10936
10937 if ((PMT_CORE != pm->pmt) && (PMT_DV_BOX != pm->pmt))
10938 return pm; /* already fragmented or reliability boxed, or control message:
10939 do nothing */
10940 if (NULL != pm->bpm)
10941 return pm->bpm; /* already computed earlier: do nothing */
10942 // TODO I guess we do not need this assertion. We might have a DLL with
10943 // fragments, because the MTU changed, and we do not need to fragment anymore.
10944 // But we should keep the fragments until message was completed, because
10945 // the MTU might change again.
10946 // GNUNET_assert (NULL == pm->head_frag);
10947 if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
10948 {
10949 /* failed hard */
10950 GNUNET_break (0);
10952 return NULL;
10953 }
10954
10956
10957 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
10958 + pm->bytes_msg);
10960 "4 created pm %p storing vl %p from pm %p\n",
10961 bpm,
10962 pm->vl,
10963 pm);
10965 bpm->vl = pm->vl;
10966 bpm->frag_parent = pm;
10967 // Why was this needed?
10968 // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
10969 bpm->timeout = pm->timeout;
10971 bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
10973 rbox.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX);
10974 rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
10975 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
10976
10977 rbox.ack_uuid = pa->ack_uuid;
10978 msg = (char *) &bpm[1];
10979 memcpy (msg, &rbox, sizeof(rbox));
10980 memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
10981 pm->bpm = bpm;
10983 "Preparing reliability box for message <%" PRIu64
10984 "> of size %d (%d) to %s on queue %s\n",
10985 pm->logging_uuid,
10986 pm->bytes_msg,
10987 ntohs (((const struct GNUNET_MessageHeader *) &pm[1])->size),
10988 GNUNET_i2s (&pm->vl->target),
10989 queue->address);
10990 return bpm;
10991}

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

10997{
10998 struct VirtualLink *vl = pm->vl;
10999 struct PendingMessage *pos;
11000
11001 /* re-insert sort in neighbour list */
11005 pm);
11006 pos = vl->pending_msg_tail;
11007 while ((NULL != pos) &&
11009 pos = pos->prev_vl;
11013 pos,
11014 pm);
11015}

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

11020{
11021 struct PendingMessage *pos;
11023
11024 pos = pm->head_frag;
11025 while (NULL != pos)
11026 {
11027 if (pos->frags_in_flight_round == pm->frags_in_flight_round ||
11028 GNUNET_NO == check_next_attempt_tree (pos, root))
11030 else
11031 {
11033 break;
11034 }
11035 pos = pos->next_frag;
11036 }
11037
11038 return frags_in_flight;
11039}

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

11044{
11045 struct PendingMessage *pos;
11046
11047 pos = pm->head_frag;
11048 while (NULL != pos)
11049 {
11050 pos->frags_in_flight_round = pm->frags_in_flight_round;
11052 pos = pos->next_frag;
11053 }
11054}

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

11068{
11069 if (NULL == pm->frag_parent)
11070 {
11071 pm->next_attempt = next_attempt;
11073 "Next attempt for message <%" PRIu64 "> set to %" PRIu64 "\n",
11074 pm->logging_uuid,
11075 next_attempt.abs_value_us);
11076 reorder_root_pm (pm, next_attempt);
11077 }
11078 else if ((PMT_RELIABILITY_BOX == pm->pmt) || (PMT_DV_BOX == pm->pmt))// || (PMT_FRAGMENT_BOX == pm->pmt))
11079 {
11080 struct PendingMessage *root = pm->frag_parent;
11081
11082 while (NULL != root->frag_parent)
11083 root = root->frag_parent;
11085 "Next attempt for root message <%" PRIu64 "> set to %s\n",
11086 root->logging_uuid,
11088 root->next_attempt = next_attempt;
11090 }
11091 else
11092 {
11093 struct PendingMessage *root = pm->frag_parent;
11094
11095 while (NULL != root->frag_parent && PMT_DV_BOX != root->pmt)
11096 root = root->frag_parent;
11097
11099 "frag_count next attempt %u\n",
11100 root->frag_count);
11101
11102 if (GNUNET_NO == root->frags_in_flight)
11103 {
11104 root->next_attempt = next_attempt;
11106 root->frags_in_flight_round++;
11108 "Next attempt for fragmented message <%" PRIu64 "> (<%" PRIu64
11109 ">)set to %" PRIu64 "\n",
11110 pm->logging_uuid,
11111 root->logging_uuid,
11113 }
11114
11115 pm->next_attempt = root->next_attempt;
11116 pm->frags_in_flight_round = root->frags_in_flight_round;
11118
11119 if (root->bytes_msg == root->frag_off)
11120 root->frags_in_flight = check_next_attempt_tree (root, root);
11121 else
11123
11124 if (GNUNET_NO == root->frags_in_flight)
11125 {
11127 "We have no fragments in flight for message %" PRIu64
11128 ", reorder root! Next attempt is %" PRIu64 "\n",
11129 root->logging_uuid,
11131 if (PMT_DV_BOX == root->pmt)
11132 root = root->frag_parent;
11133 reorder_root_pm (root, root->next_attempt);
11134 // root->next_attempt = GNUNET_TIME_UNIT_ZERO_ABS;
11135 }
11136 else
11137 {
11138 double factor = ((double) root->frag_count - 1)
11139 / (double) root->frag_count;
11140 struct GNUNET_TIME_Relative s1;
11141 struct GNUNET_TIME_Relative s2;
11142 struct GNUNET_TIME_Relative plus_mean =
11145 next_attempt);
11146
11148 "frag_count %u after factor\n",
11149 root->frag_count);
11151 factor);
11152 s2 = GNUNET_TIME_relative_divide (plus,
11153 root->frag_count);
11154 plus_mean = GNUNET_TIME_relative_add (s1, s2);
11157 "We have fragments in flight for message %" PRIu64
11158 ", do not reorder root! Actual next attempt %" PRIu64 "\n",
11159 root->logging_uuid,
11161 }
11162 }
11163}

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

11235{
11236 struct GNUNET_TIME_Absolute now;
11237
11238 now = GNUNET_TIME_absolute_get ();
11239 sc->to_early = GNUNET_NO;
11240 sc->frags_in_flight = GNUNET_NO;
11241 for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
11242 pos = pos->next_vl)
11243 {
11244 size_t real_overhead = overhead;
11245 int frag;
11246 int relb;
11247
11248 if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
11249 {
11251 "DV messages must not be DV-routed to next hop!\n");
11252 continue; /* DV messages must not be DV-routed to next hop! */
11253 }
11254 if (pos->next_attempt.abs_value_us > now.abs_value_us)
11255 {
11256 if (GNUNET_YES == pos->frags_in_flight)
11257 {
11258 sc->frags_in_flight = GNUNET_YES;
11260 "Fragments in flight for message %" PRIu64 "\n",
11261 pos->logging_uuid);
11262 }
11263 else
11264 {
11266 "Maybe too early, because message are sorted by next_attempt, if there are no fragments in flight.Checked message %"
11267 PRIu64 "\n",
11268 pos->logging_uuid);
11269 sc->to_early = GNUNET_YES;
11270 sc->to_early_retry_delay = GNUNET_TIME_absolute_get_remaining (
11271 pos->next_attempt);
11272 continue;
11273 }
11274 // break; /* too early for all messages, they are sorted by next_attempt */
11275 }
11276 if (NULL != pos->qe)
11277 {
11279 "not eligible\n");
11280 continue; /* not eligible */
11281 }
11282 sc->consideration_counter++;
11283 /* determine if we have to fragment, if so add fragmentation
11284 overhead! */
11286 "check %" PRIu64 " for sc->best\n",
11287 pos->logging_uuid);
11288 frag = GNUNET_NO;
11289 if (((0 != queue->mtu) &&
11290 (pos->bytes_msg + real_overhead > queue->mtu)) ||
11291 (pos->bytes_msg > UINT16_MAX - sizeof(struct
11293 ||
11294 (NULL != pos->head_frag /* fragments already exist, should
11295 respect that even if MTU is UINT16_MAX for
11296 this queue */))
11297 {
11299 "fragment msg with size %u, realoverhead is %lu\n",
11300 pos->bytes_msg,
11301 real_overhead);
11302 frag = GNUNET_YES;
11303 if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
11304 {
11305 /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
11306 header without the ACK UUID when using a *reliable* channel! */
11307 }
11308 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11309 }
11310 /* determine if we have to reliability-box, if so add reliability box
11311 overhead */
11312 relb = GNUNET_NO;
11313 if ((GNUNET_NO == frag) &&
11314 (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
11315 (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
11316 {
11317 real_overhead += sizeof(struct TransportReliabilityBoxMessage);
11318
11319 if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu))
11320 {
11321 frag = GNUNET_YES;
11322 real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
11323 }
11324 else
11325 {
11326 relb = GNUNET_YES;
11327 }
11329 "Create reliability box of msg with size %u, realoverhead is %lu %u %u %u\n",
11330 pos->bytes_msg,
11331 real_overhead,
11332 queue->mtu,
11333 frag,
11334 relb);
11335 }
11336
11337 /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
11338 message would beat it! */
11339 if (GNUNET_NO == sc->frags_in_flight && NULL != sc->best)
11340 {
11341 /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
11342 OPTIMIZE-ME: This is a heuristic, which so far has NOT been
11343 experimentally validated. There may be some huge potential for
11344 improvement here. Also, we right now only compare how well the
11345 given message fits _this_ queue, and do not consider how well other
11346 queues might suit the message. Taking other queues into consideration
11347 may further improve the result, but could also be expensive
11348 in terms of CPU time. */
11349 long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
11350 long long pm_score = frag * 40 + relb * 20 + real_overhead;
11351 long long time_delta =
11352 (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
11353 / 1000LL;
11354
11355 /* "time_delta" considers which message has been 'ready' for transmission
11356 for longer, if a message has a preference for low latency, increase
11357 the weight of the time_delta by 10x if it is favorable for that message */
11358 if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11359 (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
11360 time_delta *= 10; /* increase weight (always, both are low latency) */
11361 else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11362 (time_delta > 0))
11363 time_delta *= 10; /* increase weight, favors 'pos', which is low latency */
11364 else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
11365 (time_delta < 0))
11366 time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */
11367 if (0 != queue->mtu)
11368 {
11369 /* Grant bonus if we are below MTU, larger bonus the closer we will
11370 be to the MTU */
11371 if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
11372 sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
11373 if (queue->mtu > real_overhead + pos->bytes_msg)
11374 pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
11375 }
11376 if (sc_score + time_delta > pm_score)
11377 {
11379 "sc_score of %" PRIu64 " larger, keep sc->best %" PRIu64
11380 "\n",
11381 pos->logging_uuid,
11382 sc->best->logging_uuid);
11383 continue; /* sc_score larger, keep sc->best */
11384 }
11385 }
11386 sc->best = pos;
11387 sc->dvh = dvh;
11388 sc->frag = frag;
11389 sc->relb = relb;
11390 sc->real_overhead = real_overhead;
11391 }
11392}

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

11410{
11411 struct PendingMessageScoreContext *sc = cls;
11412 struct PendingMessage *pm = sc->best;
11413 struct PendingMessage *bpm;
11414 uint16_t bsize = ntohs (hdr->size);
11415
11416 GNUNET_assert (NULL == pm->bpm);
11417 bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
11419 "5 created pm %p storing vl %p from pm %p\n",
11420 bpm,
11421 pm->vl,
11422 pm);
11424 bpm->pmt = PMT_DV_BOX;
11425 bpm->vl = pm->vl;
11426 bpm->timeout = pm->timeout;
11427 bpm->bytes_msg = bsize;
11428 bpm->frag_parent = pm;
11431 "Creating DV Box %" PRIu64 " for original message %" PRIu64
11432 " (next hop is %s)\n",
11434 pm->logging_uuid,
11435 GNUNET_i2s (&next_hop->pid));
11436 memcpy (&bpm[1], hdr, bsize);
11437 pm->bpm = bpm;
11438}

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

11715{
11716 struct TransportClient *tc = cls;
11717
11718 if (CT_COMMUNICATOR != tc->type)
11719 {
11720 GNUNET_break (0);
11722 return;
11723 }
11724 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11725 queue = queue->next_client)
11726 {
11727 struct Neighbour *neighbour = queue->neighbour;
11728
11729 if ((ntohl (dqm->qid) != queue->qid) ||
11730 (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
11731 continue;
11733 "Dropped queue %s to peer %s\n",
11734 queue->address,
11735 GNUNET_i2s (&neighbour->pid));
11736 free_queue (queue);
11738 return;
11739 }
11740 GNUNET_break (0);
11742}

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

11845{
11846 struct TransportClient *tc = cls;
11847 struct QueueEntry *qe;
11848
11849 if (CT_COMMUNICATOR != tc->type)
11850 {
11851 GNUNET_break (0);
11853 return;
11854 }
11855
11856 /* find our queue entry matching the ACK */
11857 qe = NULL;
11859 "Looking for queue for PID %s\n",
11860 GNUNET_i2s (&sma->receiver));
11861 for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
11862 queue = queue->next_client)
11863 {
11864 if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
11865 continue;
11867 "Found PID %s\n",
11868 GNUNET_i2s (&queue->neighbour->pid));
11869
11870
11871 for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
11872 qep = qep->next)
11873 {
11874 if (qep->mid != GNUNET_ntohll (sma->mid) || queue->qid != ntohl (
11875 sma->qid))
11876 continue;
11878 "QueueEntry MID: %" PRIu64 " on queue QID: %u, Ack MID: %"
11879 PRIu64 " Ack QID %u\n",
11880 qep->mid,
11881 queue->qid,
11882 GNUNET_ntohll (sma->mid),
11883 ntohl (sma->qid));
11884 qe = qep;
11885 if ((NULL != qe->pm) && (qe->pm->qe != qe))
11887 "For pending message %" PRIu64 " we had retransmissions.\n",
11888 qe->pm->logging_uuid);
11889 break;
11890 }
11891 }
11892 if (NULL == qe)
11893 {
11895 "No QueueEntry found for Ack MID %" PRIu64 " QID: %u\n",
11896 GNUNET_ntohll (sma->mid),
11897 ntohl (sma->qid));
11898 // TODO I guess this can happen, if the Ack from the peer comes before the Ack from the queue.
11899 // Update: Maybe QueueEntry was accidentally freed during freeing PendingMessage.
11900 /* this should never happen */
11901 // GNUNET_break (0);
11902 // GNUNET_SERVICE_client_drop (tc->client);
11904 return;
11905 }
11908}

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

11919{
11921}

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

11937{
11938 struct TransportClient *tc = cls;
11939 struct Neighbour *neighbour = value;
11940
11941 GNUNET_assert (CT_MONITOR == tc->type);
11942 for (struct Queue *q = neighbour->queue_head; NULL != q;
11943 q = q->next_neighbour)
11944 {
11945 struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
11946 .cs = q->cs,
11947 .num_msg_pending = q->num_msg_pending,
11948 .num_bytes_pending = q->num_bytes_pending };
11949
11950 notify_monitor (tc, pid, q->address, q->nt, &me);
11951 }
11952 return GNUNET_OK;
11953}

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

11965{
11966 struct TransportClient *tc = cls;
11967
11968 if (CT_NONE != tc->type)
11969 {
11970 GNUNET_break (0);
11972 return;
11973 }
11974 tc->type = CT_MONITOR;
11975 tc->details.monitor.peer = start->peer;
11976 tc->details.monitor.one_shot = ntohl (start->one_shot);
11980}

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

11992{
11993 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
11994 {
11995 if (CT_COMMUNICATOR != tc->type)
11996 continue;
11997 if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
11998 return tc;
11999 }
12000 GNUNET_log (
12002 "Someone suggested use of communicator for `%s', but we do not have such a communicator!\n",
12003 prefix);
12004 return NULL;
12005}

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

12220{
12221 struct QueueQualityContext *ctx = cls;
12222 struct Neighbour *n = value;
12223 int do_inc;
12224
12225 (void) pid;
12226 do_inc = GNUNET_NO;
12227 for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
12228 {
12229 ctx->num_queues++;
12230 if (0 == ctx->k--)
12231 ctx->q = q;
12232 /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
12233 statistics and consider those as well here? */
12234 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
12235 do_inc = GNUNET_YES;
12236 }
12237 if (GNUNET_YES == do_inc)
12238 ctx->quality_count++;
12239 return GNUNET_OK;
12240}

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

12328{
12329 struct LearnLaunchEntry *lle;
12330 struct QueueQualityContext qqc;
12331 struct TransportDVLearnMessage dvl;
12332 const struct GNUNET_PeerIdentity *my_identity;
12333
12334 (void) cls;
12335 dvlearn_task = NULL;
12337 return; /* lost all connectivity, cannot do learning */
12338 qqc.quality_count = 0;
12339 qqc.num_queues = 0;
12343 &qqc);
12344 if (qqc.quality_count > DV_LEARN_QUALITY_THRESHOLD)
12345 {
12346 struct GNUNET_TIME_Relative delay;
12347 unsigned int factor;
12348
12349 /* scale our retries by how far we are above the threshold */
12350 factor = qqc.quality_count / DV_LEARN_QUALITY_THRESHOLD;
12353 "At connection quality %u, will launch DV learn in %s\n",
12354 qqc.quality_count,
12357 return;
12358 }
12359 /* remove old entries in #dvlearn_map if it has grown too big */
12360 while (MAX_DV_LEARN_PENDING <=
12362 {
12363 lle = lle_tail;
12366 &lle->challenge.value,
12367 lle));
12369 GNUNET_free (lle);
12370 }
12371 /* setup data structure for learning */
12372 lle = GNUNET_new (struct LearnLaunchEntry);
12374 &lle->challenge,
12375 sizeof(lle->challenge));
12377 "Starting launch DV learn with challenge %s\n",
12378 GNUNET_sh2s (&lle->challenge.value));
12383 &lle->challenge.value,
12384 lle,
12388 dvl.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN);
12389 dvl.header.size = htons (sizeof(dvl));
12390 dvl.num_hops = htons (0);
12391 dvl.bidirectional = htons (0);
12392 dvl.non_network_delay = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO);
12393 dvl.monotonic_time =
12395 // We will set the below again later
12396 memset (&dvl.init_sig, 0, sizeof dvl.init_sig);
12397 dvl.challenge = lle->challenge;
12398 dvl.initiator = *my_identity;
12399 {
12400 struct DvInitPS dvip = {
12401 .purpose.purpose = htonl (
12403 .purpose.size = htonl (sizeof(dvip)),
12404 .monotonic_time = dvl.monotonic_time,
12405 .challenge = lle->challenge
12406 };
12407 struct SignDvInitCls *sign_dv_init_cls;
12408
12409 sign_dv_init_cls = GNUNET_new (struct SignDvInitCls);
12410 sign_dv_init_cls->dvl = dvl;
12411 sign_dv_init_cls->lle = lle;
12412 sign_dv_init_cls->qqc = qqc;
12413 sign_dv_init_cls->pr = GNUNET_new (struct PilsRequest);
12416 sign_dv_init_cls->pr);
12417 sign_dv_init_cls->pr->op =
12419 &dvip.purpose,
12421 sign_dv_init_cls);
12422 }
12423}

References TransportDVLearnMessage::bidirectional, TransportDVLearnMessage::challenge, LearnLaunchEntry::challenge, check_connection_quality(), DV_LEARN_BASE_FREQUENCY, DV_LEARN_QUALITY_THRESHOLD, SignDvInitCls::dvl, dvlearn_map, dvlearn_task, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_CONTAINER_multipeermap_size(), GNUNET_CONTAINER_multishortmap_put(), GNUNET_CONTAINER_multishortmap_remove(), GNUNET_CONTAINER_multishortmap_size(), GNUNET_CRYPTO_QUALITY_NONCE, GNUNET_CRYPTO_random_block(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN, GNUNET_new, GNUNET_PILS_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 12268 of file gnunet-service-transport.c.

12271{
12272 const struct GNUNET_PeerIdentity *my_identity;
12273 struct SignDvInitCls *sign_dv_init_cls = cls;
12274 struct TransportDVLearnMessage dvl = sign_dv_init_cls->dvl;
12275 struct LearnLaunchEntry *lle = sign_dv_init_cls->lle;
12276 struct QueueQualityContext qqc = sign_dv_init_cls->qqc;
12277
12280
12281 sign_dv_init_cls->pr->op = NULL;
12284 sign_dv_init_cls->pr);
12285 GNUNET_free (sign_dv_init_cls->pr);
12286
12287 dvl.init_sig = *sig;
12288 dvl.initiator = *my_identity;
12289 dvl.challenge = lle->challenge;
12290
12291 qqc.quality_count = 0;
12293 qqc.num_queues = 0;
12294 qqc.q = NULL;
12297 &qqc);
12298 GNUNET_assert (NULL != qqc.q);
12299
12300 /* Do this as close to transmission time as possible! */
12302
12303 queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
12304 /* reschedule this job, randomizing the time it runs (but no
12305 actual backoff!) */
12306 if (NULL != dvlearn_task)
12311 NULL);
12312}

References TransportDVLearnMessage::challenge, LearnLaunchEntry::challenge, check_connection_quality(), DV_LEARN_BASE_FREQUENCY, SignDvInitCls::dvl, dvlearn_task, GNUNET_assert, GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u32(), GNUNET_free, GNUNET_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 12461 of file gnunet-service-transport.c.

12464{
12465 struct Queue *q = cls;
12466 struct ValidationState *vs = value;
12467 char *address_without_port_vs;
12468 char *address_without_port_q;
12469 int success = GNUNET_YES;
12470
12471 // TODO Check if this is really necessary.
12472 address_without_port_vs = get_address_without_port (vs->address);
12473 address_without_port_q = get_address_without_port (q->address);
12474
12476 "Check validation request pending for `%s' at `%s'/`%s' (vs)/(q)\n",
12477 GNUNET_i2s (pid),
12478 address_without_port_vs,
12479 address_without_port_q);
12480 (void) pid;
12481 if ((GNUNET_YES == vs->awaiting_queue) &&
12482 (0 == strcmp (address_without_port_vs, address_without_port_q)))
12483 {
12484
12485 vs->awaiting_queue = GNUNET_NO;
12487 success = GNUNET_NO;
12488 }
12489
12490 GNUNET_free (address_without_port_vs);
12491 GNUNET_free (address_without_port_q);
12492 return success;
12493}

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

12508{
12509 struct Neighbour *n = cls;
12510 struct GNUNET_TIME_AbsoluteNBO *mtbe;
12511
12512 (void) emsg;
12513 if (NULL == record)
12514 {
12515 /* we're done with #neighbour_dv_monotime_cb() invocations,
12516 continue normal processing */
12517 n->get = NULL;
12519 return;
12520 }
12521 if (0 == record->value_size)
12522 {
12524 GNUNET_break (0);
12525 return;
12526 }
12527 mtbe = record->value;
12532}

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

12539{
12540 struct Queue *queue = cls;
12541 struct sockaddr_in v4;
12542 const char *slash;
12543 char *address_uri;
12544 char *prefix;
12545 char *uri_without_port;
12546 char *address_uri_without_port;
12547
12548 slash = strrchr (uri, '/');
12549 prefix = GNUNET_strndup (uri, (slash - uri) - 2);
12550 GNUNET_assert (NULL != slash);
12551 slash++;
12552 GNUNET_asprintf (&address_uri,
12553 "%s-%s",
12554 prefix,
12555 slash);
12556
12558 "1 not global natted_address %u %s %s %s\n",
12559 queue->is_global_natted,
12560 uri,
12561 queue->address,
12562 slash);
12563
12564 uri_without_port = get_address_without_port (address_uri);
12565 if (1 != inet_pton (AF_INET, uri_without_port, &v4.sin_addr))
12566 {
12568 GNUNET_free (address_uri);
12569 GNUNET_free (uri_without_port);
12570 return;
12571 }
12572
12574 "2 not global natted_address %u %s %s\n",
12575 queue->is_global_natted,
12576 uri,
12577 queue->address);
12578
12579 if (GNUNET_NO == queue->is_global_natted)
12580 {
12582 GNUNET_free (address_uri);
12583 GNUNET_free (uri_without_port);
12584 return;
12585 }
12586
12588 "3 not global natted_address %u %s %s\n",
12589 queue->is_global_natted,
12590 uri,
12591 queue->address);
12592
12593 if (0 == strcmp (uri_without_port, address_uri))
12594 {
12596 GNUNET_free (address_uri);
12597 GNUNET_free (uri_without_port);
12598 return;
12599 }
12600
12602 "4 not global natted_address %u %s %s\n",
12603 queue->is_global_natted,
12604 uri,
12605 queue->address);
12606
12607 address_uri_without_port = get_address_without_port (queue->address);
12608 if (0 == strcmp (uri_without_port, address_uri_without_port))
12609 {
12610 queue->is_global_natted = GNUNET_NO;
12611 }
12612
12614 "not global natted_address %u %s %s %s %s %s %u\n",
12615 queue->is_global_natted,
12616 uri,
12617 queue->address,
12618 uri_without_port,
12619 address_uri_without_port,
12620 prefix,
12621 GNUNET_NO);
12623 GNUNET_free (address_uri);
12624 GNUNET_free (address_uri_without_port);
12625 GNUNET_free (uri_without_port);
12626}

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

12647{
12648 struct TransportGlobalNattedAddressClosure *tgna_cls = cls;
12649 struct TransportGlobalNattedAddress *tgna = value;
12650 char *addr = (char *) &tgna[1];
12651
12653 "Checking tgna %p with addr %s and length %u compare length %lu\n",
12654 tgna,
12655 addr,
12656 ntohl (tgna->address_length),
12657 strlen (tgna_cls->addr));
12658 if (strlen (tgna_cls->addr) == ntohl (tgna->address_length)
12659 && 0 == strncmp (addr, tgna_cls->addr, ntohl (tgna->address_length)))
12660 {
12661 tgna_cls->tgna = tgna;
12662 return GNUNET_NO;
12663 }
12664 return GNUNET_YES;
12665}

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

12670{
12672 "Error in PEERSTORE monitoring for checking global natted\n");
12673}

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

12678{
12680 "Done with initial PEERSTORE iteration during monitoring for checking global natted\n");
12681}

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

12688{
12689 struct Queue *queue = cls;
12690 struct Neighbour *neighbour = queue->neighbour;
12692 struct GNUNET_MessageHeader *hello;
12694 size_t address_len_without_port;
12695
12696 if (NULL != emsg)
12697 {
12699 "Got failure from PEERSTORE: %s\n",
12700 emsg);
12701 return;
12702 }
12703 if (0 == record->value_size)
12704 {
12706 GNUNET_break (0);
12707 return;
12708 }
12709 queue->is_global_natted = GNUNET_YES;
12710 hello = record->value;
12711 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
12713 "before not global natted %u\n",
12714 queue->is_global_natted);
12717 queue);
12719 "after not global natted %u\n",
12720 queue->is_global_natted);
12721 GNUNET_HELLO_parser_free (parser);
12722
12723 tgna_cls.addr = get_address_without_port (queue->address);
12724 address_len_without_port = strlen (tgna_cls.addr);
12725 /*{
12726 char buf[address_len_without_port + 1];
12727
12728 GNUNET_memcpy (&buf, addr, address_len_without_port);
12729 buf[address_len_without_port] = '\0';
12730 GNUNET_free (addr);
12731 GNUNET_memcpy (tgna_cls.addr, buf, address_len_without_port + 1);
12732 }*/
12733 tgna_cls.tgna = NULL;
12735 &neighbour->pid,
12737 &tgna_cls);
12738 if (NULL != tgna_cls.tgna)
12740 " tgna_cls.tgna tgna %p %lu %u %u\n",
12741 tgna_cls.tgna,
12742 neighbour->size_of_global_addresses,
12743 ntohl (tgna_cls.tgna->address_length),
12744 neighbour->number_of_addresses);
12745 if (NULL == tgna_cls.tgna && GNUNET_YES == queue->is_global_natted)
12746 {
12747 struct TransportGlobalNattedAddress *tgna;
12748
12749 tgna = GNUNET_malloc (sizeof (struct TransportGlobalNattedAddress)
12750 + address_len_without_port);
12751 tgna->address_length = htonl (address_len_without_port);
12752 GNUNET_memcpy (&tgna[1], tgna_cls.addr, address_len_without_port);
12754 &neighbour->pid,
12755 tgna,
12757 neighbour->number_of_addresses++;
12758 neighbour->size_of_global_addresses += address_len_without_port + 1;
12760 "Created tgna %p with address %s and length %lu\n",
12761 tgna,
12762 tgna_cls.addr,
12763 address_len_without_port + 1);
12764 }
12765 else if (NULL != tgna_cls.tgna && GNUNET_NO == queue->is_global_natted)
12766 {
12768 &neighbour->pid,
12769 tgna_cls.tgna);
12770 GNUNET_assert (neighbour->size_of_global_addresses >= ntohl (tgna_cls.tgna->
12772 );
12773 neighbour->size_of_global_addresses -= ntohl (tgna_cls.tgna->address_length)
12774 ;
12775 GNUNET_assert (0 < neighbour->number_of_addresses);
12776 neighbour->number_of_addresses--;
12778 "removed tgna %p\n",
12779 tgna_cls.tgna);
12780 GNUNET_free (tgna_cls.tgna);
12781 }
12783 GNUNET_free (tgna_cls.addr);
12784}

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

12796{
12797 struct TransportClient *tc = cls;
12798 struct Queue *queue;
12799 struct Neighbour *neighbour;
12800 const char *addr;
12801 uint16_t addr_len;
12802
12803 if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
12804 {
12805 /* MTU so small as to be useless for transmissions,
12806 required for #fragment_message()! */
12807 GNUNET_break_op (0);
12809 return;
12810 }
12811 /* This may simply be a queue update */
12812 for (queue = tc->details.communicator.queue_head;
12813 NULL != queue;
12814 queue = queue->next_client)
12815 {
12816 if (queue->qid != ntohl (aqm->qid))
12817 continue;
12818 break;
12819 }
12820
12821 if (NULL != queue)
12822 {
12823 neighbour = queue->neighbour;
12824 }
12825 else
12826 {
12827 struct GNUNET_TIME_Absolute validated_until = GNUNET_TIME_UNIT_ZERO_ABS;
12828
12829 neighbour = lookup_neighbour (&aqm->receiver);
12830 if (NULL == neighbour)
12831 {
12832 neighbour = GNUNET_new (struct Neighbour);
12834 GNUNET_YES);
12835 neighbour->pid = aqm->receiver;
12838 neighbours,
12839 &neighbour->pid,
12840 neighbour,
12842 neighbour->get =
12844 "transport",
12845 &neighbour->pid,
12848 neighbour);
12849 }
12850 addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
12851 addr = (const char *) &aqm[1];
12853 "New queue %s to %s available with QID %u and q_len %" PRIu64
12854 " and mtu %u\n",
12855 addr,
12856 GNUNET_i2s (&aqm->receiver),
12857 ntohl (aqm->qid),
12858 GNUNET_ntohll (aqm->q_len),
12859 ntohl (aqm->mtu));
12860 queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
12861 queue->tc = tc;
12862 for (struct Queue *q = neighbour->queue_head; NULL != q; q = q->
12863 next_neighbour)
12864 validated_until = GNUNET_TIME_absolute_max (validated_until, q->
12865 validated_until);
12866 if (0 == GNUNET_TIME_absolute_get_remaining (validated_until).rel_value_us)
12867 {
12869 "New queue with QID %u inherit validated until\n",
12870 ntohl (aqm->qid));
12871 queue->validated_until = validated_until;
12872 }
12873 queue->address = (const char *) &queue[1];
12874 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
12875 queue->qid = ntohl (aqm->qid);
12876 queue->neighbour = neighbour;
12878 queue->unlimited_length = GNUNET_YES;
12879 queue->q_capacity = GNUNET_ntohll (aqm->q_len);
12880 memcpy (&queue[1], addr, addr_len);
12881 /* notify monitors about new queue */
12882 {
12883 struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
12884
12885 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
12886 }
12888 neighbour->queue_head,
12889 neighbour->queue_tail,
12890 queue);
12892 tc->details.communicator.queue_head,
12893 tc->details.communicator.queue_tail,
12894 queue);
12895
12896 }
12897 queue->mtu = ntohl (aqm->mtu);
12898 queue->nt = ntohl (aqm->nt);
12899 queue->cs = ntohl (aqm->cs);
12900 queue->idle = GNUNET_YES;
12901
12902 {
12903 struct sockaddr_in v4;
12904 char *addr_without = get_address_without_port (queue->address);
12905 if (1 == inet_pton (AF_INET, addr_without, &v4.sin_addr))
12906 {
12908 "start not global natted\n");
12910 GNUNET_YES,
12911 "peerstore",
12912 &neighbour->pid,
12914 &
12916 NULL,
12917 &
12919 NULL,
12921 queue);
12922 }
12923 GNUNET_free (addr_without);
12924 }
12925 /* check if valdiations are waiting for the queue */
12927 &aqm->receiver))
12928 {
12931 &aqm->
12932 receiver,
12933 &
12935 queue))
12936 start_address_validation (&aqm->receiver, queue->address);
12937 }
12938 else
12939 start_address_validation (&aqm->receiver, queue->address);
12940 /* look for traffic for this queue */
12941 // TODO Check whether this makes any sense at all.
12942 /*schedule_transmit_on_queue (GNUNET_TIME_UNIT_ZERO,
12943 queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);*/
12944 /* might be our first queue, try launching DV learning */
12945 if (NULL == dvlearn_task)
12948}

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

12961{
12962 struct TransportClient *tc = cls;
12963 struct Queue *target_queue = NULL;
12964
12966 "Received queue update message for %u with q_len %llu and mtu %u\n",
12967 ntohl (msg->qid),
12968 (unsigned long long) GNUNET_ntohll (msg->q_len),
12969 ntohl (msg->mtu));
12970 for (target_queue = tc->details.communicator.queue_head;
12971 NULL != target_queue;
12972 target_queue = target_queue->next_client)
12973 {
12974 if (ntohl (msg->qid) == target_queue->qid)
12975 break;
12976 }
12977 if (NULL == target_queue)
12978 {
12980 "Queue to update no longer exists! Discarding update.\n");
12981 return;
12982 }
12983
12984 target_queue->nt = msg->nt;
12985 target_queue->mtu = ntohl (msg->mtu);
12986 target_queue->cs = msg->cs;
12987 target_queue->priority = ntohl (msg->priority);
12988 /* The update message indicates how many messages
12989 * the queue should be able to handle.
12990 */
12992 target_queue->unlimited_length = GNUNET_YES;
12993 else
12994 target_queue->unlimited_length = GNUNET_NO;
12995 target_queue->q_capacity += GNUNET_ntohll (msg->q_len);
12996 if (0 < target_queue->q_capacity)
12998 target_queue,
13001}

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

13014{
13015 struct TransportClient *tc = cls;
13016
13017 if (CT_COMMUNICATOR != tc->type)
13018 {
13019 GNUNET_break (0);
13021 return;
13022 }
13024 "# Suggestions succeeded at communicator",
13025 1,
13026 GNUNET_NO);
13028 "Request #%u for communicator to create queue succeeded\n",
13029 (unsigned int) ntohs (cqr->request_id));
13031}

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

13046{
13047 struct TransportClient *tc = cls;
13048
13049 if (CT_COMMUNICATOR != tc->type)
13050 {
13051 GNUNET_break (0);
13053 return;
13054 }
13056 "Request #%u for communicator to create queue failed\n",
13057 (unsigned int) ntohl (cqr->request_id));
13059 "# Suggestions failed in queue creation at communicator",
13060 1,
13061 GNUNET_NO);
13063}

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

13075{
13076 struct TransportClient *tc = cls;
13077 struct PeerRequest *pr;
13078
13079 if (CT_APPLICATION != tc->type)
13080 {
13081 GNUNET_break (0);
13083 return;
13084 }
13085 pr = GNUNET_CONTAINER_multipeermap_get (tc->details.application.requests,
13086 &msg->peer);
13087 if (NULL == pr)
13088 {
13089 GNUNET_break (0);
13091 return;
13092 }
13093 (void) stop_peer_request (tc, &pr->pid, pr);
13095}

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

13102{
13103 struct Queue *q;
13104 int pfx_len;
13105 const char *eou;
13106 char *address;
13107 (void) cls;
13108
13109 eou = strstr (uri,
13110 "://");
13111 pfx_len = eou - uri;
13112 eou += 3;
13114 "%.*s-%s",
13115 pfx_len,
13116 uri,
13117 eou);
13118
13120 "hello for client %s\n",
13121 address);
13122
13123 q = find_queue (pid, address);
13124 if (NULL == q)
13125 {
13127 }
13128 else
13131}

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

13145{
13146 const struct GNUNET_PeerIdentity *my_identity;
13147 struct PeerRequest *pr = cls;
13149 struct GNUNET_MessageHeader *hello;
13150
13151 if (NULL != emsg)
13152 {
13154 "Got failure from PEERSTORE: %s\n",
13155 emsg);
13156 return;
13157 }
13159 if (NULL == my_identity)
13160 {
13162 "No identity given yet!\n");
13163 return;
13164 }
13165 hello = record->value;
13166 if (0 == GNUNET_memcmp (&record->peer, my_identity))
13167 {
13169 return;
13170 }
13171 parser = GNUNET_HELLO_parser_from_msg (hello, &record->peer);
13172 if (NULL == parser)
13173 {
13175 "HELLO cannot be parsed!\n");
13176 return;
13177 }
13179 "HELLO for `%s' could be parsed, iterating addresses...!\n",
13183 NULL);
13184 GNUNET_HELLO_parser_free (parser);
13185}

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

13190{
13192 "Error in PEERSTORE monitoring\n");
13193}

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

13198{
13200 "Done with initial PEERSTORE iteration during monitoring\n");
13201}

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

13213{
13214 struct TransportClient *tc = cls;
13215 const struct GNUNET_PeerIdentity *my_identity;
13216 struct PeerRequest *pr;
13217
13218 if (CT_NONE == tc->type)
13219 {
13220 tc->type = CT_APPLICATION;
13221 tc->details.application.requests =
13223 }
13224 if (CT_APPLICATION != tc->type)
13225 {
13226 GNUNET_break (0);
13228 return;
13229 }
13231 if (NULL == my_identity)
13232 {
13234 "Still waiting for own identity!\n");
13236 return;
13237 }
13239 "Client suggested we talk to %s with preference %d at rate %u\n",
13240 GNUNET_i2s (&msg->peer),
13241 (int) ntohl (msg->pk),
13242 (int) ntohl (msg->bw.value__));
13243 if (0 == GNUNET_memcmp (my_identity, &msg->peer))
13244 {
13246 "Client suggested connection to ourselves, ignoring...\n");
13248 return;
13249 }
13250 pr = GNUNET_new (struct PeerRequest);
13251 pr->tc = tc;
13252 pr->pid = msg->peer;
13253 pr->bw = msg->bw;
13254 pr->pk = ntohl (msg->pk);
13256 tc->details.application.requests,
13257 &pr->pid,
13258 pr,
13260 {
13261 GNUNET_break (0);
13262 GNUNET_free (pr);
13264 return;
13265 }
13266 pr->nc =
13268 GNUNET_YES,
13269 "peerstore",
13270 NULL,
13273 NULL,
13275 NULL,
13277 pr);
13279}

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

13293{
13294 (void) cls;
13296 return GNUNET_OK;
13297}

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

13310{
13311 struct TransportClient *tc = cls;
13312 struct Queue *q;
13313
13314 q = find_queue (&m->peer, (const char *) &m[1]);
13315 if (NULL == q)
13316 {
13317 suggest_to_connect (&m->peer, (const char *) &m[1]);
13318 }
13319 else
13320 start_address_validation (&m->peer, (const char *) &m[1]);
13322}

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

13337{
13338 struct Neighbour *neighbour = value;
13339
13340 (void) cls;
13341 (void) pid;
13342 GNUNET_break (0); // should this ever happen?
13343 free_neighbour (neighbour, GNUNET_YES);
13344
13345 return GNUNET_OK;
13346}

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

13361{
13362 struct DistanceVector *dv = value;
13363
13364 (void) cls;
13365 (void) pid;
13366 free_dv_route (dv);
13367
13368 return GNUNET_OK;
13369}

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

13384{
13385 struct ValidationState *vs = value;
13386
13387 (void) cls;
13388 (void) pid;
13390 return GNUNET_OK;
13391}

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

13404{
13405 struct PendingAcknowledgement *pa = value;
13406
13407 (void) cls;
13408 (void) key;
13410 return GNUNET_OK;
13411}

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

13426{
13427 struct AcknowledgementCummulator *ac = value;
13428
13429 (void) cls;
13430 (void) pid;
13432 GNUNET_free (ac);
13433 return GNUNET_OK;
13434}

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

13561{
13562 switch (type)
13563 {
13564 case CT_CORE:
13565 return "CORE";
13566 case CT_MONITOR:
13567 return "MONITOR";
13568 case CT_COMMUNICATOR:
13569 return "COMMUNICATOR";
13570 case CT_APPLICATION:
13571 return "APPLICATION";
13572 default:
13573 return "UNKNOWN";
13574 }
13575}

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

13580{
13582
13584 "Shutdown task executed\n");
13585 if (NULL != clients_head)
13586 {
13587 for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
13588 {
13590 "Client still connected: %s\n",
13591 get_client_type_name (tc->type));
13592 }
13593 }
13594 else
13595 do_shutdown (cls);
13596
13597}

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

13607{
13608 struct UpdateHelloFromPidCtx *pc = cls;
13609
13610 if (GNUNET_OK != success)
13611 {
13613 "Failed to store our new hello with peerstore\n");
13614 }
13615 GNUNET_free (pc);
13617 "Stored our new hello with peerstore\n");
13618}

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

13625{
13627 "%s\n", uri);
13628}

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

13644{
13645 const struct GNUNET_PeerIdentity *my_identity;
13646 struct GNUNET_MQ_Envelope *env;
13647 const struct GNUNET_MessageHeader *msg;
13648 struct UpdateHelloFromPidCtx *sc;
13649 struct GNUNET_HELLO_Builder *nbuilder;
13650 struct GNUNET_PeerIdentity npid;
13651
13654
13655 if (NULL == GST_my_hello)
13658 "My current identity is `%s'\n",
13670 nbuilder = GNUNET_HELLO_builder_from_parser (parser,
13671 &npid);
13672 if (GNUNET_NO ==
13674 {
13676 "New PID from PILS is derived from address list inconsistent with ours. Ignoring...\n");
13678 "Proposed address list:\n");
13681 "Current address list:\n");
13683 GNUNET_HELLO_builder_free (nbuilder);
13684 return;
13685 }
13687 GST_my_hello = nbuilder;
13689 "My new identity is `%s'\n",
13695 msg,
13697 sc);
13698 GNUNET_free (env);
13699}

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

13713{
13714 (void) cls;
13715 (void) service;
13716 /* setup globals */
13719 GST_cfg = c;
13727 GNUNET_YES);
13732 // TODO check for all uses of GST_my_hello that it is not used uninitialized
13734 "transport",
13735 "USE_BURST_NAT");
13736 if (GNUNET_SYSERR == use_burst)
13738 "Could not configure burst nat use. Default to no.\n");
13744 "transport",
13745 0,
13746 0,
13747 NULL,
13748 0,
13749 NULL,
13750 NULL,
13751 NULL);
13752 if (NULL == peerstore)
13753 {
13754 GNUNET_break (0);
13756 return;
13757 }
13760 NULL); // FIXME we need to wait for
13761 // our first peer id before
13762 // we can start the service
13763 // completely - PILS in turn
13764 // waits for the first
13765 // addresses from the
13766 // communicators in order to
13767 // be able to generate a
13768 // peer id
13769 if (NULL == pils)
13770 {
13771 GNUNET_break (0);
13773 return;
13774 }
13775}

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().