aboutsummaryrefslogtreecommitdiff
path: root/src/util/client.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-02-21 20:21:40 +0000
committerChristian Grothoff <christian@grothoff.org>2015-02-21 20:21:40 +0000
commit9e308ff38737cc6b1d840eb72d016a7d1e109ea4 (patch)
tree07f4ed30972e879eca11c36dc4b2619bb153d35a /src/util/client.c
parent0359101b306e170ecca31520ca12081e09d1804f (diff)
downloadgnunet-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.c99
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 */
506static void 508static void
507receive_helper (void *cls, const void *buf, size_t available, 509receive_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 */
567static void 579static void
568receive_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 580receive_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 */
753static void 780static void
754confirm_handler (void *cls, const struct GNUNET_MessageHeader *msg) 781confirm_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 */
1041static size_t 1069static size_t
1042client_notify (void *cls, size_t size, void *buf); 1070client_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 */
1113static size_t 1141static size_t
1114client_notify (void *cls, size_t size, void *buf) 1142client_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;