aboutsummaryrefslogtreecommitdiff
path: root/src/util/server_nc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/server_nc.c')
-rw-r--r--src/util/server_nc.c262
1 files changed, 126 insertions, 136 deletions
diff --git a/src/util/server_nc.c b/src/util/server_nc.c
index 56d79c18e..f8e300029 100644
--- a/src/util/server_nc.c
+++ b/src/util/server_nc.c
@@ -44,12 +44,12 @@ struct PendingMessageList
44 44
45 /** 45 /**
46 * This is a doubly-linked list. 46 * This is a doubly-linked list.
47 */ 47 */
48 struct PendingMessageList *next; 48 struct PendingMessageList *next;
49 49
50 /** 50 /**
51 * This is a doubly-linked list. 51 * This is a doubly-linked list.
52 */ 52 */
53 struct PendingMessageList *prev; 53 struct PendingMessageList *prev;
54 54
55 /** 55 /**
@@ -60,7 +60,7 @@ struct PendingMessageList
60 60
61 /** 61 /**
62 * Can this message be dropped? 62 * Can this message be dropped?
63 */ 63 */
64 int can_drop; 64 int can_drop;
65 65
66}; 66};
@@ -74,7 +74,7 @@ struct ClientList
74 74
75 /** 75 /**
76 * This is a linked list. 76 * This is a linked list.
77 */ 77 */
78 struct ClientList *next; 78 struct ClientList *next;
79 79
80 /** 80 /**
@@ -94,12 +94,12 @@ struct ClientList
94 94
95 /** 95 /**
96 * Head of linked list of requests queued for transmission. 96 * Head of linked list of requests queued for transmission.
97 */ 97 */
98 struct PendingMessageList *pending_head; 98 struct PendingMessageList *pending_head;
99 99
100 /** 100 /**
101 * Tail of linked list of requests queued for transmission. 101 * Tail of linked list of requests queued for transmission.
102 */ 102 */
103 struct PendingMessageList *pending_tail; 103 struct PendingMessageList *pending_tail;
104 104
105 /** 105 /**
@@ -146,8 +146,7 @@ struct GNUNET_SERVER_NotificationContext
146 * @param client handle of client that disconnected 146 * @param client handle of client that disconnected
147 */ 147 */
148static void 148static void
149handle_client_disconnect (void *cls, 149handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
150 struct GNUNET_SERVER_Client *client)
151{ 150{
152 struct GNUNET_SERVER_NotificationContext *nc = cls; 151 struct GNUNET_SERVER_NotificationContext *nc = cls;
153 struct ClientList *pos; 152 struct ClientList *pos;
@@ -155,42 +154,40 @@ handle_client_disconnect (void *cls,
155 struct PendingMessageList *pml; 154 struct PendingMessageList *pml;
156 155
157 if (client == NULL) 156 if (client == NULL)
158 { 157 {
159 nc->server = NULL; 158 nc->server = NULL;
160 return; 159 return;
161 } 160 }
162 prev = NULL; 161 prev = NULL;
163 pos = nc->clients; 162 pos = nc->clients;
164 while (NULL != pos) 163 while (NULL != pos)
165 { 164 {
166 if (pos->client == client) 165 if (pos->client == client)
167 break; 166 break;
168 prev = pos; 167 prev = pos;
169 pos = pos->next; 168 pos = pos->next;
170 } 169 }
171 if (pos == NULL) 170 if (pos == NULL)
172 return; 171 return;
173#if DEBUG_SERVER_NC 172#if DEBUG_SERVER_NC
174 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 173 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
175 "Client disconnected, cleaning up %u messages in NC queue\n", 174 "Client disconnected, cleaning up %u messages in NC queue\n",
176 pos->num_pending); 175 pos->num_pending);
177#endif 176#endif
178 if (prev == NULL) 177 if (prev == NULL)
179 nc->clients = pos->next; 178 nc->clients = pos->next;
180 else 179 else
181 prev->next = pos->next; 180 prev->next = pos->next;
182 while (NULL != (pml = pos->pending_head)) 181 while (NULL != (pml = pos->pending_head))
183 { 182 {
184 GNUNET_CONTAINER_DLL_remove (pos->pending_head, 183 GNUNET_CONTAINER_DLL_remove (pos->pending_head, pos->pending_tail, pml);
185 pos->pending_tail, 184 GNUNET_free (pml);
186 pml); 185 }
187 GNUNET_free (pml);
188 }
189 if (pos->th != NULL) 186 if (pos->th != NULL)
190 { 187 {
191 GNUNET_CONNECTION_notify_transmit_ready_cancel (pos->th); 188 GNUNET_CONNECTION_notify_transmit_ready_cancel (pos->th);
192 pos->th = NULL; 189 pos->th = NULL;
193 } 190 }
194 GNUNET_SERVER_client_drop (client); 191 GNUNET_SERVER_client_drop (client);
195 GNUNET_free (pos); 192 GNUNET_free (pos);
196} 193}
@@ -207,16 +204,14 @@ handle_client_disconnect (void *cls,
207 */ 204 */
208struct GNUNET_SERVER_NotificationContext * 205struct GNUNET_SERVER_NotificationContext *
209GNUNET_SERVER_notification_context_create (struct GNUNET_SERVER_Handle *server, 206GNUNET_SERVER_notification_context_create (struct GNUNET_SERVER_Handle *server,
210 unsigned int queue_length) 207 unsigned int queue_length)
211{ 208{
212 struct GNUNET_SERVER_NotificationContext *ret; 209 struct GNUNET_SERVER_NotificationContext *ret;
213 210
214 ret = GNUNET_malloc (sizeof (struct GNUNET_SERVER_NotificationContext)); 211 ret = GNUNET_malloc (sizeof (struct GNUNET_SERVER_NotificationContext));
215 ret->server = server; 212 ret->server = server;
216 ret->queue_length = queue_length; 213 ret->queue_length = queue_length;
217 GNUNET_SERVER_disconnect_notify (server, 214 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, ret);
218 &handle_client_disconnect,
219 ret);
220 return ret; 215 return ret;
221} 216}
222 217
@@ -227,28 +222,27 @@ GNUNET_SERVER_notification_context_create (struct GNUNET_SERVER_Handle *server,
227 * @param nc context to destroy. 222 * @param nc context to destroy.
228 */ 223 */
229void 224void
230GNUNET_SERVER_notification_context_destroy (struct GNUNET_SERVER_NotificationContext *nc) 225GNUNET_SERVER_notification_context_destroy (struct
226 GNUNET_SERVER_NotificationContext
227 *nc)
231{ 228{
232 struct ClientList *pos; 229 struct ClientList *pos;
233 struct PendingMessageList *pml; 230 struct PendingMessageList *pml;
234 231
235 while (NULL != (pos = nc->clients)) 232 while (NULL != (pos = nc->clients))
233 {
234 nc->clients = pos->next;
235 GNUNET_SERVER_client_drop (pos->client);
236 while (NULL != (pml = pos->pending_head))
236 { 237 {
237 nc->clients = pos->next; 238 GNUNET_CONTAINER_DLL_remove (pos->pending_head, pos->pending_tail, pml);
238 GNUNET_SERVER_client_drop (pos->client); 239 GNUNET_free (pml);
239 while (NULL != (pml = pos->pending_head))
240 {
241 GNUNET_CONTAINER_DLL_remove (pos->pending_head,
242 pos->pending_tail,
243 pml);
244 GNUNET_free (pml);
245 }
246 GNUNET_free (pos);
247 } 240 }
241 GNUNET_free (pos);
242 }
248 if (nc->server != NULL) 243 if (nc->server != NULL)
249 GNUNET_SERVER_disconnect_notify_cancel (nc->server, 244 GNUNET_SERVER_disconnect_notify_cancel (nc->server,
250 &handle_client_disconnect, 245 &handle_client_disconnect, nc);
251 nc);
252 GNUNET_free (nc); 246 GNUNET_free (nc);
253} 247}
254 248
@@ -260,8 +254,9 @@ GNUNET_SERVER_notification_context_destroy (struct GNUNET_SERVER_NotificationCon
260 * @param client client to add 254 * @param client client to add
261 */ 255 */
262void 256void
263GNUNET_SERVER_notification_context_add (struct GNUNET_SERVER_NotificationContext *nc, 257GNUNET_SERVER_notification_context_add (struct GNUNET_SERVER_NotificationContext
264 struct GNUNET_SERVER_Client *client) 258 *nc,
259 struct GNUNET_SERVER_Client *client)
265{ 260{
266 struct ClientList *cl; 261 struct ClientList *cl;
267 262
@@ -285,9 +280,7 @@ GNUNET_SERVER_notification_context_add (struct GNUNET_SERVER_NotificationContext
285 * @return number of bytes written to buf 280 * @return number of bytes written to buf
286 */ 281 */
287static size_t 282static size_t
288transmit_message (void *cls, 283transmit_message (void *cls, size_t size, void *buf)
289 size_t size,
290 void *buf)
291{ 284{
292 struct ClientList *cl = cls; 285 struct ClientList *cl = cls;
293 char *cbuf = buf; 286 char *cbuf = buf;
@@ -297,48 +290,44 @@ transmit_message (void *cls,
297 290
298 cl->th = NULL; 291 cl->th = NULL;
299 if (buf == NULL) 292 if (buf == NULL)
300 { 293 {
301 /* 'cl' should be freed via disconnect notification shortly */ 294 /* 'cl' should be freed via disconnect notification shortly */
302#if DEBUG_SERVER_NC 295#if DEBUG_SERVER_NC
303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 296 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
304 "Failed to transmit message from NC queue to client\n"); 297 "Failed to transmit message from NC queue to client\n");
305#endif 298#endif
306 return 0; 299 return 0;
307 } 300 }
308 ret = 0; 301 ret = 0;
309 while (NULL != (pml = cl->pending_head) ) 302 while (NULL != (pml = cl->pending_head))
310 { 303 {
311 msize = ntohs (pml->msg->size); 304 msize = ntohs (pml->msg->size);
312 if (size < msize) 305 if (size < msize)
313 break; 306 break;
314 GNUNET_CONTAINER_DLL_remove (cl->pending_head, 307 GNUNET_CONTAINER_DLL_remove (cl->pending_head, cl->pending_tail, pml);
315 cl->pending_tail,
316 pml);
317#if DEBUG_SERVER_NC 308#if DEBUG_SERVER_NC
318 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 309 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
319 "Copying message of type %u and size %u from pending queue to transmission buffer\n", 310 "Copying message of type %u and size %u from pending queue to transmission buffer\n",
320 ntohs (pml->msg->type), 311 ntohs (pml->msg->type), msize);
321 msize);
322#endif 312#endif
323 memcpy (&cbuf[ret], pml->msg, msize); 313 memcpy (&cbuf[ret], pml->msg, msize);
324 ret += msize; 314 ret += msize;
325 size -= msize; 315 size -= msize;
326 GNUNET_free (pml); 316 GNUNET_free (pml);
327 cl->num_pending--; 317 cl->num_pending--;
328 } 318 }
329 if (pml != NULL) 319 if (pml != NULL)
330 { 320 {
331#if DEBUG_SERVER_NC 321#if DEBUG_SERVER_NC
332 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 322 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
333 "Have %u messages left in NC queue, will try transmission again\n", 323 "Have %u messages left in NC queue, will try transmission again\n",
334 cl->num_pending); 324 cl->num_pending);
335#endif 325#endif
336 cl->th = GNUNET_SERVER_notify_transmit_ready (cl->client, 326 cl->th = GNUNET_SERVER_notify_transmit_ready (cl->client,
337 ntohs (pml->msg->size), 327 ntohs (pml->msg->size),
338 GNUNET_TIME_UNIT_FOREVER_REL, 328 GNUNET_TIME_UNIT_FOREVER_REL,
339 &transmit_message, 329 &transmit_message, cl);
340 cl); 330 }
341 }
342 else 331 else
343 GNUNET_assert (cl->num_pending == 0); 332 GNUNET_assert (cl->num_pending == 0);
344 return ret; 333 return ret;
@@ -355,52 +344,49 @@ transmit_message (void *cls,
355 */ 344 */
356static void 345static void
357do_unicast (struct GNUNET_SERVER_NotificationContext *nc, 346do_unicast (struct GNUNET_SERVER_NotificationContext *nc,
358 struct ClientList *client, 347 struct ClientList *client,
359 const struct GNUNET_MessageHeader *msg, 348 const struct GNUNET_MessageHeader *msg, int can_drop)
360 int can_drop)
361{ 349{
362 struct PendingMessageList *pml; 350 struct PendingMessageList *pml;
363 uint16_t size; 351 uint16_t size;
364 352
365 if ( (client->num_pending > nc->queue_length) && 353 if ((client->num_pending > nc->queue_length) && (GNUNET_YES == can_drop))
366 (GNUNET_YES == can_drop) ) 354 {
367 { 355 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
368 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 356 "Dropping message of type %u and size %u due to full queue (%u entries)\n",
369 "Dropping message of type %u and size %u due to full queue (%u entries)\n", 357 ntohs (msg->type),
370 ntohs (msg->type), 358 ntohs (msg->size), (unsigned int) nc->queue_length);
371 ntohs (msg->size), 359 return; /* drop! */
372 (unsigned int) nc->queue_length); 360 }
373 return; /* drop! */
374 }
375 if (client->num_pending > nc->queue_length) 361 if (client->num_pending > nc->queue_length)
376 { 362 {
377 /* FIXME: consider checking for other messages in the 363 /* FIXME: consider checking for other messages in the
378 queue that are 'droppable' */ 364 * queue that are 'droppable' */
379 } 365 }
380 client->num_pending++; 366 client->num_pending++;
381 size = ntohs (msg->size); 367 size = ntohs (msg->size);
382 pml = GNUNET_malloc (sizeof (struct PendingMessageList) + size); 368 pml = GNUNET_malloc (sizeof (struct PendingMessageList) + size);
383 pml->msg = (const struct GNUNET_MessageHeader*) &pml[1]; 369 pml->msg = (const struct GNUNET_MessageHeader *) &pml[1];
384 pml->can_drop = can_drop; 370 pml->can_drop = can_drop;
385#if DEBUG_SERVER_NC 371#if DEBUG_SERVER_NC
386 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 372 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
387 "Adding message of type %u and size %u to pending queue (which has %u entries)\n", 373 "Adding message of type %u and size %u to pending queue (which has %u entries)\n",
388 ntohs (msg->type), 374 ntohs (msg->type),
389 ntohs (msg->size), 375 ntohs (msg->size), (unsigned int) nc->queue_length);
390 (unsigned int) nc->queue_length);
391#endif 376#endif
392 memcpy (&pml[1], msg, size); 377 memcpy (&pml[1], msg, size);
393 /* append */ 378 /* append */
394 GNUNET_CONTAINER_DLL_insert_tail (client->pending_head, 379 GNUNET_CONTAINER_DLL_insert_tail (client->pending_head,
395 client->pending_tail, 380 client->pending_tail, pml);
396 pml);
397 if (client->th == NULL) 381 if (client->th == NULL)
398 client->th = GNUNET_SERVER_notify_transmit_ready (client->client, 382 client->th = GNUNET_SERVER_notify_transmit_ready (client->client,
399 ntohs (client->pending_head->msg->size), 383 ntohs
400 GNUNET_TIME_UNIT_FOREVER_REL, 384 (client->pending_head->
401 &transmit_message, 385 msg->size),
402 client); 386 GNUNET_TIME_UNIT_FOREVER_REL,
403} 387 &transmit_message,
388 client);
389}
404 390
405 391
406/** 392/**
@@ -413,22 +399,24 @@ do_unicast (struct GNUNET_SERVER_NotificationContext *nc,
413 * @param can_drop can this message be dropped due to queue length limitations 399 * @param can_drop can this message be dropped due to queue length limitations
414 */ 400 */
415void 401void
416GNUNET_SERVER_notification_context_unicast (struct GNUNET_SERVER_NotificationContext *nc, 402GNUNET_SERVER_notification_context_unicast (struct
417 struct GNUNET_SERVER_Client *client, 403 GNUNET_SERVER_NotificationContext
418 const struct GNUNET_MessageHeader *msg, 404 *nc,
419 int can_drop) 405 struct GNUNET_SERVER_Client *client,
406 const struct GNUNET_MessageHeader
407 *msg, int can_drop)
420{ 408{
421 struct ClientList *pos; 409 struct ClientList *pos;
422 410
423 pos = nc->clients; 411 pos = nc->clients;
424 while (NULL != pos) 412 while (NULL != pos)
425 { 413 {
426 if (pos->client == client) 414 if (pos->client == client)
427 break; 415 break;
428 pos = pos->next; 416 pos = pos->next;
429 } 417 }
430 GNUNET_assert (pos != NULL); 418 GNUNET_assert (pos != NULL);
431 do_unicast (nc, pos, msg, can_drop); 419 do_unicast (nc, pos, msg, can_drop);
432} 420}
433 421
434 422
@@ -440,18 +428,20 @@ GNUNET_SERVER_notification_context_unicast (struct GNUNET_SERVER_NotificationCon
440 * @param can_drop can this message be dropped due to queue length limitations 428 * @param can_drop can this message be dropped due to queue length limitations
441 */ 429 */
442void 430void
443GNUNET_SERVER_notification_context_broadcast (struct GNUNET_SERVER_NotificationContext *nc, 431GNUNET_SERVER_notification_context_broadcast (struct
444 const struct GNUNET_MessageHeader *msg, 432 GNUNET_SERVER_NotificationContext
445 int can_drop) 433 *nc,
434 const struct GNUNET_MessageHeader
435 *msg, int can_drop)
446{ 436{
447 struct ClientList *pos; 437 struct ClientList *pos;
448 438
449 pos = nc->clients; 439 pos = nc->clients;
450 while (NULL != pos) 440 while (NULL != pos)
451 { 441 {
452 do_unicast (nc, pos, msg, can_drop); 442 do_unicast (nc, pos, msg, can_drop);
453 pos = pos->next; 443 pos = pos->next;
454 } 444 }
455} 445}
456 446
457 447