diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-02-21 20:21:40 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-02-21 20:21:40 +0000 |
commit | 9e308ff38737cc6b1d840eb72d016a7d1e109ea4 (patch) | |
tree | 07f4ed30972e879eca11c36dc4b2619bb153d35a /src/util/client.c | |
parent | 0359101b306e170ecca31520ca12081e09d1804f (diff) | |
download | gnunet-9e308ff38737cc6b1d840eb72d016a7d1e109ea4.tar.gz gnunet-9e308ff38737cc6b1d840eb72d016a7d1e109ea4.zip |
-signal connection failure to receive even if receive is triggered after failure is observed
Diffstat (limited to 'src/util/client.c')
-rw-r--r-- | src/util/client.c | 99 |
1 files changed, 67 insertions, 32 deletions
diff --git a/src/util/client.c b/src/util/client.c index 2271c4c5c..11abecfcf 100644 --- a/src/util/client.c +++ b/src/util/client.c | |||
@@ -217,7 +217,9 @@ struct GNUNET_CLIENT_Connection | |||
217 | 217 | ||
218 | /** | 218 | /** |
219 | * Are we currently busy doing receive-processing? | 219 | * Are we currently busy doing receive-processing? |
220 | * #GNUNET_YES if so, #GNUNET_NO if not. | 220 | * #GNUNET_YES if so, #GNUNET_NO if not. #GNUNET_SYSERR |
221 | * if the connection has failed (but we may not have | ||
222 | * closed the handle itself yet). | ||
221 | */ | 223 | */ |
222 | int in_receive; | 224 | int in_receive; |
223 | 225 | ||
@@ -504,8 +506,12 @@ check_complete (struct GNUNET_CLIENT_Connection *client) | |||
504 | * @param errCode value of errno (on errors receiving) | 506 | * @param errCode value of errno (on errors receiving) |
505 | */ | 507 | */ |
506 | static void | 508 | static void |
507 | receive_helper (void *cls, const void *buf, size_t available, | 509 | receive_helper (void *cls, |
508 | const struct sockaddr *addr, socklen_t addrlen, int errCode) | 510 | const void *buf, |
511 | size_t available, | ||
512 | const struct sockaddr *addr, | ||
513 | socklen_t addrlen, | ||
514 | int errCode) | ||
509 | { | 515 | { |
510 | struct GNUNET_CLIENT_Connection *client = cls; | 516 | struct GNUNET_CLIENT_Connection *client = cls; |
511 | struct GNUNET_TIME_Relative remaining; | 517 | struct GNUNET_TIME_Relative remaining; |
@@ -515,19 +521,25 @@ receive_helper (void *cls, const void *buf, size_t available, | |||
515 | GNUNET_assert (GNUNET_NO == client->msg_complete); | 521 | GNUNET_assert (GNUNET_NO == client->msg_complete); |
516 | GNUNET_assert (GNUNET_YES == client->in_receive); | 522 | GNUNET_assert (GNUNET_YES == client->in_receive); |
517 | client->in_receive = GNUNET_NO; | 523 | client->in_receive = GNUNET_NO; |
518 | if ((0 == available) || (NULL == client->connection) || (0 != errCode)) | 524 | if ( (0 == available) || |
525 | (NULL == client->connection) || | ||
526 | (0 != errCode) ) | ||
519 | { | 527 | { |
520 | /* signal timeout! */ | 528 | /* signal timeout! */ |
521 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 529 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
522 | "Timeout in receive_helper, available %u, client->connection %s, errCode `%s'\n", | 530 | "Timeout in receive_helper, available %u, client->connection %s, errCode `%s'\n", |
523 | (unsigned int) available, NULL == client->connection ? "NULL" : "non-NULL", | 531 | (unsigned int) available, |
532 | NULL == client->connection ? "NULL" : "non-NULL", | ||
524 | STRERROR (errCode)); | 533 | STRERROR (errCode)); |
525 | if (NULL != (receive_handler = client->receiver_handler)) | 534 | if (NULL != (receive_handler = client->receiver_handler)) |
526 | { | 535 | { |
527 | receive_handler_cls = client->receiver_handler_cls; | 536 | receive_handler_cls = client->receiver_handler_cls; |
528 | client->receiver_handler = NULL; | 537 | client->receiver_handler = NULL; |
529 | receive_handler (receive_handler_cls, NULL); | 538 | receive_handler (receive_handler_cls, |
539 | NULL); | ||
530 | } | 540 | } |
541 | /* remember failure */ | ||
542 | client->in_receive = GNUNET_SYSERR; | ||
531 | return; | 543 | return; |
532 | } | 544 | } |
533 | /* FIXME: optimize for common fast case where buf contains the | 545 | /* FIXME: optimize for common fast case where buf contains the |
@@ -565,7 +577,8 @@ receive_helper (void *cls, const void *buf, size_t available, | |||
565 | * @param tc scheduler context | 577 | * @param tc scheduler context |
566 | */ | 578 | */ |
567 | static void | 579 | static void |
568 | receive_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 580 | receive_task (void *cls, |
581 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
569 | { | 582 | { |
570 | struct GNUNET_CLIENT_Connection *client = cls; | 583 | struct GNUNET_CLIENT_Connection *client = cls; |
571 | GNUNET_CLIENT_MessageHandler handler = client->receiver_handler; | 584 | GNUNET_CLIENT_MessageHandler handler = client->receiver_handler; |
@@ -576,12 +589,22 @@ receive_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
576 | char mbuf[msize] GNUNET_ALIGN; | 589 | char mbuf[msize] GNUNET_ALIGN; |
577 | struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) mbuf; | 590 | struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) mbuf; |
578 | 591 | ||
592 | client->receive_task = NULL; | ||
593 | if ( (GNUNET_SYSERR == client->in_receive) && | ||
594 | (GNUNET_YES != client->msg_complete) ) | ||
595 | { | ||
596 | /* Connection failure, signal to caller! */ | ||
597 | client->receiver_handler = NULL; | ||
598 | if (NULL != handler) | ||
599 | handler (handler_cls, | ||
600 | NULL); | ||
601 | return; | ||
602 | } | ||
579 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 603 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
580 | "Received message of type %u and size %u from %s service.\n", | 604 | "Received message of type %u and size %u from %s service.\n", |
581 | ntohs (cmsg->type), | 605 | ntohs (cmsg->type), |
582 | msize, | 606 | msize, |
583 | client->service_name); | 607 | client->service_name); |
584 | client->receive_task = NULL; | ||
585 | GNUNET_assert (GNUNET_YES == client->msg_complete); | 608 | GNUNET_assert (GNUNET_YES == client->msg_complete); |
586 | GNUNET_assert (client->received_pos >= msize); | 609 | GNUNET_assert (client->received_pos >= msize); |
587 | memcpy (msg, cmsg, msize); | 610 | memcpy (msg, cmsg, msize); |
@@ -618,25 +641,29 @@ GNUNET_CLIENT_receive (struct GNUNET_CLIENT_Connection *client, | |||
618 | client->service_name); | 641 | client->service_name); |
619 | GNUNET_break (0); /* this should not happen in well-written code! */ | 642 | GNUNET_break (0); /* this should not happen in well-written code! */ |
620 | if (NULL != handler) | 643 | if (NULL != handler) |
621 | handler (handler_cls, NULL); | 644 | handler (handler_cls, |
645 | NULL); | ||
622 | return; | 646 | return; |
623 | } | 647 | } |
624 | client->receiver_handler = handler; | 648 | client->receiver_handler = handler; |
625 | client->receiver_handler_cls = handler_cls; | 649 | client->receiver_handler_cls = handler_cls; |
626 | client->receive_timeout = GNUNET_TIME_relative_to_absolute (timeout); | 650 | client->receive_timeout = GNUNET_TIME_relative_to_absolute (timeout); |
627 | if (GNUNET_YES == client->msg_complete) | 651 | if ( (GNUNET_YES == client->msg_complete) || |
652 | (GNUNET_SYSERR == client->in_receive) ) | ||
628 | { | 653 | { |
629 | GNUNET_assert (NULL == client->receive_task); | 654 | GNUNET_assert (NULL == client->receive_task); |
630 | client->receive_task = GNUNET_SCHEDULER_add_now (&receive_task, client); | 655 | client->receive_task = GNUNET_SCHEDULER_add_now (&receive_task, client); |
656 | return; | ||
631 | } | 657 | } |
632 | else | 658 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
633 | { | 659 | "calling GNUNET_CONNECTION_receive\n"); |
634 | LOG (GNUNET_ERROR_TYPE_DEBUG, "calling GNUNET_CONNECTION_receive\n"); | 660 | GNUNET_assert (GNUNET_NO == client->in_receive); |
635 | GNUNET_assert (GNUNET_NO == client->in_receive); | 661 | client->in_receive = GNUNET_YES; |
636 | client->in_receive = GNUNET_YES; | 662 | GNUNET_CONNECTION_receive (client->connection, |
637 | GNUNET_CONNECTION_receive (client->connection, GNUNET_SERVER_MAX_MESSAGE_SIZE - 1, | 663 | GNUNET_SERVER_MAX_MESSAGE_SIZE - 1, |
638 | timeout, &receive_helper, client); | 664 | timeout, |
639 | } | 665 | &receive_helper, |
666 | client); | ||
640 | } | 667 | } |
641 | 668 | ||
642 | 669 | ||
@@ -751,7 +778,8 @@ service_test_report (struct GNUNET_CLIENT_TestHandle *th, | |||
751 | * @param msg message received, NULL on timeout or fatal error | 778 | * @param msg message received, NULL on timeout or fatal error |
752 | */ | 779 | */ |
753 | static void | 780 | static void |
754 | confirm_handler (void *cls, const struct GNUNET_MessageHeader *msg) | 781 | confirm_handler (void *cls, |
782 | const struct GNUNET_MessageHeader *msg) | ||
755 | { | 783 | { |
756 | struct GNUNET_CLIENT_TestHandle *th = cls; | 784 | struct GNUNET_CLIENT_TestHandle *th = cls; |
757 | 785 | ||
@@ -1036,7 +1064,7 @@ GNUNET_CLIENT_service_test (const char *service, | |||
1036 | * @param cls our `struct GNUNET_CLIENT_TransmissionHandle` | 1064 | * @param cls our `struct GNUNET_CLIENT_TransmissionHandle` |
1037 | * @param size number of bytes available for transmission | 1065 | * @param size number of bytes available for transmission |
1038 | * @param buf where to write them | 1066 | * @param buf where to write them |
1039 | * @return number of bytes written to buf | 1067 | * @return number of bytes written to @a buf |
1040 | */ | 1068 | */ |
1041 | static size_t | 1069 | static size_t |
1042 | client_notify (void *cls, size_t size, void *buf); | 1070 | client_notify (void *cls, size_t size, void *buf); |
@@ -1111,7 +1139,9 @@ client_delayed_retry (void *cls, | |||
1111 | * @return number of bytes written to @a buf | 1139 | * @return number of bytes written to @a buf |
1112 | */ | 1140 | */ |
1113 | static size_t | 1141 | static size_t |
1114 | client_notify (void *cls, size_t size, void *buf) | 1142 | client_notify (void *cls, |
1143 | size_t size, | ||
1144 | void *buf) | ||
1115 | { | 1145 | { |
1116 | struct GNUNET_CLIENT_TransmitHandle *th = cls; | 1146 | struct GNUNET_CLIENT_TransmitHandle *th = cls; |
1117 | struct GNUNET_CLIENT_Connection *client = th->client; | 1147 | struct GNUNET_CLIENT_Connection *client = th->client; |
@@ -1126,14 +1156,16 @@ client_notify (void *cls, size_t size, void *buf) | |||
1126 | { | 1156 | { |
1127 | delay = GNUNET_TIME_absolute_get_remaining (th->timeout); | 1157 | delay = GNUNET_TIME_absolute_get_remaining (th->timeout); |
1128 | delay.rel_value_us /= 2; | 1158 | delay.rel_value_us /= 2; |
1129 | if ((GNUNET_YES != th->auto_retry) || (0 == --th->attempts_left) || | 1159 | if ( (GNUNET_YES != th->auto_retry) || |
1130 | (delay.rel_value_us < 1)|| | 1160 | (0 == --th->attempts_left) || |
1131 | (0 != (GNUNET_SCHEDULER_get_reason() & GNUNET_SCHEDULER_REASON_SHUTDOWN))) | 1161 | (delay.rel_value_us < 1)|| |
1162 | (0 != (GNUNET_SCHEDULER_get_reason() & GNUNET_SCHEDULER_REASON_SHUTDOWN))) | ||
1132 | { | 1163 | { |
1133 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1164 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1134 | "Transmission failed %u times, giving up.\n", | 1165 | "Transmission failed %u times, giving up.\n", |
1135 | MAX_ATTEMPTS - th->attempts_left); | 1166 | MAX_ATTEMPTS - th->attempts_left); |
1136 | GNUNET_break (0 == th->notify (th->notify_cls, 0, NULL)); | 1167 | GNUNET_break (0 == |
1168 | th->notify (th->notify_cls, 0, NULL)); | ||
1137 | GNUNET_free (th); | 1169 | GNUNET_free (th); |
1138 | return 0; | 1170 | return 0; |
1139 | } | 1171 | } |
@@ -1232,13 +1264,14 @@ GNUNET_CLIENT_notify_transmit_ready (struct GNUNET_CLIENT_Connection *client, | |||
1232 | GNUNET_SCHEDULER_add_delayed (client->back_off, | 1264 | GNUNET_SCHEDULER_add_delayed (client->back_off, |
1233 | &client_delayed_retry, | 1265 | &client_delayed_retry, |
1234 | th); | 1266 | th); |
1235 | |||
1236 | } | 1267 | } |
1237 | else | 1268 | else |
1238 | { | 1269 | { |
1239 | th->th = | 1270 | th->th = GNUNET_CONNECTION_notify_transmit_ready (client->connection, |
1240 | GNUNET_CONNECTION_notify_transmit_ready (client->connection, size, timeout, | 1271 | size, |
1241 | &client_notify, th); | 1272 | timeout, |
1273 | &client_notify, | ||
1274 | th); | ||
1242 | if (NULL == th->th) | 1275 | if (NULL == th->th) |
1243 | { | 1276 | { |
1244 | GNUNET_break (0); | 1277 | GNUNET_break (0); |
@@ -1281,7 +1314,7 @@ GNUNET_CLIENT_notify_transmit_ready_cancel (struct GNUNET_CLIENT_TransmitHandle | |||
1281 | * NULL and @a size zero if the socket was closed for | 1314 | * NULL and @a size zero if the socket was closed for |
1282 | * writing in the meantime. | 1315 | * writing in the meantime. |
1283 | * | 1316 | * |
1284 | * @param cls closure of type "struct TransmitGetResponseContext*" | 1317 | * @param cls closure of type `struct TransmitGetResponseContext *` |
1285 | * @param size number of bytes available in @a buf | 1318 | * @param size number of bytes available in @a buf |
1286 | * @param buf where the callee should write the message | 1319 | * @param buf where the callee should write the message |
1287 | * @return number of bytes written to @a buf | 1320 | * @return number of bytes written to @a buf |
@@ -1299,7 +1332,7 @@ transmit_for_response (void *cls, | |||
1299 | if (NULL == buf) | 1332 | if (NULL == buf) |
1300 | { | 1333 | { |
1301 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1334 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1302 | _("Could not submit request, not expecting to receive a response.\n")); | 1335 | "Could not submit request, not expecting to receive a response.\n"); |
1303 | if (NULL != tc->rn) | 1336 | if (NULL != tc->rn) |
1304 | tc->rn (tc->rn_cls, NULL); | 1337 | tc->rn (tc->rn_cls, NULL); |
1305 | GNUNET_free (tc); | 1338 | GNUNET_free (tc); |
@@ -1307,7 +1340,9 @@ transmit_for_response (void *cls, | |||
1307 | } | 1340 | } |
1308 | GNUNET_assert (size >= msize); | 1341 | GNUNET_assert (size >= msize); |
1309 | memcpy (buf, tc->hdr, msize); | 1342 | memcpy (buf, tc->hdr, msize); |
1310 | GNUNET_CLIENT_receive (tc->client, tc->rn, tc->rn_cls, | 1343 | GNUNET_CLIENT_receive (tc->client, |
1344 | tc->rn, | ||
1345 | tc->rn_cls, | ||
1311 | GNUNET_TIME_absolute_get_remaining (tc->timeout)); | 1346 | GNUNET_TIME_absolute_get_remaining (tc->timeout)); |
1312 | GNUNET_free (tc); | 1347 | GNUNET_free (tc); |
1313 | return msize; | 1348 | return msize; |