aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-02-16 09:25:37 +0000
committerChristian Grothoff <christian@grothoff.org>2010-02-16 09:25:37 +0000
commit71bf2d9735a07c7d827b275d0e1dd253210139d9 (patch)
tree474fdd39200aad7a2e6c0520fbdeba20778a6b90 /src
parente9656b2a24386a7f7bd92c8596e5333337f7b30c (diff)
downloadgnunet-71bf2d9735a07c7d827b275d0e1dd253210139d9.tar.gz
gnunet-71bf2d9735a07c7d827b275d0e1dd253210139d9.zip
avoid linked list traversal, more code clean up
Diffstat (limited to 'src')
-rw-r--r--src/transport/gnunet-service-transport.c179
1 files changed, 91 insertions, 88 deletions
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c
index 239ba9ca6..4c94e2939 100644
--- a/src/transport/gnunet-service-transport.c
+++ b/src/transport/gnunet-service-transport.c
@@ -45,6 +45,12 @@
45#include "transport.h" 45#include "transport.h"
46 46
47/** 47/**
48 * Should we do some additional checks (to validate behavior
49 * of clients)?
50 */
51#define EXTRA_CHECKS GNUNET_YES
52
53/**
48 * How many messages can we have pending for a given client process 54 * How many messages can we have pending for a given client process
49 * before we start to drop incoming messages? We typically should 55 * before we start to drop incoming messages? We typically should
50 * have only one client and so this would be the primary buffer for 56 * have only one client and so this would be the primary buffer for
@@ -164,24 +170,20 @@ struct ForeignAddressList
164 struct GNUNET_TIME_Absolute timeout; 170 struct GNUNET_TIME_Absolute timeout;
165 171
166 /** 172 /**
167 * Is this plugin currently connected? The first time we transmit 173 * Are we currently connected via this address? The first time we
168 * or send data to a peer via a particular plugin, we set this to 174 * successfully transmit or receive data to a peer via a particular
169 * GNUNET_YES. If we later get an error (disconnect notification or 175 * address, we set this to GNUNET_YES. If we later get an error
170 * transmission failure), we set it back to GNUNET_NO. Each time 176 * (disconnect notification, transmission failure, timeout), we set
171 * the value is set to GNUNET_YES, we increment the 177 * it back to GNUNET_NO.
172 * "connect_attempts" counter. If that one reaches a particular
173 * threshold, we consider the address to not be working properly at
174 * this time and remove it from the eligible list.
175 */ 178 */
176 int connected; 179 int connected;
177 180
178 /** 181 /**
179 * Is this plugin ready to transmit to the specific target? 182 * Is this plugin currently busy transmitting to the specific target?
180 * GNUNET_NO if not. Initially, all plugins are marked ready. If a 183 * GNUNET_NO if not (initial, default state is GNUNET_NO). Internal
181 * transmission is in progress, "transmit_ready" is set to 184 * messages do not count as 'in transmit'.
182 * GNUNET_NO.
183 */ 185 */
184 int transmit_ready; 186 int in_transmit;
185 187
186 /** 188 /**
187 * Has this address been validated yet? 189 * Has this address been validated yet?
@@ -189,7 +191,9 @@ struct ForeignAddressList
189 int validated; 191 int validated;
190 192
191 /** 193 /**
192 * How often have we tried to connect using this plugin? 194 * How often have we tried to connect using this plugin? Used to
195 * discriminate against addresses that do not work well.
196 * FIXME: not yet used, but should be!
193 */ 197 */
194 unsigned int connect_attempts; 198 unsigned int connect_attempts;
195 199
@@ -290,11 +294,16 @@ struct MessageQueue
290{ 294{
291 295
292 /** 296 /**
293 * This is a linked list. 297 * This is a doubly linked list.
294 */ 298 */
295 struct MessageQueue *next; 299 struct MessageQueue *next;
296 300
297 /** 301 /**
302 * This is a doubly linked list.
303 */
304 struct MessageQueue *prev;
305
306 /**
298 * The message(s) we want to transmit, GNUNET_MessageHeader(s) 307 * The message(s) we want to transmit, GNUNET_MessageHeader(s)
299 * stuck together in memory. Allocated at the end of this struct. 308 * stuck together in memory. Allocated at the end of this struct.
300 */ 309 */
@@ -368,12 +377,6 @@ struct ReadyList
368 */ 377 */
369 struct ForeignAddressList *addresses; 378 struct ForeignAddressList *addresses;
370 379
371 /**
372 * Is the plugin represented by this entry currently connected to
373 * the respective peer?
374 */
375 int connected;
376
377}; 380};
378 381
379 382
@@ -395,10 +398,16 @@ struct NeighborList
395 struct ReadyList *plugins; 398 struct ReadyList *plugins;
396 399
397 /** 400 /**
398 * List of messages we would like to send to this peer; 401 * Head of list of messages we would like to send to this peer;
399 * must contain at most one message per client. 402 * must contain at most one message per client.
400 */ 403 */
401 struct MessageQueue *messages; 404 struct MessageQueue *messages_head;
405
406 /**
407 * Tail of list of messages we would like to send to this peer; must
408 * contain at most one message per client.
409 */
410 struct MessageQueue *messages_tail;
402 411
403 /** 412 /**
404 * Identity of this neighbor. 413 * Identity of this neighbor.
@@ -429,9 +438,12 @@ struct NeighborList
429 * over multiple transports. This value reflects how long it took 438 * over multiple transports. This value reflects how long it took
430 * us to receive a response when SENDING via this particular 439 * us to receive a response when SENDING via this particular
431 * transport/neighbor/address combination! 440 * transport/neighbor/address combination!
432 * FIXME: why is this NBO? 441 *
442 * FIXME: we need to periodically send PINGs to update this
443 * latency (at least more often than the current "huge" (11h?)
444 * update interval).
433 */ 445 */
434 struct GNUNET_TIME_RelativeNBO latency; 446 struct GNUNET_TIME_Relative latency;
435 447
436 /** 448 /**
437 * How many bytes have we received since the "last_quota_update" 449 * How many bytes have we received since the "last_quota_update"
@@ -1023,25 +1035,25 @@ transmit_send_continuation (void *cls,
1023 1035
1024 if (result == GNUNET_OK) 1036 if (result == GNUNET_OK)
1025 { 1037 {
1026 mq->specific_address->timeout = 1038 if (mq->specific_address != NULL)
1027 GNUNET_TIME_relative_to_absolute 1039 {
1028 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); 1040 mq->specific_address->timeout =
1041 GNUNET_TIME_relative_to_absolute
1042 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1043 mq->specific_address->connected = GNUNET_YES;
1044 }
1029 } 1045 }
1030 else 1046 else
1031 { 1047 {
1032 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1048 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1033 "Transmission to peer `%s' failed, marking connection as down.\n", 1049 "Transmission to peer `%s' failed, marking connection as down.\n",
1034 GNUNET_i2s (target)); 1050 GNUNET_i2s (target));
1035 mq->specific_address->connected = GNUNET_NO; 1051 if (mq->specific_address != NULL)
1036 } 1052 mq->specific_address->connected = GNUNET_NO;
1037 if (!mq->internal_msg)
1038 {
1039#if DEBUG_TRANSPORT
1040 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1041 "Setting transmit_ready on transport!\n");
1042#endif
1043 mq->specific_address->transmit_ready = GNUNET_YES;
1044 } 1053 }
1054 if ( (! mq->internal_msg) &&
1055 (mq->specific_address != NULL) )
1056 mq->specific_address->in_transmit = GNUNET_NO;
1045 1057
1046 if (mq->client != NULL) 1058 if (mq->client != NULL)
1047 { 1059 {
@@ -1106,7 +1118,7 @@ find_ready_address(struct NeighborList *neighbor)
1106 if ( ( (best_address == NULL) || 1118 if ( ( (best_address == NULL) ||
1107 (addresses->connected == GNUNET_YES) || 1119 (addresses->connected == GNUNET_YES) ||
1108 (best_address->connected == GNUNET_NO) ) && 1120 (best_address->connected == GNUNET_NO) ) &&
1109 (addresses->transmit_ready == GNUNET_YES) && 1121 (addresses->in_transmit == GNUNET_NO) &&
1110 ( (best_address == NULL) || 1122 ( (best_address == NULL) ||
1111 (addresses->latency.value < best_address->latency.value)) ) 1123 (addresses->latency.value < best_address->latency.value)) )
1112 best_address = addresses; 1124 best_address = addresses;
@@ -1142,11 +1154,11 @@ try_transmission_to_peer (struct NeighborList *neighbor)
1142 struct ReadyList *rl; 1154 struct ReadyList *rl;
1143 struct MessageQueue *mq; 1155 struct MessageQueue *mq;
1144 1156
1145 if (neighbor->messages == NULL) 1157 if (neighbor->messages_head == NULL)
1146 return; /* nothing to do */ 1158 return; /* nothing to do */
1147 min_latency = GNUNET_TIME_UNIT_FOREVER_REL; 1159 min_latency = GNUNET_TIME_UNIT_FOREVER_REL;
1148 rl = NULL; 1160 rl = NULL;
1149 mq = neighbor->messages; 1161 mq = neighbor->messages_head;
1150 if (mq->specific_address == NULL) 1162 if (mq->specific_address == NULL)
1151 mq->specific_address = find_ready_address(neighbor); 1163 mq->specific_address = find_ready_address(neighbor);
1152 if (mq->specific_address == NULL) 1164 if (mq->specific_address == NULL)
@@ -1159,11 +1171,15 @@ try_transmission_to_peer (struct NeighborList *neighbor)
1159#endif 1171#endif
1160 return; /* nobody ready */ 1172 return; /* nobody ready */
1161 } 1173 }
1174 if (mq->specific_address->connected == GNUNET_NO)
1175 mq->specific_address->connect_attempts++;
1162 rl = mq->specific_address->ready_list; 1176 rl = mq->specific_address->ready_list;
1163 neighbor->messages = mq->next; 1177 GNUNET_CONTAINER_DLL_remove (neighbor->messages_head,
1178 neighbor->messages_tail,
1179 mq);
1164 mq->plugin = rl->plugin; 1180 mq->plugin = rl->plugin;
1165 if (!mq->internal_msg) 1181 if (!mq->internal_msg)
1166 mq->specific_address->transmit_ready = GNUNET_NO; 1182 mq->specific_address->in_transmit = GNUNET_YES;
1167#if DEBUG_TRANSPORT 1183#if DEBUG_TRANSPORT
1168 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1184 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1169 "Sending message of size %u for `%4s' to `%s' via plugin `%s'\n", 1185 "Sending message of size %u for `%4s' to `%s' via plugin `%s'\n",
@@ -1194,7 +1210,8 @@ try_transmission_to_peer (struct NeighborList *neighbor)
1194 * @param priority how important is the message 1210 * @param priority how important is the message
1195 * @param message_buf message(s) to send GNUNET_MessageHeader(s) 1211 * @param message_buf message(s) to send GNUNET_MessageHeader(s)
1196 * @param message_buf_size total size of all messages in message_buf 1212 * @param message_buf_size total size of all messages in message_buf
1197 * @param is_internal is this an internal message 1213 * @param is_internal is this an internal message; these are pre-pended and
1214 * also do not count for plugins being "ready" to transmit
1198 * @param neighbor handle to the neighbor for transmission 1215 * @param neighbor handle to the neighbor for transmission
1199 */ 1216 */
1200static void 1217static void
@@ -1206,12 +1223,12 @@ transmit_to_peer (struct TransportClient *client,
1206 int is_internal, struct NeighborList *neighbor) 1223 int is_internal, struct NeighborList *neighbor)
1207{ 1224{
1208 struct MessageQueue *mq; 1225 struct MessageQueue *mq;
1209 struct MessageQueue *mqe;
1210 1226
1227#if EXTRA_CHECKS
1211 if (client != NULL) 1228 if (client != NULL)
1212 { 1229 {
1213 /* check for duplicate submission */ 1230 /* check for duplicate submission */
1214 mq = neighbor->messages; 1231 mq = neighbor->messages_head;
1215 while (NULL != mq) 1232 while (NULL != mq)
1216 { 1233 {
1217 if (mq->client == client) 1234 if (mq->client == client)
@@ -1224,6 +1241,7 @@ transmit_to_peer (struct TransportClient *client,
1224 mq = mq->next; 1241 mq = mq->next;
1225 } 1242 }
1226 } 1243 }
1244#endif
1227 mq = GNUNET_malloc (sizeof (struct MessageQueue) + message_buf_size); 1245 mq = GNUNET_malloc (sizeof (struct MessageQueue) + message_buf_size);
1228 mq->specific_address = peer_address; 1246 mq->specific_address = peer_address;
1229 mq->client = client; 1247 mq->client = client;
@@ -1234,30 +1252,15 @@ transmit_to_peer (struct TransportClient *client,
1234 mq->internal_msg = is_internal; 1252 mq->internal_msg = is_internal;
1235 mq->priority = priority; 1253 mq->priority = priority;
1236 1254
1237 if (is_internal) 1255 if (is_internal)
1238 { 1256 GNUNET_CONTAINER_DLL_insert (neighbor->messages_head,
1239 /* append at head */ 1257 neighbor->messages_tail,
1240 mq->next = neighbor->messages; 1258 mq);
1241 neighbor->messages = mq;
1242 }
1243 else 1259 else
1244 { 1260 GNUNET_CONTAINER_DLL_insert_after (neighbor->messages_head,
1245 /* find tail */ 1261 neighbor->messages_tail,
1246 mqe = neighbor->messages; 1262 neighbor->messages_tail,
1247 if (mqe != NULL) 1263 mq);
1248 while (mqe->next != NULL)
1249 mqe = mqe->next;
1250 if (mqe == NULL)
1251 {
1252 /* new head */
1253 neighbor->messages = mq;
1254 }
1255 else
1256 {
1257 /* append */
1258 mqe->next = mq;
1259 }
1260 }
1261 try_transmission_to_peer (neighbor); 1264 try_transmission_to_peer (neighbor);
1262} 1265}
1263 1266
@@ -1609,7 +1612,6 @@ add_peer_address(struct NeighborList *neighbor,
1609 ret->expires = GNUNET_TIME_relative_to_absolute 1612 ret->expires = GNUNET_TIME_relative_to_absolute
1610 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); 1613 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1611 ret->latency = GNUNET_TIME_relative_get_forever(); 1614 ret->latency = GNUNET_TIME_relative_get_forever();
1612 ret->transmit_ready = GNUNET_YES;
1613 ret->timeout = GNUNET_TIME_relative_to_absolute 1615 ret->timeout = GNUNET_TIME_relative_to_absolute
1614 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); 1616 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1615 ret->ready_list = head; 1617 ret->ready_list = head;
@@ -1725,6 +1727,10 @@ check_pending_validation (void *cls,
1725 fal->expires = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION); 1727 fal->expires = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
1726 fal->validated = GNUNET_YES; 1728 fal->validated = GNUNET_YES;
1727 fal->latency = GNUNET_TIME_absolute_get_duration (ve->send_time); 1729 fal->latency = GNUNET_TIME_absolute_get_duration (ve->send_time);
1730 if (n->latency.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
1731 n->latency = fal->latency;
1732 else
1733 n->latency.value = (fal->latency.value + n->latency.value) / 2;
1728 } 1734 }
1729 1735
1730 /* clean up validation entry */ 1736 /* clean up validation entry */
@@ -1854,6 +1860,7 @@ setup_new_neighbor (const struct GNUNET_PeerIdentity *peer)
1854 } 1860 }
1855 tp = tp->next; 1861 tp = tp->next;
1856 } 1862 }
1863 n->latency = GNUNET_TIME_UNIT_FOREVER_REL;
1857 n->timeout_task = GNUNET_SCHEDULER_add_delayed (sched, 1864 n->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
1858 GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 1865 GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1859 &neighbor_timeout_task, n); 1866 &neighbor_timeout_task, n);
@@ -2059,10 +2066,10 @@ run_validation (void *cls,
2059 "HELLO", hello_size, 2066 "HELLO", hello_size,
2060 "PING", sizeof (struct TransportPingMessage)); 2067 "PING", sizeof (struct TransportPingMessage));
2061#endif 2068#endif
2062 transmit_to_peer(NULL, peer_address, 2069 transmit_to_peer (NULL, peer_address,
2063 GNUNET_SCHEDULER_PRIORITY_DEFAULT, 2070 GNUNET_SCHEDULER_PRIORITY_DEFAULT,
2064 message_buf, tsize, 2071 message_buf, tsize,
2065 GNUNET_YES, neighbor); 2072 GNUNET_YES, neighbor);
2066 GNUNET_free(message_buf); 2073 GNUNET_free(message_buf);
2067 return GNUNET_OK; 2074 return GNUNET_OK;
2068} 2075}
@@ -2100,6 +2107,8 @@ add_to_foreign_address_list (void *cls,
2100#endif 2107#endif
2101 fal = add_peer_address (n, tname, addr, addrlen); 2108 fal = add_peer_address (n, tname, addr, addrlen);
2102 } 2109 }
2110 if (fal == NULL)
2111 return GNUNET_OK;
2103 fal->expires = GNUNET_TIME_absolute_max (expiration, 2112 fal->expires = GNUNET_TIME_absolute_max (expiration,
2104 fal->expires); 2113 fal->expires);
2105 fal->validated = GNUNET_YES; 2114 fal->validated = GNUNET_YES;
@@ -2320,8 +2329,7 @@ disconnect_neighbor (struct NeighborList *current_handle, int check)
2320 while (NULL != (rpos = n->plugins)) 2329 while (NULL != (rpos = n->plugins))
2321 { 2330 {
2322 n->plugins = rpos->next; 2331 n->plugins = rpos->next;
2323 if (GNUNET_YES == rpos->connected) 2332 rpos->plugin->api->disconnect (rpos->plugin->api->cls, &n->id);
2324 rpos->plugin->api->disconnect (rpos->plugin->api->cls, &n->id);
2325 2333
2326 while (rpos->addresses != NULL) 2334 while (rpos->addresses != NULL)
2327 { 2335 {
@@ -2333,9 +2341,11 @@ disconnect_neighbor (struct NeighborList *current_handle, int check)
2333 } 2341 }
2334 2342
2335 /* free all messages on the queue */ 2343 /* free all messages on the queue */
2336 while (NULL != (mq = n->messages)) 2344 while (NULL != (mq = n->messages_head))
2337 { 2345 {
2338 n->messages = mq->next; 2346 GNUNET_CONTAINER_DLL_remove (n->messages_head,
2347 n->messages_tail,
2348 mq);
2339 GNUNET_assert (0 == memcmp(&mq->neighbor_id, 2349 GNUNET_assert (0 == memcmp(&mq->neighbor_id,
2340 &n->id, 2350 &n->id,
2341 sizeof(struct GNUNET_PeerIdentity))); 2351 sizeof(struct GNUNET_PeerIdentity)));
@@ -2475,7 +2485,6 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2475 if (message == NULL) 2485 if (message == NULL)
2476 return; /* disconnect of peer already marked down */ 2486 return; /* disconnect of peer already marked down */
2477 n = setup_new_neighbor (peer); 2487 n = setup_new_neighbor (peer);
2478
2479 } 2488 }
2480 service_context = n->plugins; 2489 service_context = n->plugins;
2481 while ((service_context != NULL) && (plugin != service_context->plugin)) 2490 while ((service_context != NULL) && (plugin != service_context->plugin))
@@ -2489,8 +2498,6 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2489 GNUNET_i2s (&n->id)); 2498 GNUNET_i2s (&n->id));
2490#endif 2499#endif
2491 /* TODO: call stats */ 2500 /* TODO: call stats */
2492 if (service_context != NULL)
2493 service_context->connected = GNUNET_NO;
2494 disconnect_neighbor (n, GNUNET_YES); 2501 disconnect_neighbor (n, GNUNET_YES);
2495 return; 2502 return;
2496 } 2503 }
@@ -2498,15 +2505,11 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2498 plugin->short_name, 2505 plugin->short_name,
2499 sender_address, 2506 sender_address,
2500 sender_address_len); 2507 sender_address_len);
2501 if (service_context != NULL) 2508 if (peer_address != NULL)
2502 { 2509 {
2503 if (service_context->connected == GNUNET_NO) 2510 if (peer_address->connected == GNUNET_NO)
2504 { 2511 {
2505 service_context->connected = GNUNET_YES; 2512 peer_address->connected = GNUNET_YES;
2506 /* FIXME: What to do here? Should we use these as well,
2507 to specify some Address in the AddressList should be
2508 available? */
2509 peer_address->transmit_ready = GNUNET_YES;
2510 peer_address->connect_attempts++; 2513 peer_address->connect_attempts++;
2511 } 2514 }
2512 peer_address->timeout 2515 peer_address->timeout
@@ -2557,7 +2560,7 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2557 im = GNUNET_malloc (sizeof (struct InboundMessage) + msize); 2560 im = GNUNET_malloc (sizeof (struct InboundMessage) + msize);
2558 im->header.size = htons (sizeof (struct InboundMessage) + msize); 2561 im->header.size = htons (sizeof (struct InboundMessage) + msize);
2559 im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV); 2562 im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
2560 im->latency = n->latency; 2563 im->latency = GNUNET_TIME_relative_hton (n->latency);
2561 im->peer = *peer; 2564 im->peer = *peer;
2562 memcpy (&im[1], message, msize); 2565 memcpy (&im[1], message, msize);
2563 2566