GNUnet  0.10.x
gnunet-communicator-unix.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2010-2014, 2018 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 
29 #include "platform.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_protocols.h"
32 #include "gnunet_constants.h"
33 #include "gnunet_nt_lib.h"
36 
45 #define DEFAULT_MAX_QUEUE_LENGTH 8
46 
50 #define COMMUNICATOR_ADDRESS_PREFIX "unix"
51 
55 #define COMMUNICATOR_CONFIG_SECTION "communicator-unix"
56 
60 #define UNIX_MTU UINT16_MAX
61 
63 
67 struct UNIXMessage {
72 
77 };
78 
80 
81 
85 struct Queue {
89  struct Queue *next;
90 
94  struct Queue *prev;
95 
99  struct GNUNET_PeerIdentity target;
100 
104  struct sockaddr_un *address;
105 
109  socklen_t address_len;
110 
115  const struct GNUNET_MessageHeader *msg;
116 
120  struct GNUNET_MQ_Handle *mq;
121 
125  struct GNUNET_TRANSPORT_QueueHandle *qh;
126 
130  unsigned long long bytes_in_queue;
131 
136 
141 };
142 
143 
148 
153 
157 static unsigned long long delivering_messages;
158 
162 static unsigned long long max_queue_length;
163 
168 
173 
178 
182 static struct Queue *queue_head;
183 
187 static struct Queue *queue_tail;
188 
193 
198 
199 
207 static void
209 {
210  struct GNUNET_MQ_Handle *mq;
211 
213  "Disconnecting queue for peer `%s'\n",
214  GNUNET_i2s(&queue->target));
215  if (0 != queue->bytes_in_queue)
216  {
217  GNUNET_CONTAINER_DLL_remove(queue_head, queue_tail, queue);
218  queue->bytes_in_queue = 0;
219  }
220  if (NULL != (mq = queue->mq))
221  {
222  queue->mq = NULL;
223  GNUNET_MQ_destroy(mq);
224  }
226  GNUNET_YES ==
227  GNUNET_CONTAINER_multipeermap_remove(queue_map, &queue->target, queue));
228  GNUNET_STATISTICS_set(stats,
229  "# queues active",
231  GNUNET_NO);
232  if (NULL != queue->timeout_task)
233  {
235  queue->timeout_task = NULL;
236  }
237  GNUNET_free(queue->address);
238  GNUNET_free(queue);
239 }
240 
241 
247 static void
248 queue_timeout(void *cls)
249 {
250  struct Queue *queue = cls;
251  struct GNUNET_TIME_Relative left;
252 
253  queue->timeout_task = NULL;
255  if (0 != left.rel_value_us)
256  {
257  /* not actually our turn yet, but let's at least update
258  the monitor, it may think we're about to die ... */
259  queue->timeout_task =
261  return;
262  }
264  "Queue %p was idle for %s, disconnecting\n",
265  queue,
268  GNUNET_YES));
269  queue_destroy(queue);
270 }
271 
272 
280 static void
282 {
283  GNUNET_assert(NULL != queue->timeout_task);
284  queue->timeout =
286 }
287 
288 
297 static struct sockaddr_un *
298 unix_address_to_sockaddr(const char *unixpath, socklen_t *sock_len)
299 {
300  struct sockaddr_un *un;
301  size_t slen;
302 
303  GNUNET_assert(0 < strlen(unixpath)); /* sanity check */
304  un = GNUNET_new(struct sockaddr_un);
305  un->sun_family = AF_UNIX;
306  slen = strlen(unixpath);
307  if (slen >= sizeof(un->sun_path))
308  slen = sizeof(un->sun_path) - 1;
309  GNUNET_memcpy(un->sun_path, unixpath, slen);
310  un->sun_path[slen] = '\0';
311  slen = sizeof(struct sockaddr_un);
312 #if HAVE_SOCKADDR_UN_SUN_LEN
313  un->sun_len = (u_char)slen;
314 #endif
315  (*sock_len) = slen;
316  if ('@' == un->sun_path[0])
317  un->sun_path[0] = '\0';
318  return un;
319 }
320 
321 
325 struct LookupCtx {
329  struct Queue *res;
330 
334  const struct sockaddr_un *un;
335 
339  socklen_t un_len;
340 };
341 
342 
351 static int
352 lookup_queue_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
353 {
354  struct LookupCtx *lctx = cls;
355  struct Queue *queue = value;
356 
357  if ((queue->address_len = lctx->un_len) &&
358  (0 == memcmp(lctx->un, queue->address, queue->address_len)))
359  {
360  lctx->res = queue;
361  return GNUNET_NO;
362  }
363  return GNUNET_YES;
364 }
365 
366 
374 static struct Queue *
376  const struct sockaddr_un *un,
377  socklen_t un_len)
378 {
379  struct LookupCtx lctx;
380 
381  lctx.un = un;
382  lctx.un_len = un_len;
384  peer,
386  &lctx);
387  return lctx.res;
388 }
389 
390 
397 static void
398 select_write_cb(void *cls)
399 {
400  struct Queue *queue = queue_tail;
401  const struct GNUNET_MessageHeader *msg = queue->msg;
402  size_t msg_size = ntohs(msg->size);
403  ssize_t sent;
404 
405  /* take queue of the ready list */
406  write_task = NULL;
407  GNUNET_CONTAINER_DLL_remove(queue_head, queue_tail, queue);
408  if (NULL != queue_head)
410  unix_sock,
412  NULL);
413 
414  /* send 'msg' */
415  queue->msg = NULL;
417 resend:
418  /* Send the data */
419  sent = GNUNET_NETWORK_socket_sendto(unix_sock,
420  msg,
421  msg_size,
422  (const struct sockaddr *)queue->address,
423  queue->address_len);
425  "UNIX transmitted message to %s (%d/%u: %s)\n",
426  GNUNET_i2s(&queue->target),
427  (int)sent,
428  (unsigned int)msg_size,
429  (sent < 0) ? strerror(errno) : "ok");
430  if (-1 != sent)
431  {
433  "# bytes sent",
434  (long long)sent,
435  GNUNET_NO);
437  return; /* all good */
438  }
440  "# network transmission failures",
441  1,
442  GNUNET_NO);
443  switch (errno)
444  {
445  case EAGAIN:
446  case ENOBUFS:
447  /* We should retry later... */
449  return;
450 
451  case EMSGSIZE: {
452  socklen_t size = 0;
453  socklen_t len = sizeof(size);
454 
456  SOL_SOCKET,
457  SO_SNDBUF,
458  &size,
459  &len);
460  if (size > ntohs(msg->size))
461  {
462  /* Buffer is bigger than message: error, no retry
463  * This should never happen!*/
464  GNUNET_break(0);
465  return;
466  }
467  GNUNET_log(
469  "Trying to increase socket buffer size from %u to %u for message size %u\n",
470  (unsigned int)size,
471  (unsigned int)((msg_size / 1000) + 2) * 1000,
472  (unsigned int)msg_size);
473  size = ((msg_size / 1000) + 2) * 1000;
475  SOL_SOCKET,
476  SO_SNDBUF,
477  &size,
478  sizeof(size)))
479  goto resend; /* Increased buffer size, retry sending */
480  /* Ok, then just try very modest increase */
481  size = msg_size;
483  SOL_SOCKET,
484  SO_SNDBUF,
485  &size,
486  sizeof(size)))
487  goto resend; /* Increased buffer size, retry sending */
488  /* Could not increase buffer size: error, no retry */
490  return;
491  }
492 
493  default:
495  return;
496  }
497 }
498 
499 
508 static void
510  const struct GNUNET_MessageHeader *msg,
511  void *impl_state)
512 {
513  struct Queue *queue = impl_state;
514 
515  GNUNET_assert(mq == queue->mq);
516  GNUNET_assert(NULL == queue->msg);
517  queue->msg = msg;
518  GNUNET_CONTAINER_DLL_insert(queue_head, queue_tail, queue);
519  GNUNET_assert(NULL != unix_sock);
520  if (NULL == write_task)
522  unix_sock,
524  NULL);
525 }
526 
527 
536 static void
537 mq_destroy(struct GNUNET_MQ_Handle *mq, void *impl_state)
538 {
539  struct Queue *queue = impl_state;
540 
541  if (mq == queue->mq)
542  {
543  queue->mq = NULL;
544  queue_destroy(queue);
545  }
546 }
547 
548 
555 static void
556 mq_cancel(struct GNUNET_MQ_Handle *mq, void *impl_state)
557 {
558  struct Queue *queue = impl_state;
559 
560  GNUNET_assert(NULL != queue->msg);
561  queue->msg = NULL;
562  GNUNET_CONTAINER_DLL_remove(queue_head, queue_tail, queue);
563  GNUNET_assert(NULL != write_task);
564  if (NULL == queue_head)
565  {
566  GNUNET_SCHEDULER_cancel(write_task);
567  write_task = NULL;
568  }
569 }
570 
571 
581 static void
582 mq_error(void *cls, enum GNUNET_MQ_Error error)
583 {
584  struct Queue *queue = cls;
585 
587  "UNIX MQ error in queue to %s: %d\n",
588  GNUNET_i2s(&queue->target),
589  (int)error);
590  queue_destroy(queue);
591 }
592 
593 
604 static struct Queue *
607  const struct sockaddr_un *un,
608  socklen_t un_len)
609 {
610  struct Queue *queue;
611 
612  queue = GNUNET_new(struct Queue);
613  queue->target = *target;
614  queue->address = GNUNET_memdup(un, un_len);
615  queue->address_len = un_len;
617  queue_map,
618  &queue->target,
619  queue,
621  GNUNET_STATISTICS_set(stats,
622  "# queues active",
624  GNUNET_NO);
625  queue->timeout =
627  queue->timeout_task =
629  &queue_timeout,
630  queue);
632  &mq_destroy,
633  &mq_cancel,
634  queue,
635  NULL,
636  &mq_error,
637  queue);
638  {
639  char *foreign_addr;
640 
641  if ('\0' == un->sun_path[0])
642  GNUNET_asprintf(&foreign_addr,
643  "%s-@%s",
645  &un->sun_path[1]);
646  else
647  GNUNET_asprintf(&foreign_addr,
648  "%s-%s",
650  un->sun_path);
652  &queue->target,
653  foreign_addr,
654  UNIX_MTU,
656  cs,
657  queue->mq);
658  GNUNET_free(foreign_addr);
659  }
660  return queue;
661 }
662 
663 
671 static void
672 select_read_cb(void *cls);
673 
674 
682 static void
683 receive_complete_cb(void *cls, int success)
684 {
685  (void)cls;
687  if (GNUNET_OK != success)
689  "# transport transmission failures",
690  1,
691  GNUNET_NO);
692  GNUNET_assert(NULL != unix_sock);
693  if ((NULL == read_task) && (delivering_messages < max_queue_length))
695  unix_sock,
697  NULL);
698 }
699 
700 
708 static void
709 select_read_cb(void *cls)
710 {
711  char buf[65536] GNUNET_ALIGN;
712  struct Queue *queue;
713  const struct UNIXMessage *msg;
714  struct sockaddr_un un;
715  socklen_t addrlen;
716  ssize_t ret;
717  uint16_t msize;
718 
719  GNUNET_assert(NULL != unix_sock);
721  unix_sock,
723  NULL);
724  addrlen = sizeof(un);
725  memset(&un, 0, sizeof(un));
726  ret = GNUNET_NETWORK_socket_recvfrom(unix_sock,
727  buf,
728  sizeof(buf),
729  (struct sockaddr *)&un,
730  &addrlen);
731  if ((-1 == ret) && ((EAGAIN == errno) || (ENOBUFS == errno)))
732  return;
733  if (-1 == ret)
734  {
736  return;
737  }
739  "Read %d bytes from socket %s\n",
740  (int)ret,
741  un.sun_path);
742  GNUNET_assert(AF_UNIX == (un.sun_family));
743  msg = (struct UNIXMessage *)buf;
744  msize = ntohs(msg->header.size);
745  if ((msize < sizeof(struct UNIXMessage)) || (msize > ret))
746  {
747  GNUNET_break_op(0);
748  return;
749  }
750  queue = lookup_queue(&msg->sender, &un, addrlen);
751  if (NULL == queue)
752  queue =
753  setup_queue(&msg->sender, GNUNET_TRANSPORT_CS_INBOUND, &un, addrlen);
754  else
756  if (NULL == queue)
757  {
758  GNUNET_log(
760  _(
761  "Maximum number of UNIX connections exceeded, dropping incoming message\n"));
762  return;
763  }
764 
765  {
766  uint16_t offset = 0;
767  uint16_t tsize = msize - sizeof(struct UNIXMessage);
768  const char *msgbuf = (const char *)&msg[1];
769 
770  while (offset + sizeof(struct GNUNET_MessageHeader) <= tsize)
771  {
772  const struct GNUNET_MessageHeader *currhdr;
773  struct GNUNET_MessageHeader al_hdr;
774  uint16_t csize;
775 
776  currhdr = (const struct GNUNET_MessageHeader *)&msgbuf[offset];
777  /* ensure aligned access */
778  memcpy(&al_hdr, currhdr, sizeof(al_hdr));
779  csize = ntohs(al_hdr.size);
780  if ((csize < sizeof(struct GNUNET_MessageHeader)) ||
781  (csize > tsize - offset))
782  {
783  GNUNET_break_op(0);
784  break;
785  }
787  &msg->sender,
788  currhdr,
791  NULL);
792  if (GNUNET_SYSERR == ret)
793  return; /* transport not up */
794  if (GNUNET_NO == ret)
795  break;
797  offset += csize;
798  }
799  }
801  {
802  /* we should try to apply 'back pressure' */
803  GNUNET_SCHEDULER_cancel(read_task);
804  read_task = NULL;
805  }
806 }
807 
808 
826 static int
827 mq_init(void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
828 {
829  struct Queue *queue;
830  const char *path;
831  struct sockaddr_un *un;
832  socklen_t un_len;
833 
834  (void)cls;
835  if (0 != strncmp(address,
837  strlen(COMMUNICATOR_ADDRESS_PREFIX "-")))
838  {
839  GNUNET_break_op(0);
840  return GNUNET_SYSERR;
841  }
842  path = &address[strlen(COMMUNICATOR_ADDRESS_PREFIX "-")];
843  un = unix_address_to_sockaddr(path, &un_len);
844  queue = lookup_queue(peer, un, un_len);
845  if (NULL != queue)
846  {
848  "Address `%s' for %s ignored, queue exists\n",
849  path,
850  GNUNET_i2s(peer));
851  GNUNET_free(un);
852  return GNUNET_OK;
853  }
854  queue = setup_queue(peer, GNUNET_TRANSPORT_CS_OUTBOUND, un, un_len);
855  GNUNET_free(un);
856  if (NULL == queue)
857  {
859  "Failed to setup queue to %s at `%s'\n",
860  GNUNET_i2s(peer),
861  path);
862  return GNUNET_NO;
863  }
864  return GNUNET_OK;
865 }
866 
867 
876 static int
878  const struct GNUNET_PeerIdentity *target,
879  void *value)
880 {
881  struct Queue *queue = value;
882 
883  (void)cls;
884  (void)target;
885  queue_destroy(queue);
886  return GNUNET_OK;
887 }
888 
889 
895 static void
896 do_shutdown(void *cls)
897 {
898  if (NULL != read_task)
899  {
900  GNUNET_SCHEDULER_cancel(read_task);
901  read_task = NULL;
902  }
903  if (NULL != write_task)
904  {
905  GNUNET_SCHEDULER_cancel(write_task);
906  write_task = NULL;
907  }
908  if (NULL != unix_sock)
909  {
911  unix_sock = NULL;
912  }
915  if (NULL != ai)
916  {
918  ai = NULL;
919  }
920  if (NULL != ch)
921  {
923  ch = NULL;
924  }
925  if (NULL != stats)
926  {
928  stats = NULL;
929  }
930 }
931 
932 
944 static void
945 enc_notify_cb(void *cls,
946  const struct GNUNET_PeerIdentity *sender,
947  const struct GNUNET_MessageHeader *msg)
948 {
949  (void)cls;
950  (void)sender;
951  (void)msg;
952  GNUNET_break_op(0);
953 }
954 
955 
964 static void
965 run(void *cls,
966  char *const *args,
967  const char *cfgfile,
968  const struct GNUNET_CONFIGURATION_Handle *cfg)
969 {
970  char *unix_socket_path;
971  struct sockaddr_un *un;
972  socklen_t un_len;
973  char *my_addr;
974 
975  (void)cls;
976 
977  if (GNUNET_OK !=
980  "UNIXPATH",
981  &unix_socket_path))
982  {
985  "UNIXPATH");
986  return;
987  }
988  if (GNUNET_OK !=
991  "MAX_QUEUE_LENGTH",
994 
995  un = unix_address_to_sockaddr(unix_socket_path, &un_len);
996  if (NULL == un)
997  {
999  "Failed to setup UNIX domain socket address with path `%s'\n",
1000  unix_socket_path);
1001  GNUNET_free(unix_socket_path);
1002  return;
1003  }
1004  unix_sock = GNUNET_NETWORK_socket_create(AF_UNIX, SOCK_DGRAM, 0);
1005  if (NULL == unix_sock)
1006  {
1008  GNUNET_free(un);
1009  GNUNET_free(unix_socket_path);
1010  return;
1011  }
1012  if (('\0' != un->sun_path[0]) &&
1014  {
1016  _("Cannot create path to `%s'\n"),
1017  un->sun_path);
1018  GNUNET_NETWORK_socket_close(unix_sock);
1019  unix_sock = NULL;
1020  GNUNET_free(un);
1021  GNUNET_free(unix_socket_path);
1022  return;
1023  }
1024  if (GNUNET_OK != GNUNET_NETWORK_socket_bind(unix_sock,
1025  (const struct sockaddr *)un,
1026  un_len))
1027  {
1028  GNUNET_log_strerror_file(GNUNET_ERROR_TYPE_ERROR, "bind", un->sun_path);
1029  GNUNET_NETWORK_socket_close(unix_sock);
1030  unix_sock = NULL;
1031  GNUNET_free(un);
1032  GNUNET_free(unix_socket_path);
1033  return;
1034  }
1035  GNUNET_free(un);
1036  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Bound to `%s'\n", unix_socket_path);
1037  stats = GNUNET_STATISTICS_create("C-UNIX", cfg);
1040  unix_sock,
1041  &select_read_cb,
1042  NULL);
1048  &mq_init,
1049  NULL,
1050  &enc_notify_cb,
1051  NULL);
1052  if (NULL == ch)
1053  {
1054  GNUNET_break(0);
1056  GNUNET_free(unix_socket_path);
1057  return;
1058  }
1059  GNUNET_asprintf(&my_addr,
1060  "%s-%s",
1062  unix_socket_path);
1063  GNUNET_free(unix_socket_path);
1065  my_addr,
1068  GNUNET_free(my_addr);
1069 }
1070 
1071 
1079 int
1080 main(int argc, char *const *argv)
1081 {
1082  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1084  };
1085  int ret;
1086 
1087  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args(argc, argv, &argc, &argv))
1088  return 2;
1089 
1090  ret = (GNUNET_OK ==
1091  GNUNET_PROGRAM_run(argc,
1092  argv,
1093  "gnunet-communicator-unix",
1094  _("GNUnet UNIX domain socket communicator"),
1095  options,
1096  &run,
1097  NULL))
1098  ? 0
1099  : 1;
1100  GNUNET_free((void *)argv);
1101  return ret;
1102 }
1103 
1104 
1105 #if defined(LINUX) && defined(__GLIBC__)
1106 #include <malloc.h>
1107 
1111 void __attribute__ ((constructor)) GNUNET_ARM_memory_init()
1112 {
1113  mallopt(M_TRIM_THRESHOLD, 4 * 1024);
1114  mallopt(M_TOP_PAD, 1 * 1024);
1115  malloc_trim(0);
1116 }
1117 #endif
1118 
1119 /* end of gnunet-communicator-unix.c */
static void mq_send(struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state)
Signature of functions implementing the sending functionality of a message queue. ...
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static void queue(const char *hostname)
Add hostname to the list of requests to be made.
int GNUNET_NETWORK_socket_setsockopt(struct GNUNET_NETWORK_Handle *fd, int level, int option_name, const void *option_value, socklen_t option_len)
Set socket option.
Definition: network.c:871
Transmission is reliabile (with ACKs), i.e.
static void do_shutdown(void *cls)
Shutdown the UNIX communicator.
static struct GNUNET_SCHEDULER_Task * read_task
ID of read task.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_PeerIdentity target
To whom are we talking to.
static int lookup_queue_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Function called to find a queue by address.
socklen_t un_len
Number of bytes in un.
static void queue_destroy(struct Queue *queue)
Functions with this signature are called whenever we need to close a queue due to a disconnect or fai...
int GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
uint64_t rel_value_us
The actual value.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
socklen_t address_len
Length of the address.
static struct GNUNET_TRANSPORT_CommunicatorHandle * ch
Our environment.
struct GNUNET_TRANSPORT_AddressIdentifier * GNUNET_TRANSPORT_communicator_address_add(struct GNUNET_TRANSPORT_CommunicatorHandle *ch, const char *address, enum GNUNET_NetworkType nt, struct GNUNET_TIME_Relative expiration)
Notify transport service about an address that this communicator provides for this peer...
static int get_queue_delete_it(void *cls, const struct GNUNET_PeerIdentity *target, void *value)
Iterator over all message queues to clean up.
GNUNET_MQ_Error
Error codes for the queue.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1284
#define COMMUNICATOR_CONFIG_SECTION
Configuration section used by the communicator.
static int mq_init(void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
Function called by the transport service to initialize a message queue given address information abou...
struct GNUNET_MessageHeader header
Message header.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
int GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1439
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:246
static struct GNUNET_SCHEDULER_Task * write_task
ID of write task.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
int main(int argc, char *const *argv)
The main function for the UNIX communicator.
int GNUNET_NETWORK_socket_getsockopt(const struct GNUNET_NETWORK_Handle *desc, int level, int optname, void *optval, socklen_t *optlen)
Get socket options.
Definition: network.c:671
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
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
Setup communicator and launch network interactions.
Closure to lookup_queue_it().
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1537
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:681
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_new(type)
Allocate a struct or union of the given type.
Definition of a command line option.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:517
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
static int ret
Final status code.
Definition: gnunet-arm.c:89
Handle for the service.
static void reschedule_queue_timeout(struct Queue *queue)
Increment queue timeout due to activity.
struct GNUNET_MQ_Handle * mq
Message queue we are providing for the ch.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_SCHEDULER_Task * timeout_task
Queue timeout task.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
Opaque handle to the transport service for communicators.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
void GNUNET_TRANSPORT_communicator_disconnect(struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
Disconnect from the transport service.
#define UNIX_MTU
Our MTU.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
static void enc_notify_cb(void *cls, const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg)
Function called when the transport service has received an acknowledgement for this communicator (!) ...
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
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
#define COMMUNICATOR_ADDRESS_PREFIX
Address prefix used by the communicator.
unsigned long long bytes_in_queue
Number of bytes we currently have in our write queue.
UNIX Message-Packet header.
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition: gnunet-arm.c:114
struct GNUNET_MQ_Handle * GNUNET_MQ_queue_for_callbacks(GNUNET_MQ_SendImpl send, GNUNET_MQ_DestroyImpl destroy, GNUNET_MQ_CancelImpl cancel, void *impl_state, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *cls)
Create a message queue for the specified handlers.
Definition: mq.c:550
static unsigned int csize
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
static char * value
Value of the record to add/remove.
static struct Queue * queue_head
Head of queue of messages to transmit.
static struct GNUNET_STATISTICS_Handle * stats
For logging statistics.
Handle for a queue.
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
static unsigned long long max_queue_length
Maximum queue length before we stop reading towards the transport service.
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
static void select_read_cb(void *cls)
We have been notified that our socket has something to read.
ssize_t GNUNET_NETWORK_socket_sendto(const struct GNUNET_NETWORK_Handle *desc, const void *message, size_t length, const struct sockaddr *dest_addr, socklen_t dest_len)
Send data to a particular destination (always non-blocking).
Definition: network.c:838
struct sockaddr_un * address
Address of the other peer.
static char buf[2048]
struct GNUNET_TRANSPORT_CommunicatorHandle * GNUNET_TRANSPORT_communicator_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section_name, const char *addr_prefix, enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc, GNUNET_TRANSPORT_CommunicatorMqInit mq_init, void *mq_init_cls, GNUNET_TRANSPORT_CommunicatorNotify notify_cb, void *notify_cb_cls)
Connect to the transport service.
this is an inbound connection (communicator initiated)
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
static void select_write_cb(void *cls)
We have been notified that our socket is ready to write.
Internal representation of the hash map.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
static void mq_destroy(struct GNUNET_MQ_Handle *mq, void *impl_state)
Signature of functions implementing the destruction of a message queue.
const struct sockaddr_un * un
Address we are looking for.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
void GNUNET_TRANSPORT_communicator_address_remove(struct GNUNET_TRANSPORT_AddressIdentifier *ai)
Notify transport service about an address that this communicator no longer provides for this peer...
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
struct GNUNET_HashCode key
The key used in the DHT.
static void mq_cancel(struct GNUNET_MQ_Handle *mq, void *impl_state)
Implementation function that cancels the currently sent message.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static unsigned int size
Size of the "table".
Definition: peer.c:66
static struct GNUNET_TRANSPORT_AddressIdentifier * ai
Handle to the operation that publishes our address.
static struct sockaddr_un * unix_address_to_sockaddr(const char *unixpath, socklen_t *sock_len)
Convert unix path to a struct sockaddr_un *
Loopback (same host).
Definition: gnunet_nt_lib.h:44
const struct GNUNET_MessageHeader * msg
Message currently scheduled for transmission, non-NULL if and only if this queue is in the queue_head...
static void queue_timeout(void *cls)
Queue was idle for too long, so disconnect it.
int GNUNET_TRANSPORT_communicator_receive(struct GNUNET_TRANSPORT_CommunicatorHandle *handle, const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg, struct GNUNET_TIME_Relative expected_addr_validity, GNUNET_TRANSPORT_MessageCompletedCallback cb, void *cb_cls)
Notify transport service that the communicator has received a message.
Allow multiple values with the same key.
#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
After how long do we consider a connection to a peer dead if we don&#39;t receive messages from the peer...
Handle to a message queue.
Definition: mq.c:84
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32;.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
static struct Queue * setup_queue(const struct GNUNET_PeerIdentity *target, enum GNUNET_TRANSPORT_ConnectionStatus cs, const struct sockaddr_un *un, socklen_t un_len)
Creates a new outbound queue the transport service will use to send data to another peer...
enum RadiotapType __attribute__
The identity of the host (wraps the signing key of the peer).
struct sockaddr * address
Address of the other peer.
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to &#39;struct&#39;s...
static struct GNUNET_CONTAINER_MultiPeerMap * queue_map
Queues (map from peer identity to struct Queue)
configuration data
Definition: configuration.c:83
struct Queue * prev
Queues with pending messages (!) are kept in a DLL.
this is an outbound connection (transport initiated)
static struct GNUNET_NETWORK_Handle * unix_sock
socket that we transmit all data with
enum GNUNET_TRANSPORT_ConnectionStatus cs
Connection status for this queue.
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:131
struct Queue * res
Location to store the queue, if found.
int GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
handle to a socket
Definition: network.c:46
int GNUNET_PROGRAM_run(int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration, parse options).
Definition: program.c:367
static void mq_error(void *cls, enum GNUNET_MQ_Error error)
Generic error handler, called with the appropriate error code and the same closure specified at the c...
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
Header for all communications.
Time for absolute times used by GNUnet, in microseconds.
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:821
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1467
struct GNUNET_TRANSPORT_QueueHandle * GNUNET_TRANSPORT_communicator_mq_add(struct GNUNET_TRANSPORT_CommunicatorHandle *ch, const struct GNUNET_PeerIdentity *peer, const char *address, uint32_t mtu, enum GNUNET_NetworkType nt, enum GNUNET_TRANSPORT_ConnectionStatus cs, struct GNUNET_MQ_Handle *mq)
Notify transport service that a MQ became available due to an "inbound" connection or because the com...
GNUNET_TRANSPORT_ConnectionStatus
Possible states of a connection.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
struct GNUNET_TIME_Absolute timeout
Timeout for this queue.
static struct Queue * queue_tail
Tail of queue of messages to transmit.
ssize_t GNUNET_NETWORK_socket_recvfrom(const struct GNUNET_NETWORK_Handle *desc, void *buffer, size_t length, struct sockaddr *src_addr, socklen_t *addrlen)
Read data from a socket (always non-blocking).
Definition: network.c:742
struct GNUNET_PeerIdentity sender
What is the identity of the sender (GNUNET_hash of public key)
struct GNUNET_TRANSPORT_QueueHandle * qh
handle for this queue with the ch.
struct Queue * next
Queues with pending messages (!) are kept in a DLL.
static char * address
GNS address for this phone.
void GNUNET_MQ_impl_send_continue(struct GNUNET_MQ_Handle *mq)
Call the send implementation for the next queued message, if any.
Definition: mq.c:484
#define DEFAULT_MAX_QUEUE_LENGTH
How many messages do we keep at most in the queue to the transport service before we start to drop (d...
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
Handle returned to identify the internal data structure the transport API has created to manage a mes...
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:548
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
static void receive_complete_cb(void *cls, int success)
Function called when message was successfully passed to transport service.
static unsigned long long delivering_messages
Number of messages we currently have in our queues towards the transport service. ...
static struct Queue * lookup_queue(const struct GNUNET_PeerIdentity *peer, const struct sockaddr_un *un, socklen_t un_len)
Find an existing queue by address.
Internal representation of an address a communicator is currently providing for the transport service...
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
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