static void receive_check (void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode) { int *ok = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receive validates incoming data\n"); GNUNET_assert (buf != NULL); /* no timeout */ if (0 == memcmp (&"Hello World"[sofar], buf, available)) sofar += available; if (sofar < 12) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receive needs more data\n"); GNUNET_CONNECTION_receive (asock, 1024, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5), &receive_check, cls); } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receive closes accepted socket\n"); *ok = 0; GNUNET_CONNECTION_destroy (asock); GNUNET_CONNECTION_destroy (csock); } }
static void run_accept (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { void *addr; size_t alen; struct sockaddr_in *v4; struct sockaddr_in expect; asock = GNUNET_CONNECTION_create_from_accept (NULL, NULL, ls); GNUNET_assert (asock != NULL); GNUNET_assert (GNUNET_YES == GNUNET_CONNECTION_check (asock)); GNUNET_assert (GNUNET_OK == GNUNET_CONNECTION_get_address (asock, &addr, &alen)); GNUNET_assert (alen == sizeof (struct sockaddr_in)); v4 = addr; memset (&expect, 0, sizeof (expect)); #if HAVE_SOCKADDR_IN_SIN_LEN expect.sin_len = sizeof (expect); #endif expect.sin_family = AF_INET; expect.sin_port = v4->sin_port; expect.sin_addr.s_addr = htonl (INADDR_LOOPBACK); GNUNET_assert (0 == memcmp (&expect, v4, alen)); GNUNET_free (addr); GNUNET_CONNECTION_destroy (lsock); GNUNET_CONNECTION_receive (asock, 1024, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5), &receive_check, cls); }
/** * Destroy connection with the service. This will automatically * cancel any pending "receive" request (however, the handler will * *NOT* be called, not even with a NULL message). Any pending * transmission request will also be cancelled UNLESS the callback for * the transmission request has already been called, in which case the * transmission 'finish_pending_write' argument determines whether or * not the write is guaranteed to complete before the socket is fully * destroyed (unless, of course, there is an error with the server in * which case the message may still be lost). * * @param client handle to the service connection */ void GNUNET_CLIENT_disconnect (struct GNUNET_CLIENT_Connection *client) { if (GNUNET_YES == client->in_receive) { GNUNET_CONNECTION_receive_cancel (client->connection); client->in_receive = GNUNET_NO; } if (NULL != client->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (client->th); client->th = NULL; } if (NULL != client->connection) { GNUNET_CONNECTION_destroy (client->connection); client->connection = NULL; } if (GNUNET_SCHEDULER_NO_TASK != client->receive_task) { GNUNET_SCHEDULER_cancel (client->receive_task); client->receive_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != client->tag) { GNUNET_free (client->tag); client->tag = NULL; } client->receiver_handler = NULL; GNUNET_array_grow (client->received_buf, client->received_size, 0); GNUNET_free (client->service_name); GNUNET_free (client); }
/** * We've failed for good to establish a connection (timeout or * no more addresses to try). * * @param connection the connection we tried to establish */ static void connect_fail_continuation (struct GNUNET_CONNECTION_Handle *connection) { LOG (GNUNET_ERROR_TYPE_INFO, _("Failed to establish TCP connection to `%s:%u', no further addresses to try.\n"), connection->hostname, connection->port); GNUNET_break (NULL == connection->ap_head); GNUNET_break (NULL == connection->ap_tail); GNUNET_break (GNUNET_NO == connection->dns_active); GNUNET_break (NULL == connection->sock); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->write_task); /* signal errors for jobs that used to wait on the connection */ connection->destroy_later = 1; if (NULL != connection->receiver) signal_receive_error (connection, ECONNREFUSED); if (NULL != connection->nth.notify_ready) { GNUNET_assert (connection->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK); GNUNET_SCHEDULER_cancel (connection->nth.timeout_task); connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK; signal_transmit_error (connection, ECONNREFUSED); } if (-1 == connection->destroy_later) { /* do it now */ connection->destroy_later = 0; GNUNET_CONNECTION_destroy (connection); return; } connection->destroy_later = 0; }
/** * Connection notifies us about failure or success of a transmission * request. Either pass it on to our user or, if possible, retry. * * @param cls our "struct GNUNET_CLIENT_TransmissionHandle" * @param size number of bytes available for transmission * @param buf where to write them * @return number of bytes written to buf */ static size_t client_notify (void *cls, size_t size, void *buf) { struct GNUNET_CLIENT_TransmitHandle *th = cls; struct GNUNET_CLIENT_Connection *client = th->client; size_t ret; struct GNUNET_TIME_Relative delay; th->th = NULL; client->th = NULL; if (NULL == buf) { delay = GNUNET_TIME_absolute_get_remaining (th->timeout); delay.rel_value /= 2; if ((GNUNET_YES != th->auto_retry) || (0 == --th->attempts_left) || (delay.rel_value < 1)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission failed %u times, giving up.\n", MAX_ATTEMPTS - th->attempts_left); GNUNET_break (0 == th->notify (th->notify_cls, 0, NULL)); GNUNET_free (th); return 0; } /* auto-retry */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to connect to `%s', automatically trying again.\n", client->service_name); if (GNUNET_YES == client->in_receive) { GNUNET_CONNECTION_receive_cancel (client->connection); client->in_receive = GNUNET_NO; } GNUNET_CONNECTION_destroy (client->connection); client->connection = NULL; delay = GNUNET_TIME_relative_min (delay, client->back_off); client->back_off = GNUNET_TIME_relative_min (GNUNET_TIME_relative_multiply (client->back_off, 2), GNUNET_TIME_UNIT_SECONDS); LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission failed %u times, trying again in %s.\n", MAX_ATTEMPTS - th->attempts_left, GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); client->th = th; th->reconnect_task = GNUNET_SCHEDULER_add_delayed (delay, &client_delayed_retry, th); return 0; } GNUNET_assert (size >= th->size); ret = th->notify (th->notify_cls, size, buf); GNUNET_free (th); return ret; }
static void receive_check (void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode) { int *ok = cls; GNUNET_assert (buf != NULL); /* no timeout */ if (0 == memcmp (&"Hello World"[sofar], buf, available)) sofar += available; if (sofar < 12) { GNUNET_CONNECTION_receive (asock, 1024, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5), &receive_check, cls); } else { *ok = 0; GNUNET_CONNECTION_destroy (csock); GNUNET_CONNECTION_destroy (asock); } }
static size_t send_kilo (void *cls, size_t size, void *buf) { int *ok = cls; if (size == 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got the desired timeout!\n"); GNUNET_assert (buf == NULL); *ok = 0; GNUNET_CONNECTION_destroy (lsock); GNUNET_CONNECTION_destroy (csock); return 0; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending kilo to fill buffer.\n"); GNUNET_assert (size >= 1024); memset (buf, 42, 1024); GNUNET_assert (NULL != GNUNET_CONNECTION_notify_transmit_ready (csock, 1024, GNUNET_TIME_UNIT_SECONDS, &send_kilo, cls)); return 1024; }
static void run_accept (void *cls) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test accepts connection\n"); asock = GNUNET_CONNECTION_create_from_accept (NULL, NULL, ls); GNUNET_assert (asock != NULL); GNUNET_assert (GNUNET_YES == GNUNET_CONNECTION_check (asock)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test destroys listen socket\n"); GNUNET_CONNECTION_destroy (lsock); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test asks to receive on accepted socket\n"); GNUNET_CONNECTION_receive (asock, 1024, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5), &receive_check, cls); }