GNUnet  0.10.x
tcp_server_legacy.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2009-2013 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_protocols.h"
30 
31 #define LOG_STRERROR_FILE(kind, syscall, filename) GNUNET_log_from_strerror_file(kind, "util-server", syscall, filename)
32 
33 
37 struct HandlerList {
41  struct HandlerList *next;
42 
47 };
48 
49 
53 struct NotifyList {
57  struct NotifyList *next;
58 
62  struct NotifyList *prev;
63 
68 
72  void *callback_cls;
73 };
74 
75 
84 
89 
94 
99 
104 
109 
114 
119 
124 
130 
135  struct GNUNET_TIME_Relative idle_timeout;
136 
141 
146 
151 
156 
160  void *mst_cls;
161 
167 
176 };
177 
178 
187 
192 
197 };
198 
199 
208 
213 
217  void *mst;
218 
223 
228 
234 
239 
244 
248  struct GNUNET_TIME_Absolute warn_start;
249 
254  struct GNUNET_TIME_Absolute last_activity;
255 
261 
266  struct GNUNET_TIME_Relative idle_timeout;
267 
272  unsigned int reference_count;
273 
280  unsigned int suspended;
281 
287 
297 
302 
309 
315  int persist;
316 
323 
327  uint16_t warn_type;
328 };
329 
330 
331 
340 void *
342  size_t size)
343 {
344  if ((0 == client->user_context_size) &&
345  (NULL == client->user_context))
346  return NULL; /* never set */
347  GNUNET_assert(size == client->user_context_size);
348  return client->user_context;
349 }
350 
351 
360 void
362  void *ptr,
363  size_t size)
364 {
365  if (NULL == ptr)
366  {
367  client->user_context_size = 0;
368  client->user_context = ptr;
369  return;
370  }
371  client->user_context_size = size;
372  client->user_context = ptr;
373 }
374 
375 
382 static void
384 {
385  struct GNUNET_SERVER_Handle *server = cls;
386  const struct GNUNET_SCHEDULER_TaskContext *tc;
388  unsigned int i;
389 
390  server->listen_task = NULL;
392  for (i = 0; NULL != server->listen_sockets[i]; i++)
393  {
395  server->listen_sockets[i]))
396  {
397  sock =
399  server->access_cb_cls,
400  server->listen_sockets[i]);
401  if (NULL != sock)
402  {
404  "Server accepted incoming connection.\n");
405  (void)GNUNET_SERVER_connect_socket(server,
406  sock);
407  }
408  }
409  }
410  /* listen for more! */
411  GNUNET_SERVER_resume(server);
412 }
413 
414 
422 static struct GNUNET_NETWORK_Handle *
423 open_listen_socket(const struct sockaddr *server_addr,
424  socklen_t socklen)
425 {
426  struct GNUNET_NETWORK_Handle *sock;
427  uint16_t port;
428  int eno;
429 
430  switch (server_addr->sa_family)
431  {
432  case AF_INET:
433  port = ntohs(((const struct sockaddr_in *)server_addr)->sin_port);
434  break;
435 
436  case AF_INET6:
437  port = ntohs(((const struct sockaddr_in6 *)server_addr)->sin6_port);
438  break;
439 
440  case AF_UNIX:
441  port = 0;
442  break;
443 
444  default:
445  GNUNET_break(0);
446  port = 0;
447  break;
448  }
449  sock = GNUNET_NETWORK_socket_create(server_addr->sa_family, SOCK_STREAM, 0);
450  if (NULL == sock)
451  {
453  errno = 0;
454  return NULL;
455  }
456  /* bind the socket */
457  if (GNUNET_OK != GNUNET_NETWORK_socket_bind(sock, server_addr, socklen))
458  {
459  eno = errno;
460  if (EADDRINUSE != errno)
461  {
462  /* we don't log 'EADDRINUSE' here since an IPv4 bind may
463  * fail if we already took the port on IPv6; if both IPv4 and
464  * IPv6 binds fail, then our caller will log using the
465  * errno preserved in 'eno' */
467  "bind");
468  if (0 != port)
470  _("`%s' failed for port %d (%s).\n"),
471  "bind",
472  port,
473  (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
474  eno = 0;
475  }
476  else
477  {
478  if (0 != port)
480  _("`%s' failed for port %d (%s): address already in use\n"),
481  "bind", port,
482  (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
483  else if (AF_UNIX == server_addr->sa_family)
484  {
486  _("`%s' failed for `%s': address already in use\n"),
487  "bind",
488  GNUNET_a2s(server_addr, socklen));
489  }
490  }
492  errno = eno;
493  return NULL;
494  }
495  if (GNUNET_OK != GNUNET_NETWORK_socket_listen(sock, 5))
496  {
498  "listen");
500  errno = 0;
501  return NULL;
502  }
503  if (0 != port)
505  "Server starts to listen on port %u.\n",
506  port);
507  return sock;
508 }
509 
510 
523 struct GNUNET_SERVER_Handle *
525  void *access_cb_cls,
526  struct GNUNET_NETWORK_Handle **lsocks,
528  int require_found)
529 {
530  struct GNUNET_SERVER_Handle *server;
531 
532  server = GNUNET_new(struct GNUNET_SERVER_Handle);
533  server->idle_timeout = idle_timeout;
534  server->listen_sockets = lsocks;
535  server->access_cb = access_cb;
536  server->access_cb_cls = access_cb_cls;
537  server->require_found = require_found;
538  if (NULL != lsocks)
539  GNUNET_SERVER_resume(server);
540  return server;
541 }
542 
543 
557 struct GNUNET_SERVER_Handle *
559  void *access_cb_cls,
560  struct sockaddr *const *server_addr,
561  const socklen_t * socklen,
563  int require_found)
564 {
565  struct GNUNET_NETWORK_Handle **lsocks;
566  unsigned int i;
567  unsigned int j;
568  unsigned int k;
569  int seen;
570 
571  i = 0;
572  while (NULL != server_addr[i])
573  i++;
574  if (i > 0)
575  {
576  lsocks = GNUNET_malloc(sizeof(struct GNUNET_NETWORK_Handle *) * (i + 1));
577  i = 0;
578  j = 0;
579  while (NULL != server_addr[i])
580  {
581  seen = 0;
582  for (k = 0; k < i; k++)
583  if ((socklen[k] == socklen[i]) &&
584  (0 == memcmp(server_addr[k], server_addr[i], socklen[i])))
585  {
586  seen = 1;
587  break;
588  }
589  if (0 != seen)
590  {
591  /* duplicate address, skip */
592  i++;
593  continue;
594  }
595  lsocks[j] = open_listen_socket(server_addr[i], socklen[i]);
596  if (NULL != lsocks[j])
597  j++;
598  i++;
599  }
600  if (0 == j)
601  {
602  if (0 != errno)
604  GNUNET_free(lsocks);
605  lsocks = NULL;
606  }
607  }
608  else
609  {
610  lsocks = NULL;
611  }
612  return GNUNET_SERVER_create_with_sockets(access_cb,
613  access_cb_cls,
614  lsocks,
615  idle_timeout,
616  require_found);
617 }
618 
619 
632 void
634 {
636  "Marking client as monitor!\n");
637  client->is_monitor = GNUNET_YES;
638 }
639 
640 
647 static void
648 do_destroy(void *cls)
649 {
650  struct GNUNET_SERVER_Handle *server = cls;
651 
652  GNUNET_SERVER_destroy(server);
653 }
654 
655 
662 static void
664 {
665  struct GNUNET_SERVER_Client *client;
666 
667  if (GNUNET_YES != server->in_soft_shutdown)
668  return;
669  for (client = server->clients_head; NULL != client; client = client->next)
670  if (GNUNET_NO == client->is_monitor)
671  return;
672  /* not done yet */
674  (void)GNUNET_SCHEDULER_add_now(&do_destroy, server);
675 }
676 
677 
683 void
685 {
686  if (NULL != server->listen_task)
687  {
689  server->listen_task = NULL;
690  }
691 }
692 
693 
699 void
701 {
702  struct GNUNET_NETWORK_FDSet *r;
703  unsigned int i;
704 
705  if (NULL == server->listen_sockets)
706  return;
707  if (NULL == server->listen_sockets[0])
708  return; /* nothing to do, no listen sockets! */
709  if (NULL == server->listen_sockets[1])
710  {
711  /* simplified method: no fd set needed; this is then much simpler
712  and much more efficient */
713  server->listen_task =
716  server->listen_sockets[0],
717  &process_listen_socket, server);
718  return;
719  }
721  i = 0;
722  while (NULL != server->listen_sockets[i])
723  GNUNET_NETWORK_fdset_set(r, server->listen_sockets[i++]);
724  server->listen_task =
727  &process_listen_socket, server);
729 }
730 
731 
738 void
740 {
741  unsigned int i;
742 
744  "Server in soft shutdown\n");
745  if (NULL != server->listen_task)
746  {
748  server->listen_task = NULL;
749  }
750  if (NULL != server->listen_sockets)
751  {
752  i = 0;
753  while (NULL != server->listen_sockets[i])
756  GNUNET_free(server->listen_sockets);
757  server->listen_sockets = NULL;
758  }
759  if (GNUNET_NO == server->in_soft_shutdown)
760  server->in_soft_shutdown = GNUNET_YES;
761  test_monitor_clients(server);
762 }
763 
764 
770 void
772 {
773  struct HandlerList *hpos;
774  struct NotifyList *npos;
775  unsigned int i;
776 
778  "Server shutting down.\n");
779  if (NULL != server->listen_task)
780  {
782  server->listen_task = NULL;
783  }
784  if (NULL != server->listen_sockets)
785  {
786  i = 0;
787  while (NULL != server->listen_sockets[i])
790  GNUNET_free(server->listen_sockets);
791  server->listen_sockets = NULL;
792  }
793  while (NULL != server->clients_head)
795  while (NULL != (hpos = server->handlers))
796  {
797  server->handlers = hpos->next;
798  GNUNET_free(hpos);
799  }
800  while (NULL != (npos = server->disconnect_notify_list_head))
801  {
802  npos->callback(npos->callback_cls,
803  NULL);
806  npos);
807  GNUNET_free(npos);
808  }
809  while (NULL != (npos = server->connect_notify_list_head))
810  {
811  npos->callback(npos->callback_cls,
812  NULL);
814  server->connect_notify_list_tail,
815  npos);
816  GNUNET_free(npos);
817  }
818  GNUNET_free(server);
819 }
820 
821 
835 void
838 {
839  struct HandlerList *p;
840 
841  p = GNUNET_new(struct HandlerList);
842  p->handlers = handlers;
843  p->next = server->handlers;
844  server->handlers = p;
845 }
846 
847 
858 void
863  void *cls)
864 {
865  server->mst_create = create;
866  server->mst_destroy = destroy;
867  server->mst_receive = receive;
868  server->mst_cls = cls;
869 }
870 
871 
877 static void
879 {
880  struct GNUNET_SERVER_Client *client = cls;
881 
882  GNUNET_break(0 != client->warn_type); /* type should never be 0 here, as we don't use 0 */
883  client->warn_task =
885  &warn_no_receive_done, client);
887  _("Processing code for message of type %u did not call `GNUNET_SERVER_receive_done' after %s\n"),
888  (unsigned int)client->warn_type,
890  GNUNET_YES));
891 }
892 
893 
901 void
903 {
904  if (NULL != client->warn_task)
905  {
907  client->warn_task = NULL;
908  }
909 }
910 
911 
927 int
929  struct GNUNET_SERVER_Client *sender,
930  const struct GNUNET_MessageHeader *message)
931 {
932  struct HandlerList *pos;
933  const struct GNUNET_SERVER_MessageHandler *mh;
934  unsigned int i;
935  uint16_t type;
936  uint16_t size;
937  int found;
938 
939  type = ntohs(message->type);
940  size = ntohs(message->size);
942  "Received message of type %u and size %u from client\n",
943  type, size);
944  found = GNUNET_NO;
945  for (pos = server->handlers; NULL != pos; pos = pos->next)
946  {
947  i = 0;
948  while (pos->handlers[i].callback != NULL)
949  {
950  mh = &pos->handlers[i];
951  if ((mh->type == type) || (mh->type == GNUNET_MESSAGE_TYPE_ALL))
952  {
953  if ((0 != mh->expected_size) && (mh->expected_size != size))
954  {
955 #if GNUNET8_NETWORK_IS_DEAD
957  "Expected %u bytes for message of type %u, got %u\n",
958  mh->expected_size, mh->type, size);
959  GNUNET_break_op(0);
960 #else
962  "Expected %u bytes for message of type %u, got %u\n",
963  mh->expected_size, mh->type, size);
964 #endif
965  return GNUNET_SYSERR;
966  }
967  if (NULL != sender)
968  {
969  if ((0 == sender->suspended) &&
970  (NULL == sender->warn_task))
971  {
972  GNUNET_break(0 != type); /* type should never be 0 here, as we don't use 0 */
974  sender->warn_task =
977  sender);
978  sender->warn_type = type;
979  }
980  sender->suspended++;
981  }
982  mh->callback(mh->callback_cls, sender, message);
983  found = GNUNET_YES;
984  }
985  i++;
986  }
987  }
988  if (GNUNET_NO == found)
989  {
991  "Received message of unknown type %d\n", type);
992  if (GNUNET_YES == server->require_found)
993  return GNUNET_SYSERR;
994  }
995  return GNUNET_OK;
996 }
997 
998 
1009 static void
1010 process_incoming(void *cls,
1011  const void *buf,
1012  size_t available,
1013  const struct sockaddr *addr,
1014  socklen_t addrlen,
1015  int errCode);
1016 
1017 
1031 static void
1033  int ret)
1034 {
1035  while ((GNUNET_SYSERR != ret) && (NULL != client->server) &&
1036  (GNUNET_YES != client->shutdown_now) && (0 == client->suspended))
1037  {
1038  if (GNUNET_OK == ret)
1039  {
1041  "Server re-enters receive loop, timeout: %s.\n",
1043  client->receive_pending = GNUNET_YES;
1044  if (GNUNET_OK !=
1047  client->idle_timeout,
1049  client))
1050  return;
1051  break;
1052  }
1054  "Server processes additional messages instantly.\n");
1055  if (NULL != client->server->mst_receive)
1056  ret =
1057  client->server->mst_receive(client->server->mst_cls, client->mst,
1058  client, NULL, 0, GNUNET_NO, GNUNET_YES);
1059  else
1060  ret =
1061  GNUNET_SERVER_mst_receive(client->mst, client, NULL, 0, GNUNET_NO,
1062  GNUNET_YES);
1063  }
1065  "Server leaves instant processing loop: ret = %d, server = %p, shutdown = %d, suspended = %u\n",
1066  ret, client->server,
1067  client->shutdown_now,
1068  client->suspended);
1069  if (GNUNET_NO == ret)
1070  {
1072  "Server has more data pending but is suspended.\n");
1073  client->receive_pending = GNUNET_SYSERR; /* data pending */
1074  }
1075  if ((GNUNET_SYSERR == ret) ||
1076  (GNUNET_YES == client->shutdown_now))
1078 }
1079 
1080 
1091 static void
1093  const void *buf,
1094  size_t available,
1095  const struct sockaddr *addr,
1096  socklen_t addrlen,
1097  int errCode)
1098 {
1099  struct GNUNET_SERVER_Client *client = cls;
1100  struct GNUNET_SERVER_Handle *server = client->server;
1101  struct GNUNET_TIME_Absolute end;
1102  struct GNUNET_TIME_Absolute now;
1103  int ret;
1104 
1106  client->receive_pending = GNUNET_NO;
1107  now = GNUNET_TIME_absolute_get();
1109  client->idle_timeout);
1110 
1111  if ((NULL == buf) &&
1112  (0 == available) &&
1113  (NULL == addr) &&
1114  (0 == errCode) &&
1115  (GNUNET_YES != client->shutdown_now) &&
1116  (NULL != server) &&
1118  (end.abs_value_us > now.abs_value_us))
1119  {
1120  /* wait longer, timeout changed (i.e. due to us sending) */
1122  "Receive time out, but no disconnect due to sending (%p)\n",
1123  client);
1124  client->receive_pending = GNUNET_YES;
1129  client);
1130  return;
1131  }
1132  if ((NULL == buf) ||
1133  (0 == available) ||
1134  (0 != errCode) ||
1135  (NULL == server) ||
1136  (GNUNET_YES == client->shutdown_now) ||
1138  {
1139  /* other side closed connection, error connecting, etc. */
1141  "Failed to connect or other side closed connection (%p)\n",
1142  client);
1144  return;
1145  }
1147  "Server receives %u bytes from `%s'.\n",
1148  (unsigned int)available,
1149  GNUNET_a2s(addr, addrlen));
1150  GNUNET_SERVER_client_keep(client);
1151  client->last_activity = now;
1152 
1153  if (NULL != server->mst_receive)
1154  {
1155  ret = client->server->mst_receive(client->server->mst_cls,
1156  client->mst,
1157  client,
1158  buf,
1159  available,
1160  GNUNET_NO,
1161  GNUNET_YES);
1162  }
1163  else if (NULL != client->mst)
1164  {
1165  ret =
1167  client,
1168  buf,
1169  available,
1170  GNUNET_NO,
1171  GNUNET_YES);
1172  }
1173  else
1174  {
1175  GNUNET_break(0);
1176  return;
1177  }
1178  process_mst(client,
1179  ret);
1180  GNUNET_SERVER_client_drop(client);
1181 }
1182 
1183 
1190 static void
1192 {
1193  struct GNUNET_SERVER_Client *client = cls;
1194 
1196  client->restart_task = NULL;
1197  if (GNUNET_NO == client->receive_pending)
1198  {
1199  LOG(GNUNET_ERROR_TYPE_DEBUG, "Server begins to read again from client.\n");
1200  client->receive_pending = GNUNET_YES;
1203  client->idle_timeout,
1205  client);
1206  return;
1207  }
1209  "Server continues processing messages still in the buffer.\n");
1210  GNUNET_SERVER_client_keep(client);
1211  client->receive_pending = GNUNET_NO;
1212  process_mst(client,
1213  GNUNET_NO);
1214  GNUNET_SERVER_client_drop(client);
1215 }
1216 
1217 
1228 static int
1230  void *client,
1231  const struct GNUNET_MessageHeader *message)
1232 {
1233  struct GNUNET_SERVER_Handle *server = cls;
1234  struct GNUNET_SERVER_Client *sender = client;
1235  int ret;
1236 
1238  "Tokenizer gives server message of type %u and size %u from client\n",
1239  ntohs(message->type), ntohs(message->size));
1241  ret = GNUNET_SERVER_inject(server, sender, message);
1243  if ((GNUNET_OK != ret) || (GNUNET_YES == sender->shutdown_now))
1244  {
1246  return GNUNET_SYSERR;
1247  }
1248  return GNUNET_OK;
1249 }
1250 
1251 
1263 struct GNUNET_SERVER_Client *
1266 {
1267  struct GNUNET_SERVER_Client *client;
1268  struct NotifyList *n;
1269 
1270  client = GNUNET_new(struct GNUNET_SERVER_Client);
1271  client->connection = connection;
1272  client->server = server;
1274  client->idle_timeout = server->idle_timeout;
1276  server->clients_tail,
1277  client);
1278  if (NULL != server->mst_create)
1279  client->mst =
1280  server->mst_create(server->mst_cls, client);
1281  else
1282  client->mst =
1284  server);
1285  GNUNET_assert(NULL != client->mst);
1286  for (n = server->connect_notify_list_head; NULL != n; n = n->next)
1287  n->callback(n->callback_cls, client);
1288  client->receive_pending = GNUNET_YES;
1289  if (GNUNET_SYSERR ==
1292  client->idle_timeout,
1294  client))
1295  return NULL;
1296  return client;
1297 }
1298 
1299 
1308 void
1311 {
1312  client->idle_timeout = timeout;
1313 }
1314 
1315 
1323 void
1325 {
1326  client->reference_count++;
1327 }
1328 
1329 
1338 void
1340 {
1341  GNUNET_assert(client->reference_count > 0);
1342  client->reference_count--;
1343  if ((GNUNET_YES == client->shutdown_now) && (0 == client->reference_count))
1345 }
1346 
1347 
1356 int
1358  void **addr, size_t * addrlen)
1359 {
1360  return GNUNET_CONNECTION_get_address(client->connection, addr, addrlen);
1361 }
1362 
1363 
1374 void
1377  void *callback_cls)
1378 {
1379  struct NotifyList *n;
1380 
1381  n = GNUNET_new(struct NotifyList);
1382  n->callback = callback;
1386  n);
1387 }
1388 
1389 
1403 void
1406  void *callback_cls)
1407 {
1408  struct NotifyList *n;
1409  struct GNUNET_SERVER_Client *client;
1410 
1411  n = GNUNET_new(struct NotifyList);
1412  n->callback = callback;
1413  n->callback_cls = callback_cls;
1415  server->connect_notify_list_tail,
1416  n);
1417  for (client = server->clients_head; NULL != client; client = client->next)
1418  callback(callback_cls, client);
1419 }
1420 
1421 
1429 void
1432  void *callback_cls)
1433 {
1434  struct NotifyList *pos;
1435 
1436  for (pos = server->disconnect_notify_list_head; NULL != pos; pos = pos->next)
1437  if ((pos->callback == callback) && (pos->callback_cls == callback_cls))
1438  break;
1439  if (NULL == pos)
1440  {
1441  GNUNET_break(0);
1442  return;
1443  }
1446  pos);
1447  GNUNET_free(pos);
1448 }
1449 
1450 
1458 void
1461  void *callback_cls)
1462 {
1463  struct NotifyList *pos;
1464 
1465  for (pos = server->connect_notify_list_head; NULL != pos; pos = pos->next)
1466  if ((pos->callback == callback) && (pos->callback_cls == callback_cls))
1467  break;
1468  if (NULL == pos)
1469  {
1470  GNUNET_break(0);
1471  return;
1472  }
1474  server->connect_notify_list_tail,
1475  pos);
1476  GNUNET_free(pos);
1477 }
1478 
1479 
1488 void
1490 {
1491  struct GNUNET_SERVER_Handle *server = client->server;
1492  struct NotifyList *n;
1493 
1495  "Client is being disconnected from the server.\n");
1496  if (NULL != client->restart_task)
1497  {
1499  client->restart_task = NULL;
1500  }
1501  if (NULL != client->warn_task)
1502  {
1504  client->warn_task = NULL;
1505  }
1506  if (GNUNET_YES == client->receive_pending)
1507  {
1509  client->receive_pending = GNUNET_NO;
1510  }
1511  client->shutdown_now = GNUNET_YES;
1512  client->reference_count++; /* make sure nobody else clean up client... */
1513  if ((NULL != client->mst) &&
1514  (NULL != server))
1515  {
1517  server->clients_tail,
1518  client);
1519  if (NULL != server->mst_destroy)
1520  server->mst_destroy(server->mst_cls,
1521  client->mst);
1522  else
1523  GNUNET_SERVER_mst_destroy(client->mst);
1524  client->mst = NULL;
1525  for (n = server->disconnect_notify_list_head; NULL != n; n = n->next)
1526  n->callback(n->callback_cls,
1527  client);
1528  }
1529  client->reference_count--;
1530  if (client->reference_count > 0)
1531  {
1533  "RC of %p still positive, not destroying everything.\n",
1534  client);
1535  client->server = NULL;
1536  return;
1537  }
1538  if (GNUNET_YES == client->in_process_client_buffer)
1539  {
1541  "Still processing inputs of %p, not destroying everything.\n",
1542  client);
1543  return;
1544  }
1546  "RC of %p now zero, destroying everything.\n",
1547  client);
1548  if (GNUNET_YES == client->persist)
1550  if (NULL != client->th.cth)
1553  /* need to cancel again, as it might have been re-added
1554  in the meantime (i.e. during callbacks) */
1555  if (NULL != client->warn_task)
1556  {
1558  client->warn_task = NULL;
1559  }
1560  if (GNUNET_YES == client->receive_pending)
1561  {
1563  client->receive_pending = GNUNET_NO;
1564  }
1565  GNUNET_free(client);
1566  /* we might be in soft-shutdown, test if we're done */
1567  if (NULL != server)
1568  test_monitor_clients(server);
1569 }
1570 
1571 
1580 int
1582 {
1584 }
1585 
1586 
1596 static size_t
1597 transmit_ready_callback_wrapper(void *cls, size_t size, void *buf)
1598 {
1599  struct GNUNET_SERVER_Client *client = cls;
1601 
1602  client->th.cth = NULL;
1603  callback = client->th.callback;
1604  client->th.callback = NULL;
1606  return callback(client->th.callback_cls, size, buf);
1607 }
1608 
1609 
1627  size_t size,
1630  void *callback_cls)
1631 {
1632  if (NULL != client->th.callback)
1633  return NULL;
1634  client->th.callback_cls = callback_cls;
1635  client->th.callback = callback;
1636  client->th.cth = GNUNET_CONNECTION_notify_transmit_ready(client->connection, size,
1637  timeout,
1639  client);
1640  return &client->th;
1641 }
1642 
1643 
1649 void
1651 {
1653  th->cth = NULL;
1654  th->callback = NULL;
1655 }
1656 
1657 
1664 void
1666 {
1667  client->persist = GNUNET_YES;
1668 }
1669 
1670 
1683 void
1685  int success)
1686 {
1687  if (NULL == client)
1688  return;
1689  GNUNET_assert(client->suspended > 0);
1690  client->suspended--;
1691  if (GNUNET_OK != success)
1692  {
1694  "GNUNET_SERVER_receive_done called with failure indication\n");
1695  if ((client->reference_count > 0) || (client->suspended > 0))
1696  client->shutdown_now = GNUNET_YES;
1697  else
1699  return;
1700  }
1701  if (client->suspended > 0)
1702  {
1704  "GNUNET_SERVER_receive_done called, but more clients pending\n");
1705  return;
1706  }
1707  if (NULL != client->warn_task)
1708  {
1710  client->warn_task = NULL;
1711  }
1712  if (GNUNET_YES == client->in_process_client_buffer)
1713  {
1715  "GNUNET_SERVER_receive_done called while still in processing loop\n");
1716  return;
1717  }
1718  if ((NULL == client->server) || (GNUNET_YES == client->shutdown_now))
1719  {
1721  return;
1722  }
1724  "GNUNET_SERVER_receive_done causes restart in reading from the socket\n");
1725  GNUNET_assert(NULL == client->restart_task);
1727  client);
1728 }
1729 
1730 
1731 /* end of server.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
int GNUNET_NETWORK_socket_listen(const struct GNUNET_NETWORK_Handle *desc, int backlog)
Listen on a socket.
Definition: network.c:696
void GNUNET_SERVER_destroy(struct GNUNET_SERVER_Handle *server)
Free resources held by this server.
Handle server returns for aborting transmission to a client.
const struct GNUNET_SCHEDULER_TaskContext * GNUNET_SCHEDULER_get_task_context(void)
Obtain the reasoning why the current task was started.
Definition: scheduler.c:737
struct GNUNET_NETWORK_Handle * sock
Underlying OS&#39;s socket, set to NULL after fatal errors.
void GNUNET_SERVER_add_handlers(struct GNUNET_SERVER_Handle *server, const struct GNUNET_SERVER_MessageHandler *handlers)
Add additional handlers to an existing server.
void * access_cb_cls
Closure for access_cb.
int(* GNUNET_SERVER_MstReceiveCallback)(void *cls, void *mst, struct GNUNET_SERVER_Client *client, const char *buf, size_t size, int purge, int one_shot)
Signature of a function to receive data for a custom tokenizer.
Run with high priority (important requests).
void GNUNET_CONNECTION_persist_(struct GNUNET_CONNECTION_Handle *connection)
Set the persist option on this connection handle.
List of arrays of message handlers.
void * GNUNET_SERVER_client_get_user_context_(struct GNUNET_SERVER_Client *client, size_t size)
Return user context associated with the given client.
int in_process_client_buffer
Are we currently in the "process_client_buffer" function (and will hence restart the receive job on e...
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_SERVER_client_keep(struct GNUNET_SERVER_Client *client)
Notify the server that the given client handle should be kept (keeps the connection up if possible...
struct NotifyList * connect_notify_list_head
Head of linked list of functions to call on connects by clients.
static struct GNUNET_NETWORK_Handle * open_listen_socket(const struct sockaddr *server_addr, socklen_t socklen)
Create and initialize a listen socket for the server.
GNUNET_SERVER_MessageCallback callback
Function to call for messages of "type".
List of arrays of message handlers.
struct GNUNET_SERVER_Client * clients_tail
Head of list of our current clients.
Context information passed to each scheduler task.
#define GNUNET_TIME_UNIT_MINUTES
One minute.
struct GNUNET_NETWORK_Handle ** listen_sockets
NULL-terminated array of sockets used to listen for new connections.
#define LOG(kind,...)
Definition: arm_api.c:33
GNUNET_SERVER_MstReceiveCallback mst_receive
Alternative function to give data to a MST instance.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static struct GNUNET_CADET_Handle * mh
Cadet handle.
Definition: gnunet-cadet.c:92
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:410
struct GNUNET_TIME_Absolute last_activity
Last activity on this socket (used to time it out if reference_count == 0).
static void warn_no_receive_done(void *cls)
Task run to warn about missing calls to GNUNET_SERVER_receive_done.
int GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition: network.c:474
struct GNUNET_SERVER_Handle * GNUNET_SERVER_create(GNUNET_CONNECTION_AccessCheck access_cb, void *access_cb_cls, struct sockaddr *const *server_addr, const socklen_t *socklen, struct GNUNET_TIME_Relative idle_timeout, int require_found)
Create a new server.
GNUNET_SERVER_MstDestroyCallback mst_destroy
Alternative function to destroy a MST instance.
void * user_context
User context value, manipulated using &#39;GNUNET_SERVER_client_{get/set}_user_context&#39; functions...
GNUNET_SERVER_DisconnectCallback callback
Function to call.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
void * GNUNET_CONNECTION_receive_cancel(struct GNUNET_CONNECTION_Handle *connection)
Cancel receive job on the given connection.
const struct GNUNET_NETWORK_FDSet * read_ready
Set of file descriptors ready for reading; note that additional bits may be set that were not in the ...
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Add a given relative duration to the given start time.
Definition: time.c:393
void GNUNET_SERVER_mst_destroy(struct GNUNET_SERVER_MessageStreamTokenizer *mst)
Destroys a tokenizer.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
void GNUNET_CONNECTION_notify_transmit_ready_cancel(struct GNUNET_CONNECTION_TransmitHandle *th)
Cancel the specified transmission-ready notification.
int GNUNET_SERVER_client_disable_corking(struct GNUNET_SERVER_Client *client)
Disable the "CORK" feature for communication with the given client, forcing the OS to immediately flu...
struct GNUNET_SERVER_Client * next
This is a doubly linked list.
int GNUNET_SERVER_mst_receive(struct GNUNET_SERVER_MessageStreamTokenizer *mst, void *client_identity, const char *buf, size_t size, int purge, int one_shot)
Add incoming data to the receive buffer and call the callback for all complete messages.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
int receive_pending
Are we currently trying to receive? (GNUNET_YES if we are, GNUNET_NO if we are not, GNUNET_SYSERR if data is already available in MST).
static int ret
Final status code.
Definition: gnunet-arm.c:89
void * callback_cls
Closure for callback.
int GNUNET_SERVER_inject(struct GNUNET_SERVER_Handle *server, struct GNUNET_SERVER_Client *sender, const struct GNUNET_MessageHeader *message)
Inject a message into the server, pretend it came from the specified client.
struct GNUNET_CONNECTION_Handle * GNUNET_CONNECTION_create_from_accept(GNUNET_CONNECTION_AccessCheck access_cb, void *access_cb_cls, struct GNUNET_NETWORK_Handle *lsock)
Create a connection handle by accepting on a listen socket.
struct NotifyList * next
This is a doubly linked list.
uint64_t abs_value_us
The actual value.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified priority and to be run after the specified delay or wh...
Definition: scheduler.c:1501
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_SERVER_Handle * GNUNET_SERVER_create_with_sockets(GNUNET_CONNECTION_AccessCheck access_cb, void *access_cb_cls, struct GNUNET_NETWORK_Handle **lsocks, struct GNUNET_TIME_Relative idle_timeout, int require_found)
Create a new server.
size_t(* GNUNET_CONNECTION_TransmitReadyNotify)(void *cls, size_t size, void *buf)
Function called to notify a client about the connection begin ready to queue more data...
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
void GNUNET_SERVER_disconnect_notify_cancel(struct GNUNET_SERVER_Handle *server, GNUNET_SERVER_DisconnectCallback callback, void *callback_cls)
Ask the server to stop notifying us whenever a client connects.
struct NotifyList * prev
This is a doubly linked list.
void GNUNET_SERVER_connect_notify_cancel(struct GNUNET_SERVER_Handle *server, GNUNET_SERVER_ConnectCallback callback, void *callback_cls)
Ask the server to stop notifying us whenever a client disconnects.
void GNUNET_SERVER_client_set_user_context_(struct GNUNET_SERVER_Client *client, void *ptr, size_t size)
Set user context to be associated with the given client.
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1254
struct HandlerList * handlers
List of handlers for incoming messages.
int GNUNET_CONNECTION_disable_corking(struct GNUNET_CONNECTION_Handle *connection)
Disable the "CORK" feature for communication with the given connection, forcing the OS to immediately...
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1237
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1238
struct GNUNET_CONNECTION_TransmitHandle * cth
Active connection transmission handle.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
struct GNUNET_SERVER_TransmitHandle th
Transmission handle we return for this client from GNUNET_SERVER_notify_transmit_ready.
int is_monitor
Is this client a &#39;monitor&#39; client that should not be counted when deciding on destroying the server d...
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition: gnunet-arm.c:114
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
void GNUNET_SERVER_notify_transmit_ready_cancel(struct GNUNET_SERVER_TransmitHandle *th)
Abort transmission request.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
struct GNUNET_TIME_Relative idle_timeout
After how long should an idle connection time out (on write).
struct GNUNET_TIME_Relative idle_timeout
After how long should an idle connection time out (on write).
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1264
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:686
collection of IO descriptors
static char buf[2048]
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_select(enum GNUNET_SCHEDULER_Priority prio, struct GNUNET_TIME_Relative delay, const struct GNUNET_NETWORK_FDSet *rs, const struct GNUNET_NETWORK_FDSet *ws, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when any of the specified file descriptor set...
Definition: scheduler.c:1784
void GNUNET_SERVER_set_callbacks(struct GNUNET_SERVER_Handle *server, GNUNET_SERVER_MstCreateCallback create, GNUNET_SERVER_MstDestroyCallback destroy, GNUNET_SERVER_MstReceiveCallback receive, void *cls)
Change functions used by the server to tokenize the message stream.
int GNUNET_CONNECTION_receive(struct GNUNET_CONNECTION_Handle *connection, size_t max, struct GNUNET_TIME_Relative timeout, GNUNET_CONNECTION_Receiver receiver, void *receiver_cls)
Receive data from the given connection.
struct NotifyList * disconnect_notify_list_head
Head of linked list of functions to call on disconnects by clients.
int GNUNET_CONNECTION_check(struct GNUNET_CONNECTION_Handle *connection)
Check if connection is valid (no fatal errors have happened so far).
void GNUNET_SERVER_client_drop(struct GNUNET_SERVER_Client *client)
Notify the server that the given client handle is no longer required.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
handle for a server
GNUNET_SERVER_MstCreateCallback mst_create
Alternative function to create a MST instance.
struct GNUNET_CONNECTION_Handle * connection
Client closure for callbacks.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages)...
void GNUNET_SERVER_client_set_timeout(struct GNUNET_SERVER_Client *client, struct GNUNET_TIME_Relative timeout)
Change the timeout for a particular client.
void GNUNET_SERVER_disconnect_notify(struct GNUNET_SERVER_Handle *server, GNUNET_SERVER_DisconnectCallback callback, void *callback_cls)
Ask the server to notify us whenever a client disconnects.
struct GNUNET_SERVER_Client * prev
This is a doubly linked list.
uint16_t expected_size
Expected size of messages of this type.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
void(* GNUNET_SERVER_DisconnectCallback)(void *cls, struct GNUNET_SERVER_Client *client)
Functions with this signature are called whenever a client is disconnected on the network level...
int shutdown_now
We&#39;re about to close down this client.
void GNUNET_SERVER_resume(struct GNUNET_SERVER_Handle *server)
Resume accepting connections from the listen socket.
unsigned int reference_count
Number of external entities with a reference to this client object.
void GNUNET_SERVER_client_disconnect(struct GNUNET_SERVER_Client *client)
Ask the server to disconnect from the given client.
static void restart_processing(void *cls)
Task run to start again receiving from the network and process requests.
static void process_incoming(void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode)
We are receiving an incoming message.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
size_t user_context_size
Last size given when user context was initialized; used for sanity check.
static int client_message_tokenizer_callback(void *cls, void *client, const struct GNUNET_MessageHeader *message)
This function is called whenever our inbound message tokenizer has received a complete message...
static unsigned int size
Size of the "table".
Definition: peer.c:66
int require_found
Do we ignore messages of types that we do not understand or do we require that a handler is found (an...
uint16_t type
Type of the message this handler covers.
int GNUNET_CONNECTION_get_address(struct GNUNET_CONNECTION_Handle *connection, void **addr, size_t *addrlen)
Obtain the network address of the other party.
static void process_listen_socket(void *cls)
Scheduler says our listen socket is ready.
void GNUNET_CONNECTION_destroy(struct GNUNET_CONNECTION_Handle *connection)
Close the connection and free associated resources.
uint16_t warn_type
Type of last message processed (for warn_no_receive_done).
static void do_destroy(void *cls)
Helper function for test_monitor_clients() to trigger GNUNET_SERVER_destroy() after the stack has unw...
int GNUNET_SERVER_client_get_address(struct GNUNET_SERVER_Client *client, void **addr, size_t *addrlen)
Obtain the network address of the other party.
void GNUNET_NETWORK_fdset_set(struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_NETWORK_Handle *desc)
Add a socket to the FD set.
Definition: network.c:999
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
void *(* GNUNET_SERVER_MstCreateCallback)(void *cls, struct GNUNET_SERVER_Client *client)
Signature of a function to create a custom tokenizer.
GNUNET_CONNECTION_AccessCheck access_cb
Function to call for access control.
struct GNUNET_TIME_Absolute warn_start
Time when the warn task was started.
void GNUNET_SERVER_client_mark_monitor(struct GNUNET_SERVER_Client *client)
Set the &#39;monitor&#39; flag on this client.
GNUNET_CONNECTION_TransmitReadyNotify callback
Function to call to get the message.
int(* GNUNET_CONNECTION_AccessCheck)(void *cls, const struct GNUNET_CONNECTION_Credentials *ucred, const struct sockaddr *addr, socklen_t addrlen)
Function to call for access control checks.
#define GNUNET_MESSAGE_TYPE_ALL
Next available: 1500.
void(* GNUNET_SERVER_MstDestroyCallback)(void *cls, void *mst)
Signature of a function to destroy a custom tokenizer.
struct GNUNET_SCHEDULER_Task * listen_task
Task scheduled to do the listening.
int persist
Persist the file handle for this client no matter what happens, force the OS to close once the proces...
struct NotifyList * disconnect_notify_list_tail
Tail of linked list of functions to call on disconnects by clients.
void GNUNET_SERVER_connect_notify(struct GNUNET_SERVER_Handle *server, GNUNET_SERVER_ConnectCallback callback, void *callback_cls)
Ask the server to notify us whenever a client connects.
static uint16_t port
Port number.
Definition: gnunet-bcd.c:81
struct GNUNET_CONNECTION_TransmitHandle * GNUNET_CONNECTION_notify_transmit_ready(struct GNUNET_CONNECTION_Handle *connection, size_t size, struct GNUNET_TIME_Relative timeout, GNUNET_CONNECTION_TransmitReadyNotify notify, void *notify_cls)
Ask the connection to call us once the specified number of bytes are free in the transmission buffer...
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:373
void * callback_cls
Closure for callback.
const struct GNUNET_SERVER_MessageHandler * handlers
NULL-terminated array of handlers.
#define LOG_STRERROR(kind, syscall)
#define GNUNET_log(kind,...)
struct GNUNET_SCHEDULER_Task * warn_task
Task that warns about missing calls to GNUNET_SERVER_receive_done.
Entry in list of pending tasks.
Definition: scheduler.c:131
void GNUNET_SERVER_receive_done(struct GNUNET_SERVER_Client *client, int success)
Resume receiving from this client, we are done processing the current request.
void GNUNET_SERVER_suspend(struct GNUNET_SERVER_Handle *server)
Suspend accepting connections from the listen socket temporarily.
struct NotifyList * connect_notify_list_tail
Tail of linked list of functions to call on connects by clients.
struct GNUNET_SERVER_TransmitHandle * GNUNET_SERVER_notify_transmit_ready(struct GNUNET_SERVER_Client *client, size_t size, struct GNUNET_TIME_Relative timeout, GNUNET_CONNECTION_TransmitReadyNotify callback, void *callback_cls)
Notify us when the server has enough space to transmit a message of the given size to the given clien...
handle to a socket
Definition: network.c:46
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
struct GNUNET_SERVER_Client * GNUNET_SERVER_connect_socket(struct GNUNET_SERVER_Handle *server, struct GNUNET_CONNECTION_Handle *connection)
Add a TCP socket-based connection to the set of handles managed by this server.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
Header for all communications.
int in_soft_shutdown
Set to GNUNET_YES once we are in &#39;soft&#39; shutdown where we wait for all non-monitor clients to disconn...
void GNUNET_SERVER_client_persist_(struct GNUNET_SERVER_Client *client)
Set the persistent flag on this client, used to setup client connection to only be killed when the se...
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
handle for a client of the server
struct GNUNET_SERVER_Client * clients_head
Head of list of our current clients.
static void destroy(void *cls)
static void test_monitor_clients(struct GNUNET_SERVER_Handle *server)
Check if only &#39;monitor&#39; clients are left.
struct GNUNET_SERVER_Handle * server
Server that this client belongs to.
struct HandlerList * next
This is a linked list.
int GNUNET_NETWORK_fdset_isset(const struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_NETWORK_Handle *desc)
Check whether a socket is part of the fd set.
Definition: network.c:1017
handle for a network connection
void * mst_cls
Closure for &#39;mst_&#39;-callbacks.
void * mst
Processing of incoming data.
void * callback_cls
Closure argument for callback.
void GNUNET_SERVER_stop_listening(struct GNUNET_SERVER_Handle *server)
Stop the listen socket and get ready to shutdown the server once only &#39;monitor&#39; clients are left...
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:548
static void process_mst(struct GNUNET_SERVER_Client *client, int ret)
Process messages from the client&#39;s message tokenizer until either the tokenizer is empty (and then sc...
struct GNUNET_SCHEDULER_Task * restart_task
ID of task used to restart processing.
#define GNUNET_malloc(size)
Wrapper around malloc.
struct GNUNET_SERVER_MessageStreamTokenizer * GNUNET_SERVER_mst_create(GNUNET_SERVER_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
void GNUNET_SERVER_disable_receive_done_warning(struct GNUNET_SERVER_Client *client)
Disable the warning the server issues if a message is not acknowledged in a timely fashion...
void(* GNUNET_SERVER_ConnectCallback)(void *cls, struct GNUNET_SERVER_Client *client)
Functions with this signature are called whenever a client is connected on the network level...
static size_t transmit_ready_callback_wrapper(void *cls, size_t size, void *buf)
Wrapper for transmission notification that calls the original callback and update the last activity t...
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:900
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956
unsigned int suspended
Was processing if incoming messages suspended while we were still processing data already received...