diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-06-16 11:26:01 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-06-16 11:26:01 +0000 |
commit | a25e91fe64981bad87d8a2a438b87a60a86041a3 (patch) | |
tree | 4ac54fe958c87175fc37edc09c89f0fdac603532 | |
parent | 66aac17afcd7e0ea706cfd4ca0d91892d10dadcc (diff) | |
download | gnunet-a25e91fe64981bad87d8a2a438b87a60a86041a3.tar.gz gnunet-a25e91fe64981bad87d8a2a438b87a60a86041a3.zip |
make code more tolerant to re-connect failures, i.e. due to being out of sockets
-rw-r--r-- | src/peerinfo/peerinfo_api.c | 96 |
1 files changed, 77 insertions, 19 deletions
diff --git a/src/peerinfo/peerinfo_api.c b/src/peerinfo/peerinfo_api.c index 95745a2bd..4db776b55 100644 --- a/src/peerinfo/peerinfo_api.c +++ b/src/peerinfo/peerinfo_api.c | |||
@@ -111,6 +111,11 @@ struct GNUNET_PEERINFO_Handle | |||
111 | struct GNUNET_CLIENT_TransmitHandle *th; | 111 | struct GNUNET_CLIENT_TransmitHandle *th; |
112 | 112 | ||
113 | /** | 113 | /** |
114 | * ID for a reconnect task. | ||
115 | */ | ||
116 | GNUNET_SCHEDULER_TaskIdentifier r_task; | ||
117 | |||
118 | /** | ||
114 | * Set to GNUNET_YES if we are currently receiving replies from the | 119 | * Set to GNUNET_YES if we are currently receiving replies from the |
115 | * service. | 120 | * service. |
116 | */ | 121 | */ |
@@ -129,14 +134,10 @@ struct GNUNET_PEERINFO_Handle | |||
129 | struct GNUNET_PEERINFO_Handle * | 134 | struct GNUNET_PEERINFO_Handle * |
130 | GNUNET_PEERINFO_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) | 135 | GNUNET_PEERINFO_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) |
131 | { | 136 | { |
132 | struct GNUNET_CLIENT_Connection *client; | ||
133 | struct GNUNET_PEERINFO_Handle *ret; | 137 | struct GNUNET_PEERINFO_Handle *ret; |
134 | 138 | ||
135 | client = GNUNET_CLIENT_connect ("peerinfo", cfg); | ||
136 | if (client == NULL) | ||
137 | return NULL; | ||
138 | ret = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_Handle)); | 139 | ret = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_Handle)); |
139 | ret->client = client; | 140 | ret->client = GNUNET_CLIENT_connect ("peerinfo", cfg); |
140 | ret->cfg = cfg; | 141 | ret->cfg = cfg; |
141 | return ret; | 142 | return ret; |
142 | } | 143 | } |
@@ -170,7 +171,16 @@ GNUNET_PEERINFO_disconnect (struct GNUNET_PEERINFO_Handle *h) | |||
170 | GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); | 171 | GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); |
171 | h->th = NULL; | 172 | h->th = NULL; |
172 | } | 173 | } |
173 | GNUNET_CLIENT_disconnect (h->client, GNUNET_NO); | 174 | if (NULL != h->client) |
175 | { | ||
176 | GNUNET_CLIENT_disconnect (h->client, GNUNET_NO); | ||
177 | h->client = NULL; | ||
178 | } | ||
179 | if (GNUNET_SCHEDULER_NO_TASK != h->r_task) | ||
180 | { | ||
181 | GNUNET_SCHEDULER_cancel (h->r_task); | ||
182 | h->r_task = GNUNET_SCHEDULER_NO_TASK; | ||
183 | } | ||
174 | GNUNET_free (h); | 184 | GNUNET_free (h); |
175 | } | 185 | } |
176 | 186 | ||
@@ -191,12 +201,57 @@ trigger_transmit (struct GNUNET_PEERINFO_Handle *h); | |||
191 | * @param h handle to the service | 201 | * @param h handle to the service |
192 | */ | 202 | */ |
193 | static void | 203 | static void |
204 | reconnect (struct GNUNET_PEERINFO_Handle *h); | ||
205 | |||
206 | /** | ||
207 | * Task scheduled to re-try connecting to the peerinfo service. | ||
208 | * | ||
209 | * @param cls the 'struct GNUNET_PEERINFO_Handle' | ||
210 | * @param ts scheduler context | ||
211 | */ | ||
212 | static void | ||
213 | reconnect_task (void *cls, | ||
214 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
215 | { | ||
216 | struct GNUNET_PEERINFO_Handle *h = cls; | ||
217 | |||
218 | h->r_task = GNUNET_SCHEDULER_NO_TASK; | ||
219 | reconnect (h); | ||
220 | } | ||
221 | |||
222 | |||
223 | /** | ||
224 | * Close the existing connection to PEERINFO and reconnect. | ||
225 | * | ||
226 | * @param h handle to the service | ||
227 | */ | ||
228 | static void | ||
194 | reconnect (struct GNUNET_PEERINFO_Handle *h) | 229 | reconnect (struct GNUNET_PEERINFO_Handle *h) |
195 | { | 230 | { |
196 | GNUNET_CLIENT_disconnect (h->client, GNUNET_SYSERR); | 231 | if (h->r_task != GNUNET_SCHEDULER_NO_TASK) |
197 | h->th = NULL; | 232 | { |
233 | GNUNET_SCHEDULER_cancel (h->r_task); | ||
234 | h->r_task = GNUNET_SCHEDULER_NO_TASK; | ||
235 | } | ||
236 | if (NULL != h->th) | ||
237 | { | ||
238 | GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); | ||
239 | h->th = NULL; | ||
240 | } | ||
241 | if (NULL != h->client) | ||
242 | { | ||
243 | GNUNET_CLIENT_disconnect (h->client, GNUNET_SYSERR); | ||
244 | h->client = NULL; | ||
245 | } | ||
198 | h->client = GNUNET_CLIENT_connect ("peerinfo", h->cfg); | 246 | h->client = GNUNET_CLIENT_connect ("peerinfo", h->cfg); |
199 | GNUNET_assert (h->client != NULL); | 247 | if (NULL == h->client) |
248 | { | ||
249 | h->r_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, | ||
250 | &reconnect_task, | ||
251 | h); | ||
252 | return; | ||
253 | } | ||
254 | trigger_transmit (h); | ||
200 | } | 255 | } |
201 | 256 | ||
202 | 257 | ||
@@ -227,7 +282,6 @@ do_transmit (void *cls, size_t size, void *buf) | |||
227 | h->tq_tail, | 282 | h->tq_tail, |
228 | tqe); | 283 | tqe); |
229 | reconnect (h); | 284 | reconnect (h); |
230 | trigger_transmit (h); | ||
231 | if (tqe != NULL) | 285 | if (tqe != NULL) |
232 | { | 286 | { |
233 | if (tqe->cont != NULL) | 287 | if (tqe->cont != NULL) |
@@ -278,6 +332,11 @@ trigger_transmit (struct GNUNET_PEERINFO_Handle *h) | |||
278 | return; | 332 | return; |
279 | if (h->in_receive == GNUNET_YES) | 333 | if (h->in_receive == GNUNET_YES) |
280 | return; | 334 | return; |
335 | if (NULL == h->client) | ||
336 | { | ||
337 | reconnect (h); | ||
338 | return; | ||
339 | } | ||
281 | h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, | 340 | h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, |
282 | tqe->size, | 341 | tqe->size, |
283 | GNUNET_TIME_absolute_get_remaining (tqe->timeout), | 342 | GNUNET_TIME_absolute_get_remaining (tqe->timeout), |
@@ -375,7 +434,8 @@ struct GNUNET_PEERINFO_IteratorContext | |||
375 | * @param msg message received, NULL on timeout or fatal error | 434 | * @param msg message received, NULL on timeout or fatal error |
376 | */ | 435 | */ |
377 | static void | 436 | static void |
378 | peerinfo_handler (void *cls, const struct GNUNET_MessageHeader *msg) | 437 | peerinfo_handler (void *cls, |
438 | const struct GNUNET_MessageHeader *msg) | ||
379 | { | 439 | { |
380 | struct GNUNET_PEERINFO_IteratorContext *ic = cls; | 440 | struct GNUNET_PEERINFO_IteratorContext *ic = cls; |
381 | const struct InfoMessage *im; | 441 | const struct InfoMessage *im; |
@@ -391,7 +451,6 @@ peerinfo_handler (void *cls, const struct GNUNET_MessageHeader *msg) | |||
391 | "PEERINFO"); | 451 | "PEERINFO"); |
392 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s\n", err_msg); | 452 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s\n", err_msg); |
393 | reconnect (ic->h); | 453 | reconnect (ic->h); |
394 | trigger_transmit (ic->h); | ||
395 | if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK) | 454 | if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK) |
396 | GNUNET_SCHEDULER_cancel (ic->timeout_task); | 455 | GNUNET_SCHEDULER_cancel (ic->timeout_task); |
397 | if (ic->callback != NULL) | 456 | if (ic->callback != NULL) |
@@ -424,7 +483,6 @@ peerinfo_handler (void *cls, const struct GNUNET_MessageHeader *msg) | |||
424 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,err_msg); | 483 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,err_msg); |
425 | GNUNET_break (0); | 484 | GNUNET_break (0); |
426 | reconnect (ic->h); | 485 | reconnect (ic->h); |
427 | trigger_transmit (ic->h); | ||
428 | if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK) | 486 | if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK) |
429 | GNUNET_SCHEDULER_cancel (ic->timeout_task); | 487 | GNUNET_SCHEDULER_cancel (ic->timeout_task); |
430 | if (ic->callback != NULL) | 488 | if (ic->callback != NULL) |
@@ -441,18 +499,19 @@ peerinfo_handler (void *cls, const struct GNUNET_MessageHeader *msg) | |||
441 | hello = (const struct GNUNET_HELLO_Message *) &im[1]; | 499 | hello = (const struct GNUNET_HELLO_Message *) &im[1]; |
442 | if (ms != sizeof (struct InfoMessage) + GNUNET_HELLO_size (hello)) | 500 | if (ms != sizeof (struct InfoMessage) + GNUNET_HELLO_size (hello)) |
443 | { | 501 | { |
444 | char * err_msg; | 502 | char * err_msg; |
445 | GNUNET_asprintf(&err_msg,_("Received invalid message from `%s' service.\n"),"PEERINFO"); | 503 | GNUNET_asprintf (&err_msg, |
446 | GNUNET_break (0); | 504 | _("Received invalid message from `%s' service.\n"), |
505 | "PEERINFO"); | ||
506 | GNUNET_break (0); | ||
447 | reconnect (ic->h); | 507 | reconnect (ic->h); |
448 | trigger_transmit (ic->h); | ||
449 | if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK) | 508 | if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK) |
450 | GNUNET_SCHEDULER_cancel (ic->timeout_task); | 509 | GNUNET_SCHEDULER_cancel (ic->timeout_task); |
451 | if (ic->callback != NULL) | 510 | if (ic->callback != NULL) |
452 | ic->callback (ic->callback_cls, NULL, NULL, err_msg); | 511 | ic->callback (ic->callback_cls, NULL, NULL, err_msg); |
453 | GNUNET_free (ic); | 512 | GNUNET_free (ic); |
454 | GNUNET_free (err_msg); | 513 | GNUNET_free (err_msg); |
455 | return; | 514 | return; |
456 | } | 515 | } |
457 | } | 516 | } |
458 | #if DEBUG_PEERINFO | 517 | #if DEBUG_PEERINFO |
@@ -497,7 +556,6 @@ iterator_start_receive (void *cls, | |||
497 | ic->timeout_task = GNUNET_SCHEDULER_NO_TASK; | 556 | ic->timeout_task = GNUNET_SCHEDULER_NO_TASK; |
498 | } | 557 | } |
499 | reconnect (ic->h); | 558 | reconnect (ic->h); |
500 | trigger_transmit (ic->h); | ||
501 | if (ic->callback != NULL) | 559 | if (ic->callback != NULL) |
502 | ic->callback (ic->callback_cls, NULL, NULL, err_msg); | 560 | ic->callback (ic->callback_cls, NULL, NULL, err_msg); |
503 | GNUNET_free (err_msg); | 561 | GNUNET_free (err_msg); |