aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-06-16 08:09:46 +0000
committerChristian Grothoff <christian@grothoff.org>2011-06-16 08:09:46 +0000
commit29e0d43e92d47ec5e6b632184939518546b74520 (patch)
tree1fbc98c6237ebf3f06268b1a2690993b61a2280a
parent4d2c6c417cd295905ae5140e477c76da48b30fe4 (diff)
downloadgnunet-29e0d43e92d47ec5e6b632184939518546b74520.tar.gz
gnunet-29e0d43e92d47ec5e6b632184939518546b74520.zip
do not crash if we run out of sockets
-rw-r--r--src/util/client.c75
-rw-r--r--src/util/network.c1
2 files changed, 55 insertions, 21 deletions
diff --git a/src/util/client.c b/src/util/client.c
index f9fc67c9d..9458cc94b 100644
--- a/src/util/client.c
+++ b/src/util/client.c
@@ -373,8 +373,6 @@ GNUNET_CLIENT_connect (const char *service_name,
373 373
374 sock = do_connect (service_name, 374 sock = do_connect (service_name,
375 cfg, 0); 375 cfg, 0);
376 if (sock == NULL)
377 return NULL;
378 ret = GNUNET_malloc (sizeof (struct GNUNET_CLIENT_Connection)); 376 ret = GNUNET_malloc (sizeof (struct GNUNET_CLIENT_Connection));
379 ret->attempts = 1; 377 ret->attempts = 1;
380 ret->sock = sock; 378 ret->sock = sock;
@@ -421,14 +419,16 @@ void
421GNUNET_CLIENT_disconnect (struct GNUNET_CLIENT_Connection *sock, 419GNUNET_CLIENT_disconnect (struct GNUNET_CLIENT_Connection *sock,
422 int finish_pending_write) 420 int finish_pending_write)
423{ 421{
424 GNUNET_assert (sock->sock != NULL);
425 if (sock->in_receive == GNUNET_YES) 422 if (sock->in_receive == GNUNET_YES)
426 { 423 {
427 GNUNET_CONNECTION_receive_cancel (sock->sock); 424 GNUNET_CONNECTION_receive_cancel (sock->sock);
428 sock->in_receive = GNUNET_NO; 425 sock->in_receive = GNUNET_NO;
429 } 426 }
430 GNUNET_CONNECTION_destroy (sock->sock, finish_pending_write); 427 if (NULL != sock->sock)
431 sock->sock = NULL; 428 {
429 GNUNET_CONNECTION_destroy (sock->sock, finish_pending_write);
430 sock->sock = NULL;
431 }
432 if (sock->tag != NULL) 432 if (sock->tag != NULL)
433 { 433 {
434 GNUNET_free (sock->tag); 434 GNUNET_free (sock->tag);
@@ -436,7 +436,10 @@ GNUNET_CLIENT_disconnect (struct GNUNET_CLIENT_Connection *sock,
436 } 436 }
437 sock->receiver_handler = NULL; 437 sock->receiver_handler = NULL;
438 if (sock->th != NULL) 438 if (sock->th != NULL)
439 GNUNET_CLIENT_notify_transmit_ready_cancel (sock->th); 439 {
440 GNUNET_CLIENT_notify_transmit_ready_cancel (sock->th);
441 sock->th = NULL;
442 }
440 if (sock->receive_task != GNUNET_SCHEDULER_NO_TASK) 443 if (sock->receive_task != GNUNET_SCHEDULER_NO_TASK)
441 { 444 {
442 GNUNET_SCHEDULER_cancel (sock->receive_task); 445 GNUNET_SCHEDULER_cancel (sock->receive_task);
@@ -766,6 +769,7 @@ client_delayed_retry (void *cls,
766 const struct GNUNET_SCHEDULER_TaskContext *tc) 769 const struct GNUNET_SCHEDULER_TaskContext *tc)
767{ 770{
768 struct GNUNET_CLIENT_TransmitHandle *th = cls; 771 struct GNUNET_CLIENT_TransmitHandle *th = cls;
772 struct GNUNET_TIME_Relative delay;
769 773
770 th->reconnect_task = GNUNET_SCHEDULER_NO_TASK; 774 th->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
771 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) 775 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
@@ -779,6 +783,30 @@ client_delayed_retry (void *cls,
779 GNUNET_free (th); 783 GNUNET_free (th);
780 return; 784 return;
781 } 785 }
786 th->sock->sock = do_connect (th->sock->service_name,
787 th->sock->cfg,
788 th->sock->attempts++);
789 if (NULL == th->sock->sock)
790 {
791 /* could happen if we're out of sockets */
792 delay = GNUNET_TIME_relative_min (GNUNET_TIME_absolute_get_remaining (th->timeout),
793 th->sock->back_off);
794 th->sock->back_off
795 = GNUNET_TIME_relative_min (GNUNET_TIME_relative_multiply (th->sock->back_off, 2),
796 GNUNET_TIME_UNIT_SECONDS);
797#if DEBUG_CLIENT
798 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
799 "Transmission failed %u times, trying again in %llums.\n",
800 MAX_ATTEMPTS - th->attempts_left,
801 (unsigned long long) delay.rel_value);
802#endif
803 th->reconnect_task = GNUNET_SCHEDULER_add_delayed (delay,
804 &client_delayed_retry,
805 th);
806 return;
807 }
808 GNUNET_CONNECTION_ignore_shutdown (th->sock->sock,
809 th->sock->ignore_shutdown);
782 th->th = GNUNET_CONNECTION_notify_transmit_ready (th->sock->sock, 810 th->th = GNUNET_CONNECTION_notify_transmit_ready (th->sock->sock,
783 th->size, 811 th->size,
784 GNUNET_TIME_absolute_get_remaining 812 GNUNET_TIME_absolute_get_remaining
@@ -837,15 +865,10 @@ client_notify (void *cls, size_t size, void *buf)
837 th->sock->service_name); 865 th->sock->service_name);
838#endif 866#endif
839 GNUNET_CONNECTION_destroy (th->sock->sock, GNUNET_NO); 867 GNUNET_CONNECTION_destroy (th->sock->sock, GNUNET_NO);
840 th->sock->sock = do_connect (th->sock->service_name, 868 th->sock->sock = NULL;
841 th->sock->cfg,
842 th->sock->attempts++);
843 GNUNET_assert (NULL != th->sock->sock);
844 GNUNET_CONNECTION_ignore_shutdown (th->sock->sock,
845 th->sock->ignore_shutdown);
846 delay = GNUNET_TIME_relative_min (delay, th->sock->back_off); 869 delay = GNUNET_TIME_relative_min (delay, th->sock->back_off);
847 th->sock->back_off 870 th->sock->back_off
848 = GNUNET_TIME_relative_min (GNUNET_TIME_relative_multiply (th->sock->back_off, 2), 871 = GNUNET_TIME_relative_min (GNUNET_TIME_relative_multiply (th->sock->back_off, 2),
849 GNUNET_TIME_UNIT_SECONDS); 872 GNUNET_TIME_UNIT_SECONDS);
850#if DEBUG_CLIENT 873#if DEBUG_CLIENT
851 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 874 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -910,15 +933,25 @@ GNUNET_CLIENT_notify_transmit_ready (struct GNUNET_CLIENT_Connection *sock,
910 th->notify = notify; 933 th->notify = notify;
911 th->notify_cls = notify_cls; 934 th->notify_cls = notify_cls;
912 th->attempts_left = MAX_ATTEMPTS; 935 th->attempts_left = MAX_ATTEMPTS;
913 th->th = GNUNET_CONNECTION_notify_transmit_ready (sock->sock, 936 if (sock->sock == NULL)
914 size,
915 timeout,
916 &client_notify, th);
917 if (NULL == th->th)
918 { 937 {
919 GNUNET_break (0); 938 th->reconnect_task = GNUNET_SCHEDULER_add_delayed (sock->back_off,
920 GNUNET_free (th); 939 &client_delayed_retry,
921 return NULL; 940 th);
941
942 }
943 else
944 {
945 th->th = GNUNET_CONNECTION_notify_transmit_ready (sock->sock,
946 size,
947 timeout,
948 &client_notify, th);
949 if (NULL == th->th)
950 {
951 GNUNET_break (0);
952 GNUNET_free (th);
953 return NULL;
954 }
922 } 955 }
923 sock->th = th; 956 sock->th = th;
924 return th; 957 return th;
diff --git a/src/util/network.c b/src/util/network.c
index 49e50101b..0446d649c 100644
--- a/src/util/network.c
+++ b/src/util/network.c
@@ -652,6 +652,7 @@ struct GNUNET_NETWORK_Handle *
652GNUNET_NETWORK_socket_create (int domain, int type, int protocol) 652GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
653{ 653{
654 struct GNUNET_NETWORK_Handle *ret; 654 struct GNUNET_NETWORK_Handle *ret;
655
655 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle)); 656 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
656 ret->af = domain; 657 ret->af = domain;
657 ret->fd = socket (domain, type, protocol); 658 ret->fd = socket (domain, type, protocol);