GNUnet  0.20.0
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, \
32  filename) GNUNET_log_from_strerror_file (kind, \
33  "util-server", \
34  syscall, \
35  filename)
36 
37 
42 {
46  struct HandlerList *next;
47 
52 };
53 
54 
58 struct NotifyList
59 {
63  struct NotifyList *next;
64 
68  struct NotifyList *prev;
69 
74 
78  void *callback_cls;
79 };
80 
81 
86 {
91 
96 
101 
106 
111 
116 
121 
126 
131 
137 
143 
148 
153 
158 
163 
167  void *mst_cls;
168 
174 
183 };
184 
185 
190 {
195 
200 
205 };
206 
207 
212 {
217 
222 
226  void *mst;
227 
232 
237 
243 
248 
253 
258 
264 
270 
276 
281  unsigned int reference_count;
282 
289  unsigned int suspended;
290 
296 
306 
311 
318 
324  int persist;
325 
332 
336  uint16_t warn_type;
337 };
338 
339 
348 void *
350  size_t size)
351 {
352  if ((0 == client->user_context_size) &&
353  (NULL == client->user_context))
354  return NULL; /* never set */
355  GNUNET_assert (size == client->user_context_size);
356  return client->user_context;
357 }
358 
359 
368 void
370  void *ptr,
371  size_t size)
372 {
373  if (NULL == ptr)
374  {
375  client->user_context_size = 0;
376  client->user_context = ptr;
377  return;
378  }
379  client->user_context_size = size;
380  client->user_context = ptr;
381 }
382 
383 
390 static void
392 {
393  struct GNUNET_SERVER_Handle *server = cls;
394  const struct GNUNET_SCHEDULER_TaskContext *tc;
396  unsigned int i;
397 
398  server->listen_task = NULL;
400  for (i = 0; NULL != server->listen_sockets[i]; i++)
401  {
403  server->listen_sockets[i]))
404  {
405  sock =
407  server->access_cb_cls,
408  server->listen_sockets[i]);
409  if (NULL != sock)
410  {
412  "Server accepted incoming connection.\n");
413  (void) GNUNET_SERVER_connect_socket (server,
414  sock);
415  }
416  }
417  }
418  /* listen for more! */
419  GNUNET_SERVER_resume (server);
420 }
421 
422 
430 static struct GNUNET_NETWORK_Handle *
431 open_listen_socket (const struct sockaddr *server_addr,
432  socklen_t socklen)
433 {
434  struct GNUNET_NETWORK_Handle *sock;
435  uint16_t port;
436  int eno;
437 
438  switch (server_addr->sa_family)
439  {
440  case AF_INET:
441  port = ntohs (((const struct sockaddr_in *) server_addr)->sin_port);
442  break;
443 
444  case AF_INET6:
445  port = ntohs (((const struct sockaddr_in6 *) server_addr)->sin6_port);
446  break;
447 
448  case AF_UNIX:
449  port = 0;
450  break;
451 
452  default:
453  GNUNET_break (0);
454  port = 0;
455  break;
456  }
457  sock = GNUNET_NETWORK_socket_create (server_addr->sa_family, SOCK_STREAM, 0);
458  if (NULL == sock)
459  {
461  errno = 0;
462  return NULL;
463  }
464  /* bind the socket */
465  if (GNUNET_OK != GNUNET_NETWORK_socket_bind (sock, server_addr, socklen))
466  {
467  eno = errno;
468  if (EADDRINUSE != errno)
469  {
470  /* we don't log 'EADDRINUSE' here since an IPv4 bind may
471  * fail if we already took the port on IPv6; if both IPv4 and
472  * IPv6 binds fail, then our caller will log using the
473  * errno preserved in 'eno' */
475  "bind");
476  if (0 != port)
478  _ ("`%s' failed for port %d (%s).\n"),
479  "bind",
480  port,
481  (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
482  eno = 0;
483  }
484  else
485  {
486  if (0 != port)
488  _ ("`%s' failed for port %d (%s): address already in use\n"),
489  "bind", port,
490  (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
491  else if (AF_UNIX == server_addr->sa_family)
492  {
494  _ ("`%s' failed for `%s': address already in use\n"),
495  "bind",
496  GNUNET_a2s (server_addr, socklen));
497  }
498  }
500  errno = eno;
501  return NULL;
502  }
503  if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
504  {
506  "listen");
508  errno = 0;
509  return NULL;
510  }
511  if (0 != port)
513  "Server starts to listen on port %u.\n",
514  port);
515  return sock;
516 }
517 
518 
531 struct GNUNET_SERVER_Handle *
533  void *access_cb_cls,
534  struct GNUNET_NETWORK_Handle **lsocks,
536  int require_found)
537 {
538  struct GNUNET_SERVER_Handle *server;
539 
540  server = GNUNET_new (struct GNUNET_SERVER_Handle);
541  server->idle_timeout = idle_timeout;
542  server->listen_sockets = lsocks;
543  server->access_cb = access_cb;
544  server->access_cb_cls = access_cb_cls;
545  server->require_found = require_found;
546  if (NULL != lsocks)
547  GNUNET_SERVER_resume (server);
548  return server;
549 }
550 
551 
565 struct GNUNET_SERVER_Handle *
567  void *access_cb_cls,
568  struct sockaddr *const *server_addr,
569  const socklen_t *socklen,
571  int require_found)
572 {
573  struct GNUNET_NETWORK_Handle **lsocks;
574  unsigned int i;
575  unsigned int j;
576  unsigned int k;
577  int seen;
578 
579  i = 0;
580  while (NULL != server_addr[i])
581  i++;
582  if (i > 0)
583  {
584  lsocks = GNUNET_malloc (sizeof(struct GNUNET_NETWORK_Handle *) * (i + 1));
585  i = 0;
586  j = 0;
587  while (NULL != server_addr[i])
588  {
589  seen = 0;
590  for (k = 0; k < i; k++)
591  if ((socklen[k] == socklen[i]) &&
592  (0 == memcmp (server_addr[k], server_addr[i], socklen[i])))
593  {
594  seen = 1;
595  break;
596  }
597  if (0 != seen)
598  {
599  /* duplicate address, skip */
600  i++;
601  continue;
602  }
603  lsocks[j] = open_listen_socket (server_addr[i], socklen[i]);
604  if (NULL != lsocks[j])
605  j++;
606  i++;
607  }
608  if (0 == j)
609  {
610  if (0 != errno)
612  GNUNET_free (lsocks);
613  lsocks = NULL;
614  }
615  }
616  else
617  {
618  lsocks = NULL;
619  }
620  return GNUNET_SERVER_create_with_sockets (access_cb,
621  access_cb_cls,
622  lsocks,
623  idle_timeout,
624  require_found);
625 }
626 
627 
640 void
642 {
644  "Marking client as monitor!\n");
645  client->is_monitor = GNUNET_YES;
646 }
647 
648 
655 static void
656 do_destroy (void *cls)
657 {
658  struct GNUNET_SERVER_Handle *server = cls;
659 
660  GNUNET_SERVER_destroy (server);
661 }
662 
663 
670 static void
672 {
673  struct GNUNET_SERVER_Client *client;
674 
676  return;
677  for (client = server->clients_head; NULL != client; client = client->next)
678  if (GNUNET_NO == client->is_monitor)
679  return;
680  /* not done yet */
683 }
684 
685 
691 void
693 {
694  if (NULL != server->listen_task)
695  {
697  server->listen_task = NULL;
698  }
699 }
700 
701 
702 void
704 {
705  struct GNUNET_NETWORK_FDSet *r;
706  unsigned int i;
707 
708  if (NULL == server->listen_sockets)
709  return;
710  if (NULL == server->listen_sockets[0])
711  return; /* nothing to do, no listen sockets! */
712  if (NULL == server->listen_sockets[1])
713  {
714  /* simplified method: no fd set needed; this is then much simpler
715  and much more efficient */
716  server->listen_task =
719  server->listen_sockets[0],
721  server);
722  return;
723  }
725  i = 0;
726  while (NULL != server->listen_sockets[i])
727  GNUNET_NETWORK_fdset_set (r, server->listen_sockets[i++]);
728  server->listen_task =
731  &process_listen_socket, server);
733 }
734 
735 
742 void
744 {
745  unsigned int i;
746 
748  "Server in soft shutdown\n");
749  if (NULL != server->listen_task)
750  {
752  server->listen_task = NULL;
753  }
754  if (NULL != server->listen_sockets)
755  {
756  i = 0;
757  while (NULL != server->listen_sockets[i])
760  GNUNET_free (server->listen_sockets);
761  server->listen_sockets = NULL;
762  }
763  if (GNUNET_NO == server->in_soft_shutdown)
764  server->in_soft_shutdown = GNUNET_YES;
765  test_monitor_clients (server);
766 }
767 
768 
774 void
776 {
777  struct HandlerList *hpos;
778  struct NotifyList *npos;
779  unsigned int i;
780 
782  "Server shutting down.\n");
783  if (NULL != server->listen_task)
784  {
786  server->listen_task = NULL;
787  }
788  if (NULL != server->listen_sockets)
789  {
790  i = 0;
791  while (NULL != server->listen_sockets[i])
794  GNUNET_free (server->listen_sockets);
795  server->listen_sockets = NULL;
796  }
797  while (NULL != server->clients_head)
799  while (NULL != (hpos = server->handlers))
800  {
801  server->handlers = hpos->next;
802  GNUNET_free (hpos);
803  }
804  while (NULL != (npos = server->disconnect_notify_list_head))
805  {
806  npos->callback (npos->callback_cls,
807  NULL);
810  npos);
811  GNUNET_free (npos);
812  }
813  while (NULL != (npos = server->connect_notify_list_head))
814  {
815  npos->callback (npos->callback_cls,
816  NULL);
818  server->connect_notify_list_tail,
819  npos);
820  GNUNET_free (npos);
821  }
822  GNUNET_free (server);
823 }
824 
825 
839 void
842 {
843  struct HandlerList *p;
844 
845  p = GNUNET_new (struct HandlerList);
846  p->handlers = handlers;
847  p->next = server->handlers;
848  server->handlers = p;
849 }
850 
851 
862 void
867  void *cls)
868 {
869  server->mst_create = create;
870  server->mst_destroy = destroy;
871  server->mst_receive = receive;
872  server->mst_cls = cls;
873 }
874 
875 
881 static void
883 {
884  struct GNUNET_SERVER_Client *client = cls;
885 
886  GNUNET_break (0 != client->warn_type); /* type should never be 0 here, as we don't use 0 */
887  client->warn_task =
889  &warn_no_receive_done, client);
891  _ (
892  "Processing code for message of type %u did not call `GNUNET_SERVER_receive_done' after %s\n"),
893  (unsigned int) client->warn_type,
896  GNUNET_YES));
897 }
898 
899 
907 void
909 {
910  if (NULL != client->warn_task)
911  {
913  client->warn_task = NULL;
914  }
915 }
916 
917 
933 int
935  struct GNUNET_SERVER_Client *sender,
936  const struct GNUNET_MessageHeader *message)
937 {
938  struct HandlerList *pos;
939  const struct GNUNET_SERVER_MessageHandler *mh;
940  unsigned int i;
941  uint16_t type;
942  uint16_t size;
943  int found;
944 
945  type = ntohs (message->type);
946  size = ntohs (message->size);
948  "Received message of type %u and size %u from client\n",
949  type, size);
950  found = GNUNET_NO;
951  for (pos = server->handlers; NULL != pos; pos = pos->next)
952  {
953  i = 0;
954  while (pos->handlers[i].callback != NULL)
955  {
956  mh = &pos->handlers[i];
957  if ((mh->type == type) || (mh->type == GNUNET_MESSAGE_TYPE_ALL))
958  {
959  if ((0 != mh->expected_size) && (mh->expected_size != size))
960  {
961 #if GNUNET8_NETWORK_IS_DEAD
963  "Expected %u bytes for message of type %u, got %u\n",
964  mh->expected_size, mh->type, size);
965  GNUNET_break_op (0);
966 #else
968  "Expected %u bytes for message of type %u, got %u\n",
969  mh->expected_size, mh->type, size);
970 #endif
971  return GNUNET_SYSERR;
972  }
973  if (NULL != sender)
974  {
975  if ((0 == sender->suspended) &&
976  (NULL == sender->warn_task))
977  {
978  GNUNET_break (0 != type); /* type should never be 0 here, as we don't use 0 */
980  sender->warn_task =
983  sender);
984  sender->warn_type = type;
985  }
986  sender->suspended++;
987  }
988  mh->callback (mh->callback_cls, sender, message);
989  found = GNUNET_YES;
990  }
991  i++;
992  }
993  }
994  if (GNUNET_NO == found)
995  {
997  "Received message of unknown type %d\n", type);
998  if (GNUNET_YES == server->require_found)
999  return GNUNET_SYSERR;
1000  }
1001  return GNUNET_OK;
1002 }
1003 
1004 
1015 static void
1016 process_incoming (void *cls,
1017  const void *buf,
1018  size_t available,
1019  const struct sockaddr *addr,
1020  socklen_t addrlen,
1021  int errCode);
1022 
1023 
1037 static void
1039  int ret)
1040 {
1041  while ((GNUNET_SYSERR != ret) && (NULL != client->server) &&
1042  (GNUNET_YES != client->shutdown_now) && (0 == client->suspended))
1043  {
1044  if (GNUNET_OK == ret)
1045  {
1047  "Server re-enters receive loop, timeout: %s.\n",
1049  GNUNET_YES));
1050  client->receive_pending = GNUNET_YES;
1051  if (GNUNET_OK !=
1054  client->idle_timeout,
1056  client))
1057  return;
1058  break;
1059  }
1061  "Server processes additional messages instantly.\n");
1062  if (NULL != client->server->mst_receive)
1063  ret =
1064  client->server->mst_receive (client->server->mst_cls, client->mst,
1065  client, NULL, 0, GNUNET_NO, GNUNET_YES);
1066  else
1067  ret =
1068  GNUNET_SERVER_mst_receive (client->mst, client, NULL, 0, GNUNET_NO,
1069  GNUNET_YES);
1070  }
1072  "Server leaves instant processing loop: ret = %d, server = %p, shutdown = %d, suspended = %u\n",
1073  ret, client->server,
1074  client->shutdown_now,
1075  client->suspended);
1076  if (GNUNET_NO == ret)
1077  {
1079  "Server has more data pending but is suspended.\n");
1080  client->receive_pending = GNUNET_SYSERR; /* data pending */
1081  }
1082  if ((GNUNET_SYSERR == ret) ||
1083  (GNUNET_YES == client->shutdown_now))
1085 }
1086 
1087 
1098 static void
1099 process_incoming (void *cls,
1100  const void *buf,
1101  size_t available,
1102  const struct sockaddr *addr,
1103  socklen_t addrlen,
1104  int errCode)
1105 {
1106  struct GNUNET_SERVER_Client *client = cls;
1107  struct GNUNET_SERVER_Handle *server = client->server;
1108  struct GNUNET_TIME_Absolute end;
1109  struct GNUNET_TIME_Absolute now;
1110  int ret;
1111 
1113  client->receive_pending = GNUNET_NO;
1114  now = GNUNET_TIME_absolute_get ();
1116  client->idle_timeout);
1117 
1118  if ((NULL == buf) &&
1119  (0 == available) &&
1120  (NULL == addr) &&
1121  (0 == errCode) &&
1122  (GNUNET_YES != client->shutdown_now) &&
1123  (NULL != server) &&
1125  (end.abs_value_us > now.abs_value_us))
1126  {
1127  /* wait longer, timeout changed (i.e. due to us sending) */
1129  "Receive time out, but no disconnect due to sending (%p)\n",
1130  client);
1131  client->receive_pending = GNUNET_YES;
1136  client);
1137  return;
1138  }
1139  if ((NULL == buf) ||
1140  (0 == available) ||
1141  (0 != errCode) ||
1142  (NULL == server) ||
1143  (GNUNET_YES == client->shutdown_now) ||
1145  {
1146  /* other side closed connection, error connecting, etc. */
1148  "Failed to connect or other side closed connection (%p)\n",
1149  client);
1151  return;
1152  }
1154  "Server receives %u bytes from `%s'.\n",
1155  (unsigned int) available,
1156  GNUNET_a2s (addr, addrlen));
1157  GNUNET_SERVER_client_keep (client);
1158  client->last_activity = now;
1159 
1160  if (NULL != server->mst_receive)
1161  {
1162  ret = client->server->mst_receive (client->server->mst_cls,
1163  client->mst,
1164  client,
1165  buf,
1166  available,
1167  GNUNET_NO,
1168  GNUNET_YES);
1169  }
1170  else if (NULL != client->mst)
1171  {
1172  ret =
1173  GNUNET_SERVER_mst_receive (client->mst,
1174  client,
1175  buf,
1176  available,
1177  GNUNET_NO,
1178  GNUNET_YES);
1179  }
1180  else
1181  {
1182  GNUNET_break (0);
1183  return;
1184  }
1185  process_mst (client,
1186  ret);
1187  GNUNET_SERVER_client_drop (client);
1188 }
1189 
1190 
1197 static void
1199 {
1200  struct GNUNET_SERVER_Client *client = cls;
1201 
1202  GNUNET_assert (GNUNET_YES != client->shutdown_now);
1203  client->restart_task = NULL;
1204  if (GNUNET_NO == client->receive_pending)
1205  {
1206  LOG (GNUNET_ERROR_TYPE_DEBUG, "Server begins to read again from client.\n");
1207  client->receive_pending = GNUNET_YES;
1210  client->idle_timeout,
1212  client);
1213  return;
1214  }
1216  "Server continues processing messages still in the buffer.\n");
1217  GNUNET_SERVER_client_keep (client);
1218  client->receive_pending = GNUNET_NO;
1219  process_mst (client,
1220  GNUNET_NO);
1221  GNUNET_SERVER_client_drop (client);
1222 }
1223 
1224 
1235 static int
1237  void *client,
1238  const struct GNUNET_MessageHeader *message)
1239 {
1240  struct GNUNET_SERVER_Handle *server = cls;
1241  struct GNUNET_SERVER_Client *sender = client;
1242  int ret;
1243 
1245  "Tokenizer gives server message of type %u and size %u from client\n",
1246  ntohs (message->type), ntohs (message->size));
1248  ret = GNUNET_SERVER_inject (server, sender, message);
1250  if ((GNUNET_OK != ret) || (GNUNET_YES == sender->shutdown_now))
1251  {
1253  return GNUNET_SYSERR;
1254  }
1255  return GNUNET_OK;
1256 }
1257 
1258 
1270 struct GNUNET_SERVER_Client *
1273 {
1274  struct GNUNET_SERVER_Client *client;
1275  struct NotifyList *n;
1276 
1277  client = GNUNET_new (struct GNUNET_SERVER_Client);
1278  client->connection = connection;
1279  client->server = server;
1281  client->idle_timeout = server->idle_timeout;
1283  server->clients_tail,
1284  client);
1285  if (NULL != server->mst_create)
1286  client->mst =
1287  server->mst_create (server->mst_cls, client);
1288  else
1289  client->mst =
1291  server);
1292  GNUNET_assert (NULL != client->mst);
1293  for (n = server->connect_notify_list_head; NULL != n; n = n->next)
1294  n->callback (n->callback_cls, client);
1295  client->receive_pending = GNUNET_YES;
1296  if (GNUNET_SYSERR ==
1299  client->idle_timeout,
1301  client))
1302  return NULL;
1303  return client;
1304 }
1305 
1306 
1315 void
1318 {
1319  client->idle_timeout = timeout;
1320 }
1321 
1322 
1330 void
1332 {
1333  client->reference_count++;
1334 }
1335 
1336 
1345 void
1347 {
1348  GNUNET_assert (client->reference_count > 0);
1349  client->reference_count--;
1350  if ((GNUNET_YES == client->shutdown_now) && (0 == client->reference_count))
1352 }
1353 
1354 
1363 int
1365  void **addr, size_t *addrlen)
1366 {
1367  return GNUNET_CONNECTION_get_address (client->connection, addr, addrlen);
1368 }
1369 
1370 
1381 void
1384  void *callback_cls)
1385 {
1386  struct NotifyList *n;
1387 
1388  n = GNUNET_new (struct NotifyList);
1389  n->callback = callback;
1393  n);
1394 }
1395 
1396 
1410 void
1413  void *callback_cls)
1414 {
1415  struct NotifyList *n;
1416  struct GNUNET_SERVER_Client *client;
1417 
1418  n = GNUNET_new (struct NotifyList);
1419  n->callback = callback;
1420  n->callback_cls = callback_cls;
1423  n);
1424  for (client = server->clients_head; NULL != client; client = client->next)
1425  callback (callback_cls, client);
1426 }
1427 
1428 
1436 void
1439  callback,
1440  void *callback_cls)
1441 {
1442  struct NotifyList *pos;
1443 
1444  for (pos = server->disconnect_notify_list_head; NULL != pos; pos = pos->next)
1445  if ((pos->callback == callback) && (pos->callback_cls == callback_cls))
1446  break;
1447  if (NULL == pos)
1448  {
1449  GNUNET_break (0);
1450  return;
1451  }
1454  pos);
1455  GNUNET_free (pos);
1456 }
1457 
1458 
1466 void
1469  void *callback_cls)
1470 {
1471  struct NotifyList *pos;
1472 
1473  for (pos = server->connect_notify_list_head; NULL != pos; pos = pos->next)
1474  if ((pos->callback == callback) && (pos->callback_cls == callback_cls))
1475  break;
1476  if (NULL == pos)
1477  {
1478  GNUNET_break (0);
1479  return;
1480  }
1482  server->connect_notify_list_tail,
1483  pos);
1484  GNUNET_free (pos);
1485 }
1486 
1487 
1496 void
1498 {
1499  struct GNUNET_SERVER_Handle *server = client->server;
1500  struct NotifyList *n;
1501 
1503  "Client is being disconnected from the server.\n");
1504  if (NULL != client->restart_task)
1505  {
1507  client->restart_task = NULL;
1508  }
1509  if (NULL != client->warn_task)
1510  {
1512  client->warn_task = NULL;
1513  }
1514  if (GNUNET_YES == client->receive_pending)
1515  {
1517  client->receive_pending = GNUNET_NO;
1518  }
1519  client->shutdown_now = GNUNET_YES;
1520  client->reference_count++; /* make sure nobody else clean up client... */
1521  if ((NULL != client->mst) &&
1522  (NULL != server))
1523  {
1525  server->clients_tail,
1526  client);
1527  if (NULL != server->mst_destroy)
1528  server->mst_destroy (server->mst_cls,
1529  client->mst);
1530  else
1531  GNUNET_SERVER_mst_destroy (client->mst);
1532  client->mst = NULL;
1533  for (n = server->disconnect_notify_list_head; NULL != n; n = n->next)
1534  n->callback (n->callback_cls,
1535  client);
1536  }
1537  client->reference_count--;
1538  if (client->reference_count > 0)
1539  {
1541  "RC of %p still positive, not destroying everything.\n",
1542  client);
1543  client->server = NULL;
1544  return;
1545  }
1546  if (GNUNET_YES == client->in_process_client_buffer)
1547  {
1549  "Still processing inputs of %p, not destroying everything.\n",
1550  client);
1551  return;
1552  }
1554  "RC of %p now zero, destroying everything.\n",
1555  client);
1556  if (GNUNET_YES == client->persist)
1558  if (NULL != client->th.cth)
1561  /* need to cancel again, as it might have been re-added
1562  in the meantime (i.e. during callbacks) */
1563  if (NULL != client->warn_task)
1564  {
1566  client->warn_task = NULL;
1567  }
1568  if (GNUNET_YES == client->receive_pending)
1569  {
1571  client->receive_pending = GNUNET_NO;
1572  }
1573  GNUNET_free (client);
1574  /* we might be in soft-shutdown, test if we're done */
1575  if (NULL != server)
1576  test_monitor_clients (server);
1577 }
1578 
1579 
1588 int
1590 {
1592 }
1593 
1594 
1604 static size_t
1605 transmit_ready_callback_wrapper (void *cls, size_t size, void *buf)
1606 {
1607  struct GNUNET_SERVER_Client *client = cls;
1609 
1610  client->th.cth = NULL;
1611  callback = client->th.callback;
1612  client->th.callback = NULL;
1614  return callback (client->th.callback_cls, size, buf);
1615 }
1616 
1617 
1620  size_t size,
1623  callback,
1624  void *callback_cls)
1625 {
1626  if (NULL != client->th.callback)
1627  return NULL;
1628  client->th.callback_cls = callback_cls;
1629  client->th.callback = callback;
1631  size,
1632  timeout,
1633  &
1635  client);
1636  return &client->th;
1637 }
1638 
1639 
1645 void
1648 {
1650  th->cth = NULL;
1651  th->callback = NULL;
1652 }
1653 
1654 
1661 void
1663 {
1664  client->persist = GNUNET_YES;
1665 }
1666 
1667 
1680 void
1682  int success)
1683 {
1684  if (NULL == client)
1685  return;
1686  GNUNET_assert (client->suspended > 0);
1687  client->suspended--;
1688  if (GNUNET_OK != success)
1689  {
1691  "GNUNET_SERVER_receive_done called with failure indication\n");
1692  if ((client->reference_count > 0) || (client->suspended > 0))
1693  client->shutdown_now = GNUNET_YES;
1694  else
1696  return;
1697  }
1698  if (client->suspended > 0)
1699  {
1701  "GNUNET_SERVER_receive_done called, but more clients pending\n");
1702  return;
1703  }
1704  if (NULL != client->warn_task)
1705  {
1707  client->warn_task = NULL;
1708  }
1709  if (GNUNET_YES == client->in_process_client_buffer)
1710  {
1712  "GNUNET_SERVER_receive_done called while still in processing loop\n");
1713  return;
1714  }
1715  if ((NULL == client->server) || (GNUNET_YES == client->shutdown_now))
1716  {
1718  return;
1719  }
1721  "GNUNET_SERVER_receive_done causes restart in reading from the socket\n");
1722  GNUNET_assert (NULL == client->restart_task);
1724  client);
1725 }
1726 
1727 
1728 /* end of server.c */
#define LOG(kind,...)
Definition: abd_api.c:38
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
static uint16_t port
Port number.
Definition: gnunet-bcd.c:147
static struct GNUNET_CADET_MessageHandler handlers[]
Handlers, for diverse services.
static struct GNUNET_CADET_Handle * mh
Cadet handle.
Definition: gnunet-cadet.c:92
static void destroy(void *cls)
static int create
Create DID Document Flag.
Definition: gnunet-did.c:71
#define LOG_STRERROR(kind, syscall)
static char buf[2048]
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
Constants for network protocols.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_log(kind,...)
@ GNUNET_SCHEDULER_PRIORITY_HIGH
Run with high priority (important requests).
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
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).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_BULK
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1171
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:509
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1187
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:833
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:932
enum GNUNET_GenericReturnValue 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:440
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_listen(const struct GNUNET_NETWORK_Handle *desc, int backlog)
Listen on a socket.
Definition: network.c:652
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:950
#define GNUNET_MESSAGE_TYPE_ALL
Type used to match 'all' message types.
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:1540
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:1299
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:1830
const struct GNUNET_SCHEDULER_TaskContext * GNUNET_SCHEDULER_get_task_context(void)
Obtain the reasoning why the current task was started.
Definition: scheduler.c:752
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
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:1272
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
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:436
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:405
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
#define GNUNET_TIME_UNIT_MINUTES
One minute.
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:450
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:569
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
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.
struct GNUNET_SERVER_MessageStreamTokenizer * GNUNET_SERVER_mst_create(GNUNET_SERVER_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
void(* GNUNET_SERVER_MstDestroyCallback)(void *cls, void *mst)
Signature of a function to destroy a custom tokenizer.
void *(* GNUNET_SERVER_MstCreateCallback)(void *cls, struct GNUNET_SERVER_Client *client)
Signature of a function to create a custom tokenizer.
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.
void GNUNET_SERVER_mst_destroy(struct GNUNET_SERVER_MessageStreamTokenizer *mst)
Destroys a tokenizer.
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.
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.
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.
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.
void GNUNET_CONNECTION_destroy(struct GNUNET_CONNECTION_Handle *connection)
Close the connection and free associated resources.
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:431
handle for a network connection
struct GNUNET_NETWORK_Handle * sock
Underlying OS's socket, set to NULL after fatal errors.
Header for all communications.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
collection of IO descriptors
handle to a socket
Definition: network.c:54
Context information passed to each scheduler task.
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 ...
Entry in list of pending tasks.
Definition: scheduler.c:136
handle for a client of the server
struct GNUNET_SERVER_Client * prev
This is a doubly linked list.
uint16_t warn_type
Type of last message processed (for warn_no_receive_done).
struct GNUNET_TIME_Absolute warn_start
Time when the warn task was started.
int receive_pending
Are we currently trying to receive? (GNUNET_YES if we are, GNUNET_NO if we are not,...
unsigned int reference_count
Number of external entities with a reference to this client object.
unsigned int suspended
Was processing if incoming messages suspended while we were still processing data already received?...
int persist
Persist the file handle for this client no matter what happens, force the OS to close once the proces...
struct GNUNET_TIME_Relative idle_timeout
After how long should an idle connection time out (on write).
int shutdown_now
We're about to close down this client.
struct GNUNET_SCHEDULER_Task * warn_task
Task that warns about missing calls to GNUNET_SERVER_receive_done.
struct GNUNET_CONNECTION_Handle * connection
Client closure for callbacks.
struct GNUNET_SERVER_Client * next
This is a doubly linked list.
struct GNUNET_SERVER_TransmitHandle th
Transmission handle we return for this client from GNUNET_SERVER_notify_transmit_ready.
void * mst
Processing of incoming data.
void * user_context
User context value, manipulated using 'GNUNET_SERVER_client_{get/set}_user_context' functions.
size_t user_context_size
Last size given when user context was initialized; used for sanity check.
int is_monitor
Is this client a 'monitor' client that should not be counted when deciding on destroying the server d...
struct GNUNET_TIME_Absolute last_activity
Last activity on this socket (used to time it out if reference_count == 0).
struct GNUNET_SCHEDULER_Task * restart_task
ID of task used to restart processing.
int in_process_client_buffer
Are we currently in the "process_client_buffer" function (and will hence restart the receive job on e...
struct GNUNET_SERVER_Handle * server
Server that this client belongs to.
handle for a server
struct NotifyList * disconnect_notify_list_tail
Tail of linked list of functions to call on disconnects by clients.
void * mst_cls
Closure for 'mst_'-callbacks.
int require_found
Do we ignore messages of types that we do not understand or do we require that a handler is found (an...
struct GNUNET_SERVER_Client * clients_tail
Head of list of our current clients.
struct GNUNET_SCHEDULER_Task * listen_task
Task scheduled to do the listening.
struct NotifyList * connect_notify_list_tail
Tail of linked list of functions to call on connects by clients.
struct GNUNET_SERVER_Client * clients_head
Head of list of our current clients.
GNUNET_SERVER_MstCreateCallback mst_create
Alternative function to create a MST instance.
int in_soft_shutdown
Set to GNUNET_YES once we are in 'soft' shutdown where we wait for all non-monitor clients to disconn...
struct GNUNET_NETWORK_Handle ** listen_sockets
NULL-terminated array of sockets used to listen for new connections.
void * access_cb_cls
Closure for access_cb.
GNUNET_CONNECTION_AccessCheck access_cb
Function to call for access control.
GNUNET_SERVER_MstReceiveCallback mst_receive
Alternative function to give data to a MST instance.
GNUNET_SERVER_MstDestroyCallback mst_destroy
Alternative function to destroy a MST instance.
struct NotifyList * connect_notify_list_head
Head of linked list of functions to call on connects by clients.
struct HandlerList * handlers
List of handlers for incoming messages.
struct GNUNET_TIME_Relative idle_timeout
After how long should an idle connection time out (on write).
struct NotifyList * disconnect_notify_list_head
Head of linked list of functions to call on disconnects by clients.
GNUNET_SERVER_MessageCallback callback
Function to call for messages of "type".
Handle server returns for aborting transmission to a client.
void * callback_cls
Closure for callback.
GNUNET_CONNECTION_TransmitReadyNotify callback
Function to call to get the message.
struct GNUNET_CONNECTION_TransmitHandle * cth
Active connection transmission handle.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
List of arrays of message handlers.
const struct GNUNET_SERVER_MessageHandler * handlers
NULL-terminated array of handlers.
struct HandlerList * next
This is a linked list.
List of arrays of message handlers.
void * callback_cls
Closure for callback.
GNUNET_SERVER_DisconnectCallback callback
Function to call.
struct NotifyList * prev
This is a doubly linked list.
struct NotifyList * next
This is a doubly linked list.
void * GNUNET_CONNECTION_receive_cancel(struct GNUNET_CONNECTION_Handle *connection)
Cancel receive job on the given connection.
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.
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...
int GNUNET_CONNECTION_get_address(struct GNUNET_CONNECTION_Handle *connection, void **addr, size_t *addrlen)
Obtain the network address of the other party.
int GNUNET_CONNECTION_check(struct GNUNET_CONNECTION_Handle *connection)
Check if connection is valid (no fatal errors have happened so far).
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 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.
void GNUNET_CONNECTION_persist_(struct GNUNET_CONNECTION_Handle *connection)
Set the persist option on this connection handle.
void GNUNET_CONNECTION_notify_transmit_ready_cancel(struct GNUNET_CONNECTION_TransmitHandle *th)
Cancel the specified transmission-ready notification.
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.
static void test_monitor_clients(struct GNUNET_SERVER_Handle *server)
Check if only 'monitor' clients are left.
void GNUNET_SERVER_add_handlers(struct GNUNET_SERVER_Handle *server, const struct GNUNET_SERVER_MessageHandler *handlers)
Add additional handlers to an existing server.
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_client_keep(struct GNUNET_SERVER_Client *client)
Notify the server that the given client handle should be kept (keeps the connection up if possible,...
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.
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.
void GNUNET_SERVER_client_drop(struct GNUNET_SERVER_Client *client)
Notify the server that the given client handle is no longer required.
static void warn_no_receive_done(void *cls)
Task run to warn about missing calls to GNUNET_SERVER_receive_done.
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...
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_client_mark_monitor(struct GNUNET_SERVER_Client *client)
Set the 'monitor' flag on this client.
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.
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.
void GNUNET_SERVER_destroy(struct GNUNET_SERVER_Handle *server)
Free resources held by this server.
void * GNUNET_SERVER_client_get_user_context_(struct GNUNET_SERVER_Client *client, size_t size)
Return user context associated with the given client.
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.
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_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...
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_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...
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.
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_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_suspend(struct GNUNET_SERVER_Handle *server)
Suspend accepting connections from the listen socket temporarily.
static void do_destroy(void *cls)
Helper function for test_monitor_clients() to trigger GNUNET_SERVER_destroy() after the stack has unw...
void GNUNET_SERVER_client_disconnect(struct GNUNET_SERVER_Client *client)
Ask the server to disconnect from the given client.
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...
static void process_mst(struct GNUNET_SERVER_Client *client, int ret)
Process messages from the client's message tokenizer until either the tokenizer is empty (and then sc...
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.
static void restart_processing(void *cls)
Task run to start again receiving from the network and process requests.
void GNUNET_SERVER_stop_listening(struct GNUNET_SERVER_Handle *server)
Stop the listen socket and get ready to shutdown the server once only 'monitor' clients are left.
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.
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.
void GNUNET_SERVER_resume(struct GNUNET_SERVER_Handle *server)
Resume accepting connections from the listen socket.
void GNUNET_SERVER_notify_transmit_ready_cancel(struct GNUNET_SERVER_TransmitHandle *th)
Abort transmission request.
static void process_listen_socket(void *cls)
Scheduler says our listen socket is ready.
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.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model