connection.c | connection.c | |||
---|---|---|---|---|
skipping to change at line 42 | skipping to change at line 42 | |||
*/ | */ | |||
#include "platform.h" | #include "platform.h" | |||
#include "gnunet_common.h" | #include "gnunet_common.h" | |||
#include "gnunet_connection_lib.h" | #include "gnunet_connection_lib.h" | |||
#include "gnunet_container_lib.h" | #include "gnunet_container_lib.h" | |||
#include "gnunet_resolver_service.h" | #include "gnunet_resolver_service.h" | |||
#include "gnunet_scheduler_lib.h" | #include "gnunet_scheduler_lib.h" | |||
#include "gnunet_server_lib.h" | #include "gnunet_server_lib.h" | |||
#define DEBUG_CONNECTION GNUNET_EXTRA_LOGGING | ||||
#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) | #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) | |||
#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) | #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) | |||
/** | /** | |||
* Possible functions to call after connect failed or succeeded. | * Possible functions to call after connect failed or succeeded. | |||
*/ | */ | |||
enum ConnectContinuations | enum ConnectContinuations | |||
{ | { | |||
/** | /** | |||
skipping to change at line 470 | skipping to change at line 468 | |||
GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); | |||
GNUNET_free (uaddr); | GNUNET_free (uaddr); | |||
return NULL; | return NULL; | |||
} | } | |||
ret = GNUNET_malloc (sizeof (struct GNUNET_CONNECTION_Handle)); | ret = GNUNET_malloc (sizeof (struct GNUNET_CONNECTION_Handle)); | |||
ret->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE; | ret->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE; | |||
ret->write_buffer = GNUNET_malloc (ret->write_buffer_size); | ret->write_buffer = GNUNET_malloc (ret->write_buffer_size); | |||
ret->addr = uaddr; | ret->addr = uaddr; | |||
ret->addrlen = addrlen; | ret->addrlen = addrlen; | |||
ret->sock = sock; | ret->sock = sock; | |||
#if DEBUG_CONNECTION | LOG (GNUNET_ERROR_TYPE_INFO, | |||
LOG (GNUNET_ERROR_TYPE_INFO, _("Accepting connection from `%s': %p\n"), | _("Accepting connection from `%s': %p\n"), | |||
GNUNET_a2s (uaddr, addrlen), ret); | GNUNET_a2s (uaddr, addrlen), ret); | |||
#endif | ||||
return ret; | return ret; | |||
} | } | |||
/** | /** | |||
* Obtain the network address of the other party. | * Obtain the network address of the other party. | |||
* | * | |||
* @param sock the client to get the address for | * @param sock the client to get the address for | |||
* @param addr where to store the address | * @param addr where to store the address | |||
* @param addrlen where to store the length of the address | * @param addrlen where to store the length of the address | |||
* @return GNUNET_OK on success | * @return GNUNET_OK on success | |||
skipping to change at line 528 | skipping to change at line 525 | |||
destroy_continuation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | destroy_continuation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
{ | { | |||
struct GNUNET_CONNECTION_Handle *sock = cls; | struct GNUNET_CONNECTION_Handle *sock = cls; | |||
GNUNET_CONNECTION_TransmitReadyNotify notify; | GNUNET_CONNECTION_TransmitReadyNotify notify; | |||
struct AddressProbe *pos; | struct AddressProbe *pos; | |||
sock->destroy_task = GNUNET_SCHEDULER_NO_TASK; | sock->destroy_task = GNUNET_SCHEDULER_NO_TASK; | |||
GNUNET_assert (sock->dns_active == NULL); | GNUNET_assert (sock->dns_active == NULL); | |||
if (0 != (sock->ccs & COCO_TRANSMIT_READY)) | if (0 != (sock->ccs & COCO_TRANSMIT_READY)) | |||
{ | { | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroy waits for CCS-TR to be done (%p) \n", | LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroy waits for CCS-TR to be done (%p) \n", | |||
sock); | sock); | |||
#endif | ||||
sock->ccs |= COCO_DESTROY_CONTINUATION; | sock->ccs |= COCO_DESTROY_CONTINUATION; | |||
return; | return; | |||
} | } | |||
if (sock->write_task != GNUNET_SCHEDULER_NO_TASK) | if (sock->write_task != GNUNET_SCHEDULER_NO_TASK) | |||
{ | { | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"Destroy waits for write_task to be done (%p)\n", sock); | "Destroy waits for write_task to be done (%p)\n", sock); | |||
#endif | ||||
GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == sock->destroy_task); | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == sock->destroy_task); | |||
sock->destroy_task = | sock->destroy_task = | |||
GNUNET_SCHEDULER_add_after (sock->write_task, &destroy_continuation , | GNUNET_SCHEDULER_add_after (sock->write_task, &destroy_continuation , | |||
sock); | sock); | |||
return; | return; | |||
} | } | |||
if (0 != (sock->ccs & COCO_RECEIVE_AGAIN)) | if (0 != (sock->ccs & COCO_RECEIVE_AGAIN)) | |||
{ | { | |||
sock->ccs |= COCO_DESTROY_CONTINUATION; | sock->ccs |= COCO_DESTROY_CONTINUATION; | |||
return; | return; | |||
} | } | |||
if (sock->sock != NULL) | if (sock->sock != NULL) | |||
{ | { | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down socket (%p)\n", sock); | LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down socket (%p)\n", sock); | |||
#endif | ||||
if (sock->persist != GNUNET_YES) | if (sock->persist != GNUNET_YES) | |||
{ | { | |||
if ((GNUNET_YES != GNUNET_NETWORK_socket_shutdown (sock->sock, SHUT_R DWR)) | if ((GNUNET_YES != GNUNET_NETWORK_socket_shutdown (sock->sock, SHUT_R DWR)) | |||
&& (errno != ENOTCONN) && (errno != ECONNRESET)) | && (errno != ENOTCONN) && (errno != ECONNRESET)) | |||
LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "shutdown"); | LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "shutdown"); | |||
} | } | |||
} | } | |||
if (sock->read_task != GNUNET_SCHEDULER_NO_TASK) | if (sock->read_task != GNUNET_SCHEDULER_NO_TASK) | |||
{ | { | |||
GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == sock->destroy_task); | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == sock->destroy_task); | |||
sock->destroy_task = | sock->destroy_task = | |||
GNUNET_SCHEDULER_add_after (sock->read_task, &destroy_continuation, | GNUNET_SCHEDULER_add_after (sock->read_task, &destroy_continuation, | |||
sock); | sock); | |||
return; | return; | |||
} | } | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroy actually runs (%p)!\n", sock); | LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroy actually runs (%p)!\n", sock); | |||
#endif | ||||
while (NULL != (pos = sock->ap_head)) | while (NULL != (pos = sock->ap_head)) | |||
{ | { | |||
GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pos->sock)); | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pos->sock)); | |||
GNUNET_SCHEDULER_cancel (pos->task); | GNUNET_SCHEDULER_cancel (pos->task); | |||
GNUNET_CONTAINER_DLL_remove (sock->ap_head, sock->ap_tail, pos); | GNUNET_CONTAINER_DLL_remove (sock->ap_head, sock->ap_tail, pos); | |||
GNUNET_free (pos); | GNUNET_free (pos); | |||
} | } | |||
GNUNET_assert (sock->nth.timeout_task == GNUNET_SCHEDULER_NO_TASK); | GNUNET_assert (sock->nth.timeout_task == GNUNET_SCHEDULER_NO_TASK); | |||
GNUNET_assert (sock->ccs == COCO_NONE); | GNUNET_assert (sock->ccs == COCO_NONE); | |||
if (NULL != (notify = sock->nth.notify_ready)) | if (NULL != (notify = sock->nth.notify_ready)) | |||
skipping to change at line 601 | skipping to change at line 590 | |||
{ | { | |||
if (sock->persist != GNUNET_YES) | if (sock->persist != GNUNET_YES) | |||
GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock->sock)); | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock->sock)); | |||
else | else | |||
GNUNET_free (sock->sock); /* at least no memory leak (we deliberately | GNUNET_free (sock->sock); /* at least no memory leak (we deliberately | |||
* leak the socket in this special case) .. . */ | * leak the socket in this special case) .. . */ | |||
} | } | |||
GNUNET_free_non_null (sock->addr); | GNUNET_free_non_null (sock->addr); | |||
GNUNET_free_non_null (sock->hostname); | GNUNET_free_non_null (sock->hostname); | |||
GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == sock->destroy_task); | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == sock->destroy_task); | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, "Freeing memory of connection %p.\n", sock) ; | LOG (GNUNET_ERROR_TYPE_DEBUG, "Freeing memory of connection %p.\n", sock) ; | |||
#endif | ||||
GNUNET_free (sock->write_buffer); | GNUNET_free (sock->write_buffer); | |||
GNUNET_free (sock); | GNUNET_free (sock); | |||
} | } | |||
/** | /** | |||
* See if we are now connected. If not, wait longer for | * See if we are now connected. If not, wait longer for | |||
* connect to succeed. If connected, we should be able | * connect to succeed. If connected, we should be able | |||
* to write now as well, unless we timed out. | * to write now as well, unless we timed out. | |||
* | * | |||
* @param cls our connection handle | * @param cls our connection handle | |||
skipping to change at line 627 | skipping to change at line 614 | |||
transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | |||
/** | /** | |||
* We've failed for good to establish a connection. | * We've failed for good to establish a connection. | |||
* | * | |||
* @param h the connection we tried to establish | * @param h the connection we tried to establish | |||
*/ | */ | |||
static void | static void | |||
connect_fail_continuation (struct GNUNET_CONNECTION_Handle *h) | connect_fail_continuation (struct GNUNET_CONNECTION_Handle *h) | |||
{ | { | |||
#if DEBUG_CONNECTION | ||||
LOG ((0 != | LOG ((0 != | |||
strncmp (h->hostname, "localhost:", | strncmp (h->hostname, "localhost:", | |||
10)) ? GNUNET_ERROR_TYPE_INFO : GNUNET_ERROR_TYPE_WARNING, | 10)) ? GNUNET_ERROR_TYPE_INFO : GNUNET_ERROR_TYPE_WARNING, | |||
_ | _ | |||
("Failed to establish TCP connection to `%s:%u', no further addresse s to try.\n"), | ("Failed to establish TCP connection to `%s:%u', no further addresse s to try.\n"), | |||
h->hostname, h->port); | h->hostname, h->port); | |||
#endif | ||||
/* connect failed / timed out */ | /* connect failed / timed out */ | |||
GNUNET_break (h->ap_head == NULL); | GNUNET_break (h->ap_head == NULL); | |||
GNUNET_break (h->ap_tail == NULL); | GNUNET_break (h->ap_tail == NULL); | |||
GNUNET_break (h->dns_active == GNUNET_NO); | GNUNET_break (h->dns_active == GNUNET_NO); | |||
GNUNET_break (h->sock == NULL); | GNUNET_break (h->sock == NULL); | |||
/* trigger jobs that used to wait on "connect_task" */ | /* trigger jobs that used to wait on "connect_task" */ | |||
if (0 != (h->ccs & COCO_RECEIVE_AGAIN)) | if (0 != (h->ccs & COCO_RECEIVE_AGAIN)) | |||
{ | { | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"connect_fail_continuation triggers receive_again (%p)\n", h); | "connect_fail_continuation triggers receive_again (%p)\n", h); | |||
#endif | ||||
h->ccs -= COCO_RECEIVE_AGAIN; | h->ccs -= COCO_RECEIVE_AGAIN; | |||
h->read_task = GNUNET_SCHEDULER_add_now (&receive_again, h); | h->read_task = GNUNET_SCHEDULER_add_now (&receive_again, h); | |||
} | } | |||
if (0 != (h->ccs & COCO_TRANSMIT_READY)) | if (0 != (h->ccs & COCO_TRANSMIT_READY)) | |||
{ | { | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"connect_fail_continuation cancels timeout_task, triggers transmit _ready (%p)\n", | "connect_fail_continuation cancels timeout_task, triggers transmit _ready (%p)\n", | |||
h); | h); | |||
#endif | ||||
GNUNET_assert (h->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK); | GNUNET_assert (h->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK); | |||
GNUNET_SCHEDULER_cancel (h->nth.timeout_task); | GNUNET_SCHEDULER_cancel (h->nth.timeout_task); | |||
h->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK; | h->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK; | |||
h->ccs -= COCO_TRANSMIT_READY; | h->ccs -= COCO_TRANSMIT_READY; | |||
GNUNET_assert (h->nth.notify_ready != NULL); | GNUNET_assert (h->nth.notify_ready != NULL); | |||
GNUNET_assert (h->write_task == GNUNET_SCHEDULER_NO_TASK); | GNUNET_assert (h->write_task == GNUNET_SCHEDULER_NO_TASK); | |||
h->write_task = GNUNET_SCHEDULER_add_now (&transmit_ready, h); | h->write_task = GNUNET_SCHEDULER_add_now (&transmit_ready, h); | |||
} | } | |||
if (0 != (h->ccs & COCO_DESTROY_CONTINUATION)) | if (0 != (h->ccs & COCO_DESTROY_CONTINUATION)) | |||
{ | { | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"connect_fail_continuation runs destroy_continuation (%p)\n", h); | "connect_fail_continuation runs destroy_continuation (%p)\n", h); | |||
#endif | ||||
h->ccs -= COCO_DESTROY_CONTINUATION; | h->ccs -= COCO_DESTROY_CONTINUATION; | |||
GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->destroy_task); | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->destroy_task); | |||
h->destroy_task = GNUNET_SCHEDULER_add_now (&destroy_continuation, h); | h->destroy_task = GNUNET_SCHEDULER_add_now (&destroy_continuation, h); | |||
} | } | |||
} | } | |||
/** | /** | |||
* We've succeeded in establishing a connection. | * We've succeeded in establishing a connection. | |||
* | * | |||
* @param h the connection we tried to establish | * @param h the connection we tried to establish | |||
*/ | */ | |||
static void | static void | |||
connect_success_continuation (struct GNUNET_CONNECTION_Handle *h) | connect_success_continuation (struct GNUNET_CONNECTION_Handle *h) | |||
{ | { | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection to `%s' succeeded! (%p)\n", | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection to `%s' succeeded! (%p)\n", | |||
GNUNET_a2s (h->addr, h->addrlen), h); | GNUNET_a2s (h->addr, h->addrlen), h); | |||
#endif | ||||
/* trigger jobs that waited for the connection */ | /* trigger jobs that waited for the connection */ | |||
if (0 != (h->ccs & COCO_RECEIVE_AGAIN)) | if (0 != (h->ccs & COCO_RECEIVE_AGAIN)) | |||
{ | { | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"connect_success_continuation runs receive_again (%p)\n", h); | "connect_success_continuation runs receive_again (%p)\n", h); | |||
#endif | ||||
h->ccs -= COCO_RECEIVE_AGAIN; | h->ccs -= COCO_RECEIVE_AGAIN; | |||
h->read_task = GNUNET_SCHEDULER_add_now (&receive_again, h); | h->read_task = GNUNET_SCHEDULER_add_now (&receive_again, h); | |||
} | } | |||
if (0 != (h->ccs & COCO_TRANSMIT_READY)) | if (0 != (h->ccs & COCO_TRANSMIT_READY)) | |||
{ | { | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"connect_success_continuation runs transmit_ready, cancels timeout _task (%p)\n", | "connect_success_continuation runs transmit_ready, cancels timeout _task (%p)\n", | |||
h); | h); | |||
#endif | ||||
GNUNET_assert (h->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK); | GNUNET_assert (h->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK); | |||
GNUNET_SCHEDULER_cancel (h->nth.timeout_task); | GNUNET_SCHEDULER_cancel (h->nth.timeout_task); | |||
h->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK; | h->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK; | |||
h->ccs -= COCO_TRANSMIT_READY; | h->ccs -= COCO_TRANSMIT_READY; | |||
GNUNET_assert (h->write_task == GNUNET_SCHEDULER_NO_TASK); | GNUNET_assert (h->write_task == GNUNET_SCHEDULER_NO_TASK); | |||
GNUNET_assert (h->nth.notify_ready != NULL); | GNUNET_assert (h->nth.notify_ready != NULL); | |||
h->write_task = | h->write_task = | |||
GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining | GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining | |||
(h->nth.transmit_timeout), h->sock, | (h->nth.transmit_timeout), h->sock, | |||
&transmit_ready, h); | &transmit_ready, h); | |||
} | } | |||
if (0 != (h->ccs & COCO_DESTROY_CONTINUATION)) | if (0 != (h->ccs & COCO_DESTROY_CONTINUATION)) | |||
{ | { | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"connect_success_continuation runs destroy_continuation (%p)\n", h ); | "connect_success_continuation runs destroy_continuation (%p)\n", h ); | |||
#endif | ||||
h->ccs -= COCO_DESTROY_CONTINUATION; | h->ccs -= COCO_DESTROY_CONTINUATION; | |||
GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->destroy_task); | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->destroy_task); | |||
h->destroy_task = GNUNET_SCHEDULER_add_now (&destroy_continuation, h); | h->destroy_task = GNUNET_SCHEDULER_add_now (&destroy_continuation, h); | |||
} | } | |||
} | } | |||
/** | /** | |||
* Scheduler let us know that we're either ready to write on the | * Scheduler let us know that we're either ready to write on the | |||
* socket OR connect timed out. Do the right thing. | * socket OR connect timed out. Do the right thing. | |||
* | * | |||
skipping to change at line 808 | skipping to change at line 779 | |||
{ | { | |||
h->dns_active = NULL; | h->dns_active = NULL; | |||
if ((NULL == h->ap_head) && (NULL == h->sock)) | if ((NULL == h->ap_head) && (NULL == h->sock)) | |||
connect_fail_continuation (h); | connect_fail_continuation (h); | |||
return; | return; | |||
} | } | |||
if (h->sock != NULL) | if (h->sock != NULL) | |||
return; /* already connected */ | return; /* already connected */ | |||
GNUNET_assert (h->addr == NULL); | GNUNET_assert (h->addr == NULL); | |||
/* try to connect */ | /* try to connect */ | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"Trying to connect using address `%s:%u/%s:%u'\n", h->hostname, h->p ort, | "Trying to connect using address `%s:%u/%s:%u'\n", h->hostname, h->p ort, | |||
GNUNET_a2s (addr, addrlen), h->port); | GNUNET_a2s (addr, addrlen), h->port); | |||
#endif | ||||
ap = GNUNET_malloc (sizeof (struct AddressProbe) + addrlen); | ap = GNUNET_malloc (sizeof (struct AddressProbe) + addrlen); | |||
ap->addr = (const struct sockaddr *) &ap[1]; | ap->addr = (const struct sockaddr *) &ap[1]; | |||
memcpy (&ap[1], addr, addrlen); | memcpy (&ap[1], addr, addrlen); | |||
ap->addrlen = addrlen; | ap->addrlen = addrlen; | |||
ap->h = h; | ap->h = h; | |||
switch (ap->addr->sa_family) | switch (ap->addr->sa_family) | |||
{ | { | |||
case AF_INET: | case AF_INET: | |||
((struct sockaddr_in *) ap->addr)->sin_port = htons (h->port); | ((struct sockaddr_in *) ap->addr)->sin_port = htons (h->port); | |||
skipping to change at line 838 | skipping to change at line 807 | |||
GNUNET_break (0); | GNUNET_break (0); | |||
GNUNET_free (ap); | GNUNET_free (ap); | |||
return; /* not supported by us */ | return; /* not supported by us */ | |||
} | } | |||
ap->sock = GNUNET_NETWORK_socket_create (ap->addr->sa_family, SOCK_STREAM , 0); | ap->sock = GNUNET_NETWORK_socket_create (ap->addr->sa_family, SOCK_STREAM , 0); | |||
if (ap->sock == NULL) | if (ap->sock == NULL) | |||
{ | { | |||
GNUNET_free (ap); | GNUNET_free (ap); | |||
return; /* not supported by OS */ | return; /* not supported by OS */ | |||
} | } | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_INFO, _("Trying to connect to `%s' (%p)\n"), | LOG (GNUNET_ERROR_TYPE_INFO, _("Trying to connect to `%s' (%p)\n"), | |||
GNUNET_a2s (ap->addr, ap->addrlen), h); | GNUNET_a2s (ap->addr, ap->addrlen), h); | |||
#endif | ||||
if ((GNUNET_OK != | if ((GNUNET_OK != | |||
GNUNET_NETWORK_socket_connect (ap->sock, ap->addr, ap->addrlen)) && | GNUNET_NETWORK_socket_connect (ap->sock, ap->addr, ap->addrlen)) && | |||
(errno != EINPROGRESS)) | (errno != EINPROGRESS)) | |||
{ | { | |||
/* maybe refused / unsupported address, try next */ | /* maybe refused / unsupported address, try next */ | |||
LOG_STRERROR (GNUNET_ERROR_TYPE_INFO, "connect"); | LOG_STRERROR (GNUNET_ERROR_TYPE_INFO, "connect"); | |||
#if 0 | #if 0 | |||
LOG (GNUNET_ERROR_TYPE_INFO, _("Failed to connect to `%s' (%p)\n"), | LOG (GNUNET_ERROR_TYPE_INFO, _("Failed to connect to `%s' (%p)\n"), | |||
GNUNET_a2s (ap->addr, ap->addrlen), h); | GNUNET_a2s (ap->addr, ap->addrlen), h); | |||
#endif | #endif | |||
skipping to change at line 1007 | skipping to change at line 974 | |||
LOG_STRERROR (GNUNET_ERROR_TYPE_INFO, "connect"); | LOG_STRERROR (GNUNET_ERROR_TYPE_INFO, "connect"); | |||
LOG (GNUNET_ERROR_TYPE_INFO, _("Attempt to connect to `%s' failed\n"), | LOG (GNUNET_ERROR_TYPE_INFO, _("Attempt to connect to `%s' failed\n"), | |||
GNUNET_a2s (serv_addr, addrlen)); | GNUNET_a2s (serv_addr, addrlen)); | |||
GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (s)); | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (s)); | |||
return NULL; | return NULL; | |||
} | } | |||
ret = GNUNET_CONNECTION_create_from_existing (s); | ret = GNUNET_CONNECTION_create_from_existing (s); | |||
ret->addr = GNUNET_malloc (addrlen); | ret->addr = GNUNET_malloc (addrlen); | |||
memcpy (ret->addr, serv_addr, addrlen); | memcpy (ret->addr, serv_addr, addrlen); | |||
ret->addrlen = addrlen; | ret->addrlen = addrlen; | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_INFO, _("Trying to connect to `%s' (%p)\n"), | LOG (GNUNET_ERROR_TYPE_INFO, _("Trying to connect to `%s' (%p)\n"), | |||
GNUNET_a2s (serv_addr, addrlen), ret); | GNUNET_a2s (serv_addr, addrlen), ret); | |||
#endif | ||||
return ret; | return ret; | |||
} | } | |||
/** | /** | |||
* Check if socket is valid (no fatal errors have happened so far). | * Check if socket is valid (no fatal errors have happened so far). | |||
* Note that a socket that is still trying to connect is considered | * Note that a socket that is still trying to connect is considered | |||
* valid. | * valid. | |||
* | * | |||
* @param sock socket to check | * @param sock socket to check | |||
* @return GNUNET_YES if valid, GNUNET_NO otherwise | * @return GNUNET_YES if valid, GNUNET_NO otherwise | |||
skipping to change at line 1075 | skipping to change at line 1040 | |||
} | } | |||
/** | /** | |||
* Tell the receiver callback that a timeout was reached. | * Tell the receiver callback that a timeout was reached. | |||
*/ | */ | |||
static void | static void | |||
signal_timeout (struct GNUNET_CONNECTION_Handle *sh) | signal_timeout (struct GNUNET_CONNECTION_Handle *sh) | |||
{ | { | |||
GNUNET_CONNECTION_Receiver receiver; | GNUNET_CONNECTION_Receiver receiver; | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, "Network signals time out to receiver (%p)! \n", | LOG (GNUNET_ERROR_TYPE_DEBUG, "Network signals time out to receiver (%p)! \n", | |||
sh); | sh); | |||
#endif | ||||
GNUNET_assert (NULL != (receiver = sh->receiver)); | GNUNET_assert (NULL != (receiver = sh->receiver)); | |||
sh->receiver = NULL; | sh->receiver = NULL; | |||
receiver (sh->receiver_cls, NULL, 0, NULL, 0, 0); | receiver (sh->receiver_cls, NULL, 0, NULL, 0, 0); | |||
} | } | |||
/** | /** | |||
* Tell the receiver callback that we had an IO error. | * Tell the receiver callback that we had an IO error. | |||
*/ | */ | |||
static void | static void | |||
signal_error (struct GNUNET_CONNECTION_Handle *sh, int errcode) | signal_error (struct GNUNET_CONNECTION_Handle *sh, int errcode) | |||
skipping to change at line 1115 | skipping to change at line 1078 | |||
struct GNUNET_TIME_Absolute now; | struct GNUNET_TIME_Absolute now; | |||
char buffer[sh->max]; | char buffer[sh->max]; | |||
ssize_t ret; | ssize_t ret; | |||
GNUNET_CONNECTION_Receiver receiver; | GNUNET_CONNECTION_Receiver receiver; | |||
sh->read_task = GNUNET_SCHEDULER_NO_TASK; | sh->read_task = GNUNET_SCHEDULER_NO_TASK; | |||
if ((GNUNET_YES == sh->ignore_shutdown) && | if ((GNUNET_YES == sh->ignore_shutdown) && | |||
(0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))) | (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))) | |||
{ | { | |||
/* ignore shutdown request, go again immediately */ | /* ignore shutdown request, go again immediately */ | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"Ignoring shutdown signal per configuration\n"); | "Ignoring shutdown signal per configuration\n"); | |||
#endif | ||||
sh->read_task = | sh->read_task = | |||
GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining | GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining | |||
(sh->receive_timeout), sh->sock, | (sh->receive_timeout), sh->sock, | |||
&receive_ready, sh); | &receive_ready, sh); | |||
return; | return; | |||
} | } | |||
now = GNUNET_TIME_absolute_get (); | now = GNUNET_TIME_absolute_get (); | |||
if ((now.abs_value > sh->receive_timeout.abs_value) || | if ((now.abs_value > sh->receive_timeout.abs_value) || | |||
(0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) || | (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) || | |||
(0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))) | (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))) | |||
{ | { | |||
#if DEBUG_CONNECTION | ||||
if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | |||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"Receive from `%s' encounters error: time out by %llums... (%p)\ n", | "Receive from `%s' encounters error: time out by %llums... (%p)\ n", | |||
GNUNET_a2s (sh->addr, sh->addrlen), | GNUNET_a2s (sh->addr, sh->addrlen), | |||
GNUNET_TIME_absolute_get_duration (sh->receive_timeout).rel_valu e, | GNUNET_TIME_absolute_get_duration (sh->receive_timeout).rel_valu e, | |||
sh); | sh); | |||
#endif | ||||
signal_timeout (sh); | signal_timeout (sh); | |||
return; | return; | |||
} | } | |||
if (sh->sock == NULL) | if (sh->sock == NULL) | |||
{ | { | |||
/* connect failed for good */ | /* connect failed for good */ | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"Receive encounters error, socket closed... (%p)\n", sh); | "Receive encounters error, socket closed... (%p)\n", sh); | |||
#endif | ||||
signal_error (sh, ECONNREFUSED); | signal_error (sh, ECONNREFUSED); | |||
return; | return; | |||
} | } | |||
GNUNET_assert (GNUNET_NETWORK_fdset_isset (tc->read_ready, sh->sock)); | GNUNET_assert (GNUNET_NETWORK_fdset_isset (tc->read_ready, sh->sock)); | |||
RETRY: | RETRY: | |||
ret = GNUNET_NETWORK_socket_recv (sh->sock, buffer, sh->max); | ret = GNUNET_NETWORK_socket_recv (sh->sock, buffer, sh->max); | |||
if (ret == -1) | if (ret == -1) | |||
{ | { | |||
if (errno == EINTR) | if (errno == EINTR) | |||
goto RETRY; | goto RETRY; | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, "Error receiving: %s\n", STRERROR (errno) ); | LOG (GNUNET_ERROR_TYPE_DEBUG, "Error receiving: %s\n", STRERROR (errno) ); | |||
#endif | ||||
signal_error (sh, errno); | signal_error (sh, errno); | |||
return; | return; | |||
} | } | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"receive_ready read %u/%u bytes from `%s' (%p)!\n", (unsigned int) r et, | "receive_ready read %u/%u bytes from `%s' (%p)!\n", (unsigned int) r et, | |||
sh->max, GNUNET_a2s (sh->addr, sh->addrlen), sh); | sh->max, GNUNET_a2s (sh->addr, sh->addrlen), sh); | |||
#endif | ||||
GNUNET_assert (NULL != (receiver = sh->receiver)); | GNUNET_assert (NULL != (receiver = sh->receiver)); | |||
sh->receiver = NULL; | sh->receiver = NULL; | |||
receiver (sh->receiver_cls, buffer, ret, sh->addr, sh->addrlen, 0); | receiver (sh->receiver_cls, buffer, ret, sh->addr, sh->addrlen, 0); | |||
} | } | |||
/** | /** | |||
* This function is called after establishing a connection either has | * This function is called after establishing a connection either has | |||
* succeeded or timed out. Note that it is possible that the attempt | * succeeded or timed out. Note that it is possible that the attempt | |||
* timed out and that we're immediately retrying. If we are retrying, | * timed out and that we're immediately retrying. If we are retrying, | |||
* we need to wait again (or timeout); if we succeeded, we need to | * we need to wait again (or timeout); if we succeeded, we need to | |||
skipping to change at line 1194 | skipping to change at line 1147 | |||
static void | static void | |||
receive_again (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | receive_again (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
{ | { | |||
struct GNUNET_CONNECTION_Handle *sh = cls; | struct GNUNET_CONNECTION_Handle *sh = cls; | |||
struct GNUNET_TIME_Absolute now; | struct GNUNET_TIME_Absolute now; | |||
sh->read_task = GNUNET_SCHEDULER_NO_TASK; | sh->read_task = GNUNET_SCHEDULER_NO_TASK; | |||
if (sh->sock == NULL) | if (sh->sock == NULL) | |||
{ | { | |||
/* not connected and no longer trying */ | /* not connected and no longer trying */ | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"Receive encounters error, socket closed (%p)...\n", sh); | "Receive encounters error, socket closed (%p)...\n", sh); | |||
#endif | ||||
signal_error (sh, ECONNREFUSED); | signal_error (sh, ECONNREFUSED); | |||
return; | return; | |||
} | } | |||
now = GNUNET_TIME_absolute_get (); | now = GNUNET_TIME_absolute_get (); | |||
if ((now.abs_value > sh->receive_timeout.abs_value) || | if ((now.abs_value > sh->receive_timeout.abs_value) || | |||
(0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))) | (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))) | |||
{ | { | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"Receive encounters error: time out (%p)...\n", sh); | "Receive encounters error: time out (%p)...\n", sh); | |||
#endif | ||||
signal_timeout (sh); | signal_timeout (sh); | |||
return; | return; | |||
} | } | |||
GNUNET_assert (sh->sock != NULL); | GNUNET_assert (sh->sock != NULL); | |||
/* connect succeeded, wait for data! */ | /* connect succeeded, wait for data! */ | |||
sh->read_task = | sh->read_task = | |||
GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining | GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining | |||
(sh->receive_timeout), sh->sock, | (sh->receive_timeout), sh->sock, | |||
&receive_ready, sh); | &receive_ready, sh); | |||
} | } | |||
skipping to change at line 1360 | skipping to change at line 1309 | |||
* | * | |||
* @param cls the 'struct GNUNET_CONNECTION_Handle' | * @param cls the 'struct GNUNET_CONNECTION_Handle' | |||
* @param tc scheduler context | * @param tc scheduler context | |||
*/ | */ | |||
static void | static void | |||
transmit_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | transmit_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
{ | { | |||
struct GNUNET_CONNECTION_Handle *sock = cls; | struct GNUNET_CONNECTION_Handle *sock = cls; | |||
GNUNET_CONNECTION_TransmitReadyNotify notify; | GNUNET_CONNECTION_TransmitReadyNotify notify; | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, "transmit_timeout running (%p)\n", sock); | ||||
#endif | ||||
sock->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK; | sock->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK; | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"Transmit to `%s:%u/%s' fails, time out reached (%p).\n", sock->host | "Transmit to `%s:%u/%s' fails, time out reached (%p).\n", | |||
name, | sock->hostname, | |||
sock->port, GNUNET_a2s (sock->addr, sock->addrlen), sock); | sock->port, GNUNET_a2s (sock->addr, sock->addrlen), sock); | |||
#endif | ||||
GNUNET_assert (0 != (sock->ccs & COCO_TRANSMIT_READY)); | GNUNET_assert (0 != (sock->ccs & COCO_TRANSMIT_READY)); | |||
sock->ccs -= COCO_TRANSMIT_READY; /* remove request */ | sock->ccs -= COCO_TRANSMIT_READY; /* remove request */ | |||
notify = sock->nth.notify_ready; | notify = sock->nth.notify_ready; | |||
sock->nth.notify_ready = NULL; | sock->nth.notify_ready = NULL; | |||
notify (sock->nth.notify_ready_cls, 0, NULL); | notify (sock->nth.notify_ready_cls, 0, NULL); | |||
} | } | |||
/** | /** | |||
* Task invoked by the scheduler when we failed to connect | * Task invoked by the scheduler when we failed to connect | |||
* at the time of being asked to transmit. | * at the time of being asked to transmit. | |||
skipping to change at line 1391 | skipping to change at line 1336 | |||
* | * | |||
* @param cls the 'struct GNUNET_CONNECTION_Handle' | * @param cls the 'struct GNUNET_CONNECTION_Handle' | |||
* @param tc scheduler context | * @param tc scheduler context | |||
*/ | */ | |||
static void | static void | |||
connect_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | connect_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
{ | { | |||
struct GNUNET_CONNECTION_Handle *sock = cls; | struct GNUNET_CONNECTION_Handle *sock = cls; | |||
GNUNET_CONNECTION_TransmitReadyNotify notify; | GNUNET_CONNECTION_TransmitReadyNotify notify; | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"Transmission request of size %u fails (%s/%u), connection failed (% p).\n", | "Transmission request of size %u fails (%s/%u), connection failed (% p).\n", | |||
sock->nth.notify_size, sock->hostname, sock->port, sock); | sock->nth.notify_size, sock->hostname, sock->port, sock); | |||
#endif | ||||
sock->write_task = GNUNET_SCHEDULER_NO_TASK; | sock->write_task = GNUNET_SCHEDULER_NO_TASK; | |||
notify = sock->nth.notify_ready; | notify = sock->nth.notify_ready; | |||
sock->nth.notify_ready = NULL; | sock->nth.notify_ready = NULL; | |||
notify (sock->nth.notify_ready_cls, 0, NULL); | notify (sock->nth.notify_ready_cls, 0, NULL); | |||
} | } | |||
/** | /** | |||
* FIXME | * FIXME | |||
* | * | |||
* @param sock FIXME | * @param sock FIXME | |||
skipping to change at line 1448 | skipping to change at line 1391 | |||
* @param tc task context describing why we are here | * @param tc task context describing why we are here | |||
*/ | */ | |||
static void | static void | |||
transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
{ | { | |||
struct GNUNET_CONNECTION_Handle *sock = cls; | struct GNUNET_CONNECTION_Handle *sock = cls; | |||
GNUNET_CONNECTION_TransmitReadyNotify notify; | GNUNET_CONNECTION_TransmitReadyNotify notify; | |||
ssize_t ret; | ssize_t ret; | |||
size_t have; | size_t have; | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, "transmit_ready running (%p).\n", sock); | LOG (GNUNET_ERROR_TYPE_DEBUG, "transmit_ready running (%p).\n", sock); | |||
#endif | ||||
GNUNET_assert (sock->write_task != GNUNET_SCHEDULER_NO_TASK); | GNUNET_assert (sock->write_task != GNUNET_SCHEDULER_NO_TASK); | |||
sock->write_task = GNUNET_SCHEDULER_NO_TASK; | sock->write_task = GNUNET_SCHEDULER_NO_TASK; | |||
GNUNET_assert (sock->nth.timeout_task == GNUNET_SCHEDULER_NO_TASK); | GNUNET_assert (sock->nth.timeout_task == GNUNET_SCHEDULER_NO_TASK); | |||
if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | |||
{ | { | |||
if ((sock->ignore_shutdown == GNUNET_YES) && (NULL != sock->sock)) | if ((sock->ignore_shutdown == GNUNET_YES) && (NULL != sock->sock)) | |||
goto SCHEDULE_WRITE; /* ignore shutdown, go again immediately */ | goto SCHEDULE_WRITE; /* ignore shutdown, go again immediately */ | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"Transmit to `%s' fails, shutdown happened (%p).\n", | "Transmit to `%s' fails, shutdown happened (%p).\n", | |||
GNUNET_a2s (sock->addr, sock->addrlen), sock); | GNUNET_a2s (sock->addr, sock->addrlen), sock); | |||
#endif | ||||
notify = sock->nth.notify_ready; | notify = sock->nth.notify_ready; | |||
if (NULL != notify) | if (NULL != notify) | |||
{ | { | |||
sock->nth.notify_ready = NULL; | sock->nth.notify_ready = NULL; | |||
notify (sock->nth.notify_ready_cls, 0, NULL); | notify (sock->nth.notify_ready_cls, 0, NULL); | |||
} | } | |||
return; | return; | |||
} | } | |||
if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) | |||
{ | { | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"Transmit to `%s' fails, time out reached (%p).\n", | "Transmit to `%s' fails, time out reached (%p).\n", | |||
GNUNET_a2s (sock->addr, sock->addrlen), sock); | GNUNET_a2s (sock->addr, sock->addrlen), sock); | |||
#endif | ||||
notify = sock->nth.notify_ready; | notify = sock->nth.notify_ready; | |||
GNUNET_assert (NULL != notify); | GNUNET_assert (NULL != notify); | |||
sock->nth.notify_ready = NULL; | sock->nth.notify_ready = NULL; | |||
notify (sock->nth.notify_ready_cls, 0, NULL); | notify (sock->nth.notify_ready_cls, 0, NULL); | |||
return; | return; | |||
} | } | |||
GNUNET_assert (NULL != sock->sock); | GNUNET_assert (NULL != sock->sock); | |||
if (tc->write_ready == NULL) | if (tc->write_ready == NULL) | |||
{ | { | |||
/* special circumstances (in particular, | /* special circumstances (in particular, | |||
* PREREQ_DONE after connect): not yet ready to write, | * PREREQ_DONE after connect): not yet ready to write, | |||
* but no "fatal" error either. Hence retry. */ | * but no "fatal" error either. Hence retry. */ | |||
goto SCHEDULE_WRITE; | goto SCHEDULE_WRITE; | |||
} | } | |||
if (!GNUNET_NETWORK_fdset_isset (tc->write_ready, sock->sock)) | if (!GNUNET_NETWORK_fdset_isset (tc->write_ready, sock->sock)) | |||
{ | { | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_INFO, | LOG (GNUNET_ERROR_TYPE_INFO, | |||
_ | _ | |||
("Could not satisfy pending transmission request, socket closed or connect failed (%p).\n"), | ("Could not satisfy pending transmission request, socket closed or connect failed (%p).\n"), | |||
sock); | sock); | |||
#endif | ||||
transmit_error (sock); | transmit_error (sock); | |||
return; /* connect failed for good, we're finished */ | return; /* connect failed for good, we're finished */ | |||
} | } | |||
GNUNET_assert (sock->write_buffer_off >= sock->write_buffer_pos); | GNUNET_assert (sock->write_buffer_off >= sock->write_buffer_pos); | |||
if ((sock->nth.notify_ready != NULL) && | if ((sock->nth.notify_ready != NULL) && | |||
(sock->write_buffer_size < sock->nth.notify_size)) | (sock->write_buffer_size < sock->nth.notify_size)) | |||
{ | { | |||
sock->write_buffer = | sock->write_buffer = | |||
GNUNET_realloc (sock->write_buffer, sock->nth.notify_size); | GNUNET_realloc (sock->write_buffer, sock->nth.notify_size); | |||
sock->write_buffer_size = sock->nth.notify_size; | sock->write_buffer_size = sock->nth.notify_size; | |||
skipping to change at line 1530 | skipping to change at line 1465 | |||
GNUNET_assert (sock->write_buffer_pos <= sock->write_buffer_size); | GNUNET_assert (sock->write_buffer_pos <= sock->write_buffer_size); | |||
RETRY: | RETRY: | |||
ret = | ret = | |||
GNUNET_NETWORK_socket_send (sock->sock, | GNUNET_NETWORK_socket_send (sock->sock, | |||
&sock->write_buffer[sock->write_buffer_po s], | &sock->write_buffer[sock->write_buffer_po s], | |||
have); | have); | |||
if (ret == -1) | if (ret == -1) | |||
{ | { | |||
if (errno == EINTR) | if (errno == EINTR) | |||
goto RETRY; | goto RETRY; | |||
#if 0 | ||||
int en = errno; | ||||
LOG (GNUNET_ERROR_TYPE_ERROR, _("Failed to send to `%s': %s\n"), | ||||
GNUNET_a2s (sock->addr, sock->addrlen), STRERROR (en)); | ||||
#endif | ||||
#if DEBUG_CONNECTION | ||||
LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "send"); | LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "send"); | |||
#endif | ||||
transmit_error (sock); | transmit_error (sock); | |||
return; | return; | |||
} | } | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"transmit_ready transmitted %u/%u bytes to `%s' (%p)\n", | "transmit_ready transmitted %u/%u bytes to `%s' (%p)\n", | |||
(unsigned int) ret, have, GNUNET_a2s (sock->addr, sock->addrlen), so ck); | (unsigned int) ret, have, GNUNET_a2s (sock->addr, sock->addrlen), so ck); | |||
#endif | ||||
sock->write_buffer_pos += ret; | sock->write_buffer_pos += ret; | |||
if (sock->write_buffer_pos == sock->write_buffer_off) | if (sock->write_buffer_pos == sock->write_buffer_off) | |||
{ | { | |||
/* transmitted all pending data */ | /* transmitted all pending data */ | |||
sock->write_buffer_pos = 0; | sock->write_buffer_pos = 0; | |||
sock->write_buffer_off = 0; | sock->write_buffer_off = 0; | |||
} | } | |||
if ((sock->write_buffer_off == 0) && (NULL == sock->nth.notify_ready)) | if ((sock->write_buffer_off == 0) && (NULL == sock->nth.notify_ready)) | |||
return; /* all data sent! */ | return; /* all data sent! */ | |||
/* not done writing, schedule more */ | /* not done writing, schedule more */ | |||
SCHEDULE_WRITE: | SCHEDULE_WRITE: | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"Re-scheduling transmit_ready (more to do) (%p).\n", sock); | "Re-scheduling transmit_ready (more to do) (%p).\n", sock); | |||
#endif | ||||
have = sock->write_buffer_off - sock->write_buffer_pos; | have = sock->write_buffer_off - sock->write_buffer_pos; | |||
GNUNET_assert ((sock->nth.notify_ready != NULL) || (have > 0)); | GNUNET_assert ((sock->nth.notify_ready != NULL) || (have > 0)); | |||
if (sock->write_task == GNUNET_SCHEDULER_NO_TASK) | if (sock->write_task == GNUNET_SCHEDULER_NO_TASK) | |||
sock->write_task = | sock->write_task = | |||
GNUNET_SCHEDULER_add_write_net ((sock->nth.notify_ready == | GNUNET_SCHEDULER_add_write_net ((sock->nth.notify_ready == | |||
NULL) ? GNUNET_TIME_UNIT_FOREVER_R EL : | NULL) ? GNUNET_TIME_UNIT_FOREVER_R EL : | |||
GNUNET_TIME_absolute_get_remaining | GNUNET_TIME_absolute_get_remaining | |||
(sock->nth.transmit_timeout), | (sock->nth.transmit_timeout), | |||
sock->sock, &transmit_ready, sock); | sock->sock, &transmit_ready, sock); | |||
} | } | |||
skipping to change at line 1622 | skipping to change at line 1545 | |||
{ | { | |||
if (sock->write_task != GNUNET_SCHEDULER_NO_TASK) | if (sock->write_task != GNUNET_SCHEDULER_NO_TASK) | |||
GNUNET_SCHEDULER_cancel (sock->write_task); | GNUNET_SCHEDULER_cancel (sock->write_task); | |||
sock->write_task = GNUNET_SCHEDULER_add_now (&connect_error, sock); | sock->write_task = GNUNET_SCHEDULER_add_now (&connect_error, sock); | |||
return &sock->nth; | return &sock->nth; | |||
} | } | |||
if (GNUNET_SCHEDULER_NO_TASK != sock->write_task) | if (GNUNET_SCHEDULER_NO_TASK != sock->write_task) | |||
return &sock->nth; | return &sock->nth; | |||
if (sock->sock != NULL) | if (sock->sock != NULL) | |||
{ | { | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduling transmit_ready (%p).\n", sock ); | LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduling transmit_ready (%p).\n", sock ); | |||
#endif | ||||
sock->write_task = | sock->write_task = | |||
GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining | GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining | |||
(sock->nth.transmit_timeout), | (sock->nth.transmit_timeout), | |||
sock->sock, &transmit_ready, sock); | sock->sock, &transmit_ready, sock); | |||
} | } | |||
else | else | |||
{ | { | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"CCS-Scheduling transmit_ready, adding timeout task (%p).\n", sock ); | "CCS-Scheduling transmit_ready, adding timeout task (%p).\n", sock ); | |||
#endif | ||||
sock->ccs |= COCO_TRANSMIT_READY; | sock->ccs |= COCO_TRANSMIT_READY; | |||
sock->nth.timeout_task = | sock->nth.timeout_task = | |||
GNUNET_SCHEDULER_add_delayed (timeout, &transmit_timeout, sock); | GNUNET_SCHEDULER_add_delayed (timeout, &transmit_timeout, sock); | |||
} | } | |||
return &sock->nth; | return &sock->nth; | |||
} | } | |||
/** | /** | |||
* Cancel the specified transmission-ready notification. | * Cancel the specified transmission-ready notification. | |||
* | * | |||
* @param th notification to cancel | * @param th notification to cancel | |||
*/ | */ | |||
void | void | |||
GNUNET_CONNECTION_notify_transmit_ready_cancel (struct | GNUNET_CONNECTION_notify_transmit_ready_cancel (struct | |||
GNUNET_CONNECTION_TransmitH andle | GNUNET_CONNECTION_TransmitH andle | |||
*th) | *th) | |||
{ | { | |||
GNUNET_assert (th->notify_ready != NULL); | GNUNET_assert (th->notify_ready != NULL); | |||
if (0 != (th->sh->ccs & COCO_TRANSMIT_READY)) | if (0 != (th->sh->ccs & COCO_TRANSMIT_READY)) | |||
{ | { | |||
#if DEBUG_CONNECTION | ||||
LOG (GNUNET_ERROR_TYPE_DEBUG, | LOG (GNUNET_ERROR_TYPE_DEBUG, | |||
"notify_transmit_ready_cancel cancels timeout_task (%p)\n", th); | "notify_transmit_ready_cancel cancels timeout_task (%p)\n", th); | |||
#endif | ||||
GNUNET_SCHEDULER_cancel (th->timeout_task); | GNUNET_SCHEDULER_cancel (th->timeout_task); | |||
th->timeout_task = GNUNET_SCHEDULER_NO_TASK; | th->timeout_task = GNUNET_SCHEDULER_NO_TASK; | |||
th->sh->ccs -= COCO_TRANSMIT_READY; | th->sh->ccs -= COCO_TRANSMIT_READY; | |||
} | } | |||
else | else | |||
{ | { | |||
if (th->sh->write_task != GNUNET_SCHEDULER_NO_TASK) | if (th->sh->write_task != GNUNET_SCHEDULER_NO_TASK) | |||
{ | { | |||
GNUNET_SCHEDULER_cancel (th->sh->write_task); | GNUNET_SCHEDULER_cancel (th->sh->write_task); | |||
th->sh->write_task = GNUNET_SCHEDULER_NO_TASK; | th->sh->write_task = GNUNET_SCHEDULER_NO_TASK; | |||
End of changes. 77 change blocks. | ||||
88 lines changed or deleted | 4 lines changed or added | |||
This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |