aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-service-tng.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/gnunet-service-tng.c')
-rw-r--r--src/transport/gnunet-service-tng.c294
1 files changed, 159 insertions, 135 deletions
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c
index ecff6b6e1..342b4c2bc 100644
--- a/src/transport/gnunet-service-tng.c
+++ b/src/transport/gnunet-service-tng.c
@@ -33,14 +33,6 @@
33 * transport-to-transport traffic) 33 * transport-to-transport traffic)
34 * 34 *
35 * Implement next: 35 * Implement next:
36 * - address validation: what is our plan here?
37 * #1 Peerstore only gets 'validated' addresses
38 * #2 transport should use validation to also establish
39 * effective flow control (for uni-directional transports!)
40 * #3 only validated addresses are selected for scheduling; that
41 * also ensures we know the RTT
42 * #4 to ensure flow control and RTT are OK, we always do the
43 * 'validation', even if address comes from PEERSTORE???
44 * - ACK handling / retransmission 36 * - ACK handling / retransmission
45 * - track RTT, distance, loss, etc. 37 * - track RTT, distance, loss, etc.
46 * - DV data structures: 38 * - DV data structures:
@@ -67,7 +59,7 @@
67 * Design realizations / discussion: 59 * Design realizations / discussion:
68 * - communicators do flow control by calling MQ "notify sent" 60 * - communicators do flow control by calling MQ "notify sent"
69 * when 'ready'. They determine flow implicitly (i.e. TCP blocking) 61 * when 'ready'. They determine flow implicitly (i.e. TCP blocking)
70 * or explicitly via background channel FC ACKs. As long as the 62 * or explicitly via backchannel FC ACKs. As long as the
71 * channel is not full, they may 'notify sent' even if the other 63 * channel is not full, they may 'notify sent' even if the other
72 * peer has not yet confirmed receipt. The other peer confirming 64 * peer has not yet confirmed receipt. The other peer confirming
73 * is _only_ for FC, not for more reliable transmission; reliable 65 * is _only_ for FC, not for more reliable transmission; reliable
@@ -1236,7 +1228,6 @@ enum PendingMessageType
1236 */ 1228 */
1237 PMT_ACKNOWLEDGEMENT = 3 1229 PMT_ACKNOWLEDGEMENT = 3
1238 1230
1239
1240}; 1231};
1241 1232
1242 1233
@@ -1658,11 +1649,6 @@ struct ValidationState
1658 struct GNUNET_PEERSTORE_StoreContext *sc; 1649 struct GNUNET_PEERSTORE_StoreContext *sc;
1659 1650
1660 /** 1651 /**
1661 * Network type (presumably) associated with @e address. NEEDED?
1662 */
1663 enum GNUNET_NetworkType nt;
1664
1665 /**
1666 * We are technically ready to send the challenge, but we are waiting for 1652 * We are technically ready to send the challenge, but we are waiting for
1667 * the respective queue to become available for transmission. 1653 * the respective queue to become available for transmission.
1668 */ 1654 */
@@ -1671,8 +1657,6 @@ struct ValidationState
1671}; 1657};
1672 1658
1673 1659
1674
1675
1676/** 1660/**
1677 * Head of linked list of all clients to this service. 1661 * Head of linked list of all clients to this service.
1678 */ 1662 */
@@ -2133,7 +2117,7 @@ core_send_connect_info (struct TransportClient *tc,
2133 cim->quota_out = quota_out; 2117 cim->quota_out = quota_out;
2134 cim->id = *pid; 2118 cim->id = *pid;
2135 GNUNET_MQ_send (tc->mq, 2119 GNUNET_MQ_send (tc->mq,
2136 env); 2120 env);
2137} 2121}
2138 2122
2139 2123
@@ -2967,6 +2951,15 @@ static void
2967route_message (const struct GNUNET_PeerIdentity *target, 2951route_message (const struct GNUNET_PeerIdentity *target,
2968 struct GNUNET_MessageHeader *hdr) 2952 struct GNUNET_MessageHeader *hdr)
2969{ 2953{
2954 // FIXME: this one is tricky:
2955 // - we could try a direct, reliable channel
2956 // - if that is unavailable / for load balancing, we may try:
2957 // * multiple (?) direct unreliable channels - depending on loss rate?
2958 // * some (?) DV channels - if above unavailable / too lossy?
2959 // * _random_ other peers ("broadcasting") in hope of *discovering*
2960 // a path back! - if all else fails
2961 // => need more on DV first!
2962
2970 // FIXME: send hdr to target, free hdr (possibly using DV, possibly broadcasting) 2963 // FIXME: send hdr to target, free hdr (possibly using DV, possibly broadcasting)
2971 GNUNET_free (hdr); 2964 GNUNET_free (hdr);
2972} 2965}
@@ -3096,20 +3089,29 @@ static void
3096store_pi (void *cls) 3089store_pi (void *cls)
3097{ 3090{
3098 struct AddressListEntry *ale = cls; 3091 struct AddressListEntry *ale = cls;
3092 void *addr;
3093 size_t addr_len;
3099 struct GNUNET_TIME_Absolute expiration; 3094 struct GNUNET_TIME_Absolute expiration;
3100 3095
3101 ale->st = NULL; 3096 ale->st = NULL;
3102 expiration = GNUNET_TIME_relative_to_absolute (ale->expiration); 3097 expiration = GNUNET_TIME_relative_to_absolute (ale->expiration);
3098 GNUNET_HELLO_sign_address (ale->address,
3099 ale->nt,
3100 expiration,
3101 GST_my_private_key,
3102 &addr,
3103 &addr_len);
3103 ale->sc = GNUNET_PEERSTORE_store (peerstore, 3104 ale->sc = GNUNET_PEERSTORE_store (peerstore,
3104 "transport", 3105 "transport",
3105 &GST_my_identity, 3106 &GST_my_identity,
3106 GNUNET_HELLO_PEERSTORE_KEY, 3107 GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY,
3107 ale->address, 3108 addr,
3108 strlen (ale->address) + 1, 3109 addr_len,
3109 expiration, 3110 expiration,
3110 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE, 3111 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
3111 &peerstore_store_own_cb, 3112 &peerstore_store_own_cb,
3112 ale); 3113 ale);
3114 GNUNET_free (addr);
3113 if (NULL == ale->sc) 3115 if (NULL == ale->sc)
3114 { 3116 {
3115 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 3117 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -3359,7 +3361,7 @@ send_fragment_ack (struct ReassemblyContext *rc)
3359 ack->reassembly_timeout 3361 ack->reassembly_timeout
3360 = GNUNET_TIME_relative_hton (GNUNET_TIME_absolute_get_remaining (rc->reassembly_timeout)); 3362 = GNUNET_TIME_relative_hton (GNUNET_TIME_absolute_get_remaining (rc->reassembly_timeout));
3361 route_message (&rc->neighbour->pid, 3363 route_message (&rc->neighbour->pid,
3362 &ack->header); 3364 &ack->header);
3363 rc->avg_ack_delay = GNUNET_TIME_UNIT_ZERO; 3365 rc->avg_ack_delay = GNUNET_TIME_UNIT_ZERO;
3364 rc->num_acks = 0; 3366 rc->num_acks = 0;
3365 rc->extra_acks = 0LLU; 3367 rc->extra_acks = 0LLU;
@@ -3425,10 +3427,10 @@ handle_fragment_box (void *cls,
3425 rc, 3427 rc,
3426 rc->reassembly_timeout.abs_value_us); 3428 rc->reassembly_timeout.abs_value_us);
3427 GNUNET_assert (GNUNET_OK == 3429 GNUNET_assert (GNUNET_OK ==
3428 GNUNET_CONTAINER_multishortmap_put (n->reassembly_map, 3430 GNUNET_CONTAINER_multishortmap_put (n->reassembly_map,
3429 &rc->msg_uuid, 3431 &rc->msg_uuid,
3430 rc, 3432 rc,
3431 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 3433 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
3432 target = (char *) &rc[1]; 3434 target = (char *) &rc[1];
3433 rc->bitfield = (uint8_t *) (target + rc->msg_size); 3435 rc->bitfield = (uint8_t *) (target + rc->msg_size);
3434 rc->msg_missing = rc->msg_size; 3436 rc->msg_missing = rc->msg_size;
@@ -3601,14 +3603,14 @@ handle_reliability_box (void *cls,
3601 ack->header.size = htons (sizeof (*ack) + 3603 ack->header.size = htons (sizeof (*ack) +
3602 sizeof (struct GNUNET_ShortHashCode)); 3604 sizeof (struct GNUNET_ShortHashCode));
3603 memcpy (&ack[1], 3605 memcpy (&ack[1],
3604 &rb->msg_uuid, 3606 &rb->msg_uuid,
3605 sizeof (struct GNUNET_ShortHashCode)); 3607 sizeof (struct GNUNET_ShortHashCode));
3606 route_message (&cmc->im.sender, 3608 route_message (&cmc->im.sender,
3607 &ack->header); 3609 &ack->header);
3608 } 3610 }
3609 /* continue with inner message */ 3611 /* continue with inner message */
3610 demultiplex_with_cmc (cmc, 3612 demultiplex_with_cmc (cmc,
3611 inbox); 3613 inbox);
3612} 3614}
3613 3615
3614 3616
@@ -3846,8 +3848,37 @@ handle_validation_challenge (void *cls,
3846 const struct TransportValidationChallenge *tvc) 3848 const struct TransportValidationChallenge *tvc)
3847{ 3849{
3848 struct CommunicatorMessageContext *cmc = cls; 3850 struct CommunicatorMessageContext *cmc = cls;
3851 struct TransportValidationResponse *tvr;
3852
3853 if (cmc->total_hops > 0)
3854 {
3855 /* DV routing is not allowed for validation challenges! */
3856 GNUNET_break_op (0);
3857 finish_cmc_handling (cmc);
3858 return;
3859 }
3860 tvr = GNUNET_new (struct TransportValidationResponse);
3861 tvr->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE);
3862 tvr->header.size = htons (sizeof (*tvr));
3863 tvr->challenge = tvc->challenge;
3864 tvr->origin_time = tvc->sender_time;
3865 tvr->validity_duration = cmc->im.expected_address_validity;
3866 {
3867 /* create signature */
3868 struct TransportValidationPS tvp = {
3869 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE),
3870 .purpose.size = htonl (sizeof (tvp)),
3871 .validity_duration = tvr->validity_duration,
3872 .challenge = tvc->challenge
3873 };
3849 3874
3850 // FIXME: sign challenge and try to get it back to the origin! 3875 GNUNET_assert (GNUNET_OK ==
3876 GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
3877 &tvp.purpose,
3878 &tvr->signature));
3879 }
3880 route_message (&cmc->im.sender,
3881 &tvr->header);
3851 finish_cmc_handling (cmc); 3882 finish_cmc_handling (cmc);
3852} 3883}
3853 3884
@@ -4054,15 +4085,14 @@ handle_validation_response (void *cls,
4054 vs->sc = GNUNET_PEERSTORE_store (peerstore, 4085 vs->sc = GNUNET_PEERSTORE_store (peerstore,
4055 "transport", 4086 "transport",
4056 &cmc->im.sender, 4087 &cmc->im.sender,
4057 GNUNET_HELLO_PEERSTORE_KEY, 4088 GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY,
4058 vs->address, 4089 vs->address,
4059 strlen (vs->address) + 1, 4090 strlen (vs->address) + 1,
4060 vs->valid_until, 4091 vs->valid_until,
4061 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE, 4092 GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
4062 &peerstore_store_validation_cb, 4093 &peerstore_store_validation_cb,
4063 vs); 4094 vs);
4064 // FIXME: now that we know that the address is *valid*, 4095 // FIXME: should we find the matching queue and update the RTT?
4065 // do we need to trigger _using_ it for something?
4066 finish_cmc_handling (cmc); 4096 finish_cmc_handling (cmc);
4067} 4097}
4068 4098
@@ -5183,97 +5213,6 @@ handle_queue_create_fail (void *cls,
5183 5213
5184 5214
5185/** 5215/**
5186 * Function called by PEERSTORE for each matching record.
5187 *
5188 * @param cls closure
5189 * @param record peerstore record information
5190 * @param emsg error message, or NULL if no errors
5191 */
5192static void
5193handle_hello (void *cls,
5194 const struct GNUNET_PEERSTORE_Record *record,
5195 const char *emsg)
5196{
5197 struct PeerRequest *pr = cls;
5198 const char *val;
5199
5200 if (NULL != emsg)
5201 {
5202 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
5203 "Got failure from PEERSTORE: %s\n",
5204 emsg);
5205 return;
5206 }
5207 val = record->value;
5208 if ( (0 == record->value_size) ||
5209 ('\0' != val[record->value_size - 1]) )
5210 {
5211 GNUNET_break (0);
5212 return;
5213 }
5214 suggest_to_connect (&pr->pid,
5215 (const char *) record->value);
5216}
5217
5218
5219/**
5220 * We have received a `struct ExpressPreferenceMessage` from an application client.
5221 *
5222 * @param cls handle to the client
5223 * @param msg the start message
5224 */
5225static void
5226handle_suggest (void *cls,
5227 const struct ExpressPreferenceMessage *msg)
5228{
5229 struct TransportClient *tc = cls;
5230 struct PeerRequest *pr;
5231
5232 if (CT_NONE == tc->type)
5233 {
5234 tc->type = CT_APPLICATION;
5235 tc->details.application.requests
5236 = GNUNET_CONTAINER_multipeermap_create (16,
5237 GNUNET_YES);
5238 }
5239 if (CT_APPLICATION != tc->type)
5240 {
5241 GNUNET_break (0);
5242 GNUNET_SERVICE_client_drop (tc->client);
5243 return;
5244 }
5245 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5246 "Client suggested we talk to %s with preference %d at rate %u\n",
5247 GNUNET_i2s (&msg->peer),
5248 (int) ntohl (msg->pk),
5249 (int) ntohl (msg->bw.value__));
5250 pr = GNUNET_new (struct PeerRequest);
5251 pr->tc = tc;
5252 pr->pid = msg->peer;
5253 pr->bw = msg->bw;
5254 pr->pk = (enum GNUNET_MQ_PreferenceKind) ntohl (msg->pk);
5255 if (GNUNET_YES !=
5256 GNUNET_CONTAINER_multipeermap_put (tc->details.application.requests,
5257 &pr->pid,
5258 pr,
5259 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
5260 {
5261 GNUNET_break (0);
5262 GNUNET_free (pr);
5263 GNUNET_SERVICE_client_drop (tc->client);
5264 return;
5265 }
5266 pr->wc = GNUNET_PEERSTORE_watch (peerstore,
5267 "transport",
5268 &pr->pid,
5269 GNUNET_HELLO_PEERSTORE_KEY,
5270 &handle_hello,
5271 pr);
5272 GNUNET_SERVICE_client_continue (tc->client);
5273}
5274
5275
5276/**
5277 * We have received a `struct ExpressPreferenceMessage` from an application client. 5216 * We have received a `struct ExpressPreferenceMessage` from an application client.
5278 * 5217 *
5279 * @param cls handle to the client 5218 * @param cls handle to the client
@@ -5374,13 +5313,11 @@ check_known_address (void *cls,
5374 * @param pid peer the @a address is for 5313 * @param pid peer the @a address is for
5375 * @param address an address to reach @a pid (presumably) 5314 * @param address an address to reach @a pid (presumably)
5376 * @param expiration when did @a pid claim @a address will become invalid 5315 * @param expiration when did @a pid claim @a address will become invalid
5377 * @param nt network type of @a address
5378 */ 5316 */
5379static void 5317static void
5380start_address_validation (const struct GNUNET_PeerIdentity *pid, 5318start_address_validation (const struct GNUNET_PeerIdentity *pid,
5381 const char *address, 5319 const char *address,
5382 struct GNUNET_TIME_Absolute expiration, 5320 struct GNUNET_TIME_Absolute expiration)
5383 enum GNUNET_NetworkType nt)
5384{ 5321{
5385 struct GNUNET_TIME_Absolute now; 5322 struct GNUNET_TIME_Absolute now;
5386 struct ValidationState *vs; 5323 struct ValidationState *vs;
@@ -5389,10 +5326,8 @@ start_address_validation (const struct GNUNET_PeerIdentity *pid,
5389 .vs = NULL 5326 .vs = NULL
5390 }; 5327 };
5391 5328
5392
5393 if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us) 5329 if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
5394 return; /* expired */ 5330 return; /* expired */
5395
5396 (void) GNUNET_CONTAINER_multipeermap_get_multiple (validation_map, 5331 (void) GNUNET_CONTAINER_multipeermap_get_multiple (validation_map,
5397 pid, 5332 pid,
5398 &check_known_address, 5333 &check_known_address,
@@ -5421,7 +5356,6 @@ start_address_validation (const struct GNUNET_PeerIdentity *pid,
5421 &vs->challenge, 5356 &vs->challenge,
5422 sizeof (vs->challenge)); 5357 sizeof (vs->challenge));
5423 vs->address = GNUNET_strdup (address); 5358 vs->address = GNUNET_strdup (address);
5424 vs->nt = nt;
5425 GNUNET_assert (GNUNET_YES == 5359 GNUNET_assert (GNUNET_YES ==
5426 GNUNET_CONTAINER_multipeermap_put (validation_map, 5360 GNUNET_CONTAINER_multipeermap_put (validation_map,
5427 &vs->pid, 5361 &vs->pid,
@@ -5433,6 +5367,98 @@ start_address_validation (const struct GNUNET_PeerIdentity *pid,
5433 5367
5434 5368
5435/** 5369/**
5370 * Function called by PEERSTORE for each matching record.
5371 *
5372 * @param cls closure
5373 * @param record peerstore record information
5374 * @param emsg error message, or NULL if no errors
5375 */
5376static void
5377handle_hello (void *cls,
5378 const struct GNUNET_PEERSTORE_Record *record,
5379 const char *emsg)
5380{
5381 struct PeerRequest *pr = cls;
5382 const char *val;
5383
5384 if (NULL != emsg)
5385 {
5386 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
5387 "Got failure from PEERSTORE: %s\n",
5388 emsg);
5389 return;
5390 }
5391 val = record->value;
5392 if ( (0 == record->value_size) ||
5393 ('\0' != val[record->value_size - 1]) )
5394 {
5395 GNUNET_break (0);
5396 return;
5397 }
5398 start_address_validation (&pr->pid,
5399 (const char *) record->value,
5400 record->expiry);
5401}
5402
5403
5404/**
5405 * We have received a `struct ExpressPreferenceMessage` from an application client.
5406 *
5407 * @param cls handle to the client
5408 * @param msg the start message
5409 */
5410static void
5411handle_suggest (void *cls,
5412 const struct ExpressPreferenceMessage *msg)
5413{
5414 struct TransportClient *tc = cls;
5415 struct PeerRequest *pr;
5416
5417 if (CT_NONE == tc->type)
5418 {
5419 tc->type = CT_APPLICATION;
5420 tc->details.application.requests
5421 = GNUNET_CONTAINER_multipeermap_create (16,
5422 GNUNET_YES);
5423 }
5424 if (CT_APPLICATION != tc->type)
5425 {
5426 GNUNET_break (0);
5427 GNUNET_SERVICE_client_drop (tc->client);
5428 return;
5429 }
5430 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5431 "Client suggested we talk to %s with preference %d at rate %u\n",
5432 GNUNET_i2s (&msg->peer),
5433 (int) ntohl (msg->pk),
5434 (int) ntohl (msg->bw.value__));
5435 pr = GNUNET_new (struct PeerRequest);
5436 pr->tc = tc;
5437 pr->pid = msg->peer;
5438 pr->bw = msg->bw;
5439 pr->pk = (enum GNUNET_MQ_PreferenceKind) ntohl (msg->pk);
5440 if (GNUNET_YES !=
5441 GNUNET_CONTAINER_multipeermap_put (tc->details.application.requests,
5442 &pr->pid,
5443 pr,
5444 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
5445 {
5446 GNUNET_break (0);
5447 GNUNET_free (pr);
5448 GNUNET_SERVICE_client_drop (tc->client);
5449 return;
5450 }
5451 pr->wc = GNUNET_PEERSTORE_watch (peerstore,
5452 "transport",
5453 &pr->pid,
5454 GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY,
5455 &handle_hello,
5456 pr);
5457 GNUNET_SERVICE_client_continue (tc->client);
5458}
5459
5460
5461/**
5436 * Given another peers address, consider checking it for validity 5462 * Given another peers address, consider checking it for validity
5437 * and then adding it to the Peerstore. 5463 * and then adding it to the Peerstore.
5438 * 5464 *
@@ -5465,8 +5491,7 @@ handle_address_consider_verify (void *cls,
5465 } 5491 }
5466 start_address_validation (&hdr->peer, 5492 start_address_validation (&hdr->peer,
5467 address, 5493 address,
5468 expiration, 5494 expiration);
5469 nt);
5470 GNUNET_free (address); 5495 GNUNET_free (address);
5471 GNUNET_SERVICE_client_continue (tc->client); 5496 GNUNET_SERVICE_client_continue (tc->client);
5472} 5497}
@@ -5504,8 +5529,7 @@ handle_request_hello_validation (void *cls,
5504 5529
5505 start_address_validation (&m->peer, 5530 start_address_validation (&m->peer,
5506 (const char *) &m[1], 5531 (const char *) &m[1],
5507 GNUNET_TIME_absolute_ntoh (m->expiration), 5532 GNUNET_TIME_absolute_ntoh (m->expiration));
5508 (enum GNUNET_NetworkType) ntohl (m->nt));
5509 GNUNET_SERVICE_client_continue (tc->client); 5533 GNUNET_SERVICE_client_continue (tc->client);
5510} 5534}
5511 5535