diff options
Diffstat (limited to 'src/util/server_nc.c')
-rw-r--r-- | src/util/server_nc.c | 100 |
1 files changed, 48 insertions, 52 deletions
diff --git a/src/util/server_nc.c b/src/util/server_nc.c index 08ffd4b..6e0181e 100644 --- a/src/util/server_nc.c +++ b/src/util/server_nc.c @@ -36,8 +36,6 @@ #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) -#define DEBUG_SERVER_NC GNUNET_EXTRA_LOGGING - /** * Entry in list of messages pending to be transmitted. */ @@ -75,11 +73,16 @@ struct ClientList { /** - * This is a linked list. + * This is a doubly linked list. */ struct ClientList *next; /** + * This is a doubly linked list. + */ + struct ClientList *prev; + + /** * Overall context this client belongs to. */ struct GNUNET_SERVER_NotificationContext *nc; @@ -92,7 +95,7 @@ struct ClientList /** * Handle for pending transmission request to the client (or NULL). */ - struct GNUNET_CONNECTION_TransmitHandle *th; + struct GNUNET_SERVER_TransmitHandle *th; /** * Head of linked list of requests queued for transmission. @@ -129,9 +132,14 @@ struct GNUNET_SERVER_NotificationContext struct GNUNET_SERVER_Handle *server; /** - * List of clients receiving notifications. + * Head of list of clients receiving notifications. */ - struct ClientList *clients; + struct ClientList *clients_head; + + /** + * Tail of list of clients receiving notifications. + */ + struct ClientList *clients_tail; /** * Maximum number of optional messages to queue per client. @@ -152,45 +160,37 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct GNUNET_SERVER_NotificationContext *nc = cls; struct ClientList *pos; - struct ClientList *prev; struct PendingMessageList *pml; - if (client == NULL) + if (NULL == client) { nc->server = NULL; return; } - prev = NULL; - pos = nc->clients; - while (NULL != pos) - { + for (pos = nc->clients_head; NULL != pos; pos = pos->next) if (pos->client == client) break; - prev = pos; - pos = pos->next; - } - if (pos == NULL) + if (NULL == pos) return; -#if DEBUG_SERVER_NC LOG (GNUNET_ERROR_TYPE_DEBUG, "Client disconnected, cleaning up %u messages in NC queue\n", pos->num_pending); -#endif - if (prev == NULL) - nc->clients = pos->next; - else - prev->next = pos->next; + GNUNET_CONTAINER_DLL_remove (nc->clients_head, + nc->clients_tail, + pos); while (NULL != (pml = pos->pending_head)) { GNUNET_CONTAINER_DLL_remove (pos->pending_head, pos->pending_tail, pml); GNUNET_free (pml); + pos->num_pending--; } - if (pos->th != NULL) + if (NULL != pos->th) { - GNUNET_CONNECTION_notify_transmit_ready_cancel (pos->th); + GNUNET_SERVER_notify_transmit_ready_cancel (pos->th); pos->th = NULL; } GNUNET_SERVER_client_drop (client); + GNUNET_assert (0 == pos->num_pending); GNUNET_free (pos); } @@ -231,18 +231,27 @@ GNUNET_SERVER_notification_context_destroy (struct struct ClientList *pos; struct PendingMessageList *pml; - while (NULL != (pos = nc->clients)) + while (NULL != (pos = nc->clients_head)) { - nc->clients = pos->next; + GNUNET_CONTAINER_DLL_remove (nc->clients_head, + nc->clients_tail, + pos); + if (NULL != pos->th) + { + GNUNET_SERVER_notify_transmit_ready_cancel(pos->th); + pos->th = NULL; + } GNUNET_SERVER_client_drop (pos->client); while (NULL != (pml = pos->pending_head)) { GNUNET_CONTAINER_DLL_remove (pos->pending_head, pos->pending_tail, pml); GNUNET_free (pml); + pos->num_pending--; } + GNUNET_assert (0 == pos->num_pending); GNUNET_free (pos); } - if (nc->server != NULL) + if (NULL != nc->server) GNUNET_SERVER_disconnect_notify_cancel (nc->server, &handle_client_disconnect, nc); GNUNET_free (nc); @@ -262,15 +271,16 @@ GNUNET_SERVER_notification_context_add (struct GNUNET_SERVER_NotificationContext { struct ClientList *cl; - for (cl = nc->clients; NULL != cl; cl = cl->next) + for (cl = nc->clients_head; NULL != cl; cl = cl->next) if (cl->client == client) return; /* already present */ cl = GNUNET_malloc (sizeof (struct ClientList)); - cl->next = nc->clients; + GNUNET_CONTAINER_DLL_insert (nc->clients_head, + nc->clients_tail, + cl); cl->nc = nc; cl->client = client; GNUNET_SERVER_client_keep (client); - nc->clients = cl; } @@ -294,13 +304,11 @@ transmit_message (void *cls, size_t size, void *buf) size_t ret; cl->th = NULL; - if (buf == NULL) + if (NULL == buf) { /* 'cl' should be freed via disconnect notification shortly */ -#if DEBUG_SERVER_NC LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to transmit message from NC queue to client\n"); -#endif return 0; } ret = 0; @@ -310,31 +318,29 @@ transmit_message (void *cls, size_t size, void *buf) if (size < msize) break; GNUNET_CONTAINER_DLL_remove (cl->pending_head, cl->pending_tail, pml); -#if DEBUG_SERVER_NC LOG (GNUNET_ERROR_TYPE_DEBUG, "Copying message of type %u and size %u from pending queue to transmission buffer\n", ntohs (pml->msg->type), msize); -#endif memcpy (&cbuf[ret], pml->msg, msize); ret += msize; size -= msize; GNUNET_free (pml); cl->num_pending--; } - if (pml != NULL) + if (NULL != pml) { -#if DEBUG_SERVER_NC LOG (GNUNET_ERROR_TYPE_DEBUG, "Have %u messages left in NC queue, will try transmission again\n", cl->num_pending); -#endif cl->th = GNUNET_SERVER_notify_transmit_ready (cl->client, ntohs (pml->msg->size), GNUNET_TIME_UNIT_FOREVER_REL, &transmit_message, cl); } else - GNUNET_assert (cl->num_pending == 0); + { + GNUNET_assert (0 == cl->num_pending); + } return ret; } @@ -372,11 +378,9 @@ do_unicast (struct GNUNET_SERVER_NotificationContext *nc, pml = GNUNET_malloc (sizeof (struct PendingMessageList) + size); pml->msg = (const struct GNUNET_MessageHeader *) &pml[1]; pml->can_drop = can_drop; -#if DEBUG_SERVER_NC LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding message of type %u and size %u to pending queue (which has %u entries)\n", ntohs (msg->type), ntohs (msg->size), (unsigned int) nc->queue_length); -#endif memcpy (&pml[1], msg, size); /* append */ GNUNET_CONTAINER_DLL_insert_tail (client->pending_head, client->pending_tail, @@ -410,14 +414,10 @@ GNUNET_SERVER_notification_context_unicast (struct { struct ClientList *pos; - pos = nc->clients; - while (NULL != pos) - { + for (pos = nc->clients_head; NULL != pos; pos = pos->next) if (pos->client == client) break; - pos = pos->next; - } - GNUNET_assert (pos != NULL); + GNUNET_assert (NULL != pos); do_unicast (nc, pos, msg, can_drop); } @@ -438,12 +438,8 @@ GNUNET_SERVER_notification_context_broadcast (struct { struct ClientList *pos; - pos = nc->clients; - while (NULL != pos) - { + for (pos = nc->clients_head; NULL != pos; pos = pos->next) do_unicast (nc, pos, msg, can_drop); - pos = pos->next; - } } |