GNUnet  0.19.4
plugin_transport_unix.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2010-2014 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_hello_lib.h"
32 #include "gnunet_protocols.h"
36 #include "transport.h"
37 
38 
44 #define RETRY 0
45 
49 #define PLUGIN_NAME "unix"
50 
55 {
60 
65 };
66 
67 
71 #define HOSTNAME_RESOLVE_TIMEOUT \
72  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
73 
74 #define LOG(kind, ...) GNUNET_log_from (kind, "transport-unix", __VA_ARGS__)
75 
76 
78 
83 {
88 
93 
94  /* followed by actual path */
95 };
96 
97 
101 struct UNIXMessage
102 {
107 
112 };
113 
115 
116 
121 {
126 
131 
135  struct UNIXMessage *msg;
136 
141 
146 
150  void *cont_cls;
151 
156 
160  size_t msgsize;
161 
165  size_t payload;
166 
170  unsigned int priority;
171 };
172 
173 
177 struct GNUNET_ATS_Session
178 {
182  struct GNUNET_ATS_Session *next;
183 
187  struct GNUNET_ATS_Session *prev;
188 
196 
200  struct Plugin *plugin;
201 
206 
210  unsigned long long bytes_in_queue;
211 
216 
221 
225  unsigned int msgs_in_queue;
226 };
227 
228 
232 struct Plugin;
233 
234 
239 {
244 };
245 
246 
250 struct Plugin
251 {
256 
261 
266 
270  unsigned long long bytes_in_queue;
271 
276 
281 
286 
291 
296 
301 
305  void *sic_cls;
306 
310  struct UNIX_Sock_Info unix_sock;
311 
315  uint32_t myoptions;
316 
321 };
322 
323 
332 static void
334  struct GNUNET_ATS_Session *session,
336 {
338 
339  if (NULL == plugin->sic)
340  return;
341  memset (&info, 0, sizeof(info));
342  info.state = state;
343  info.is_inbound = GNUNET_SYSERR; /* hard to say */
344  info.num_msg_pending = session->msgs_in_queue;
345  info.num_bytes_pending = session->bytes_in_queue;
346  /* info.receive_delay remains zero as this is not supported by UNIX
347  (cannot selectively not receive from 'some' peer while continuing
348  to receive from others) */
349  info.session_timeout = session->timeout;
350  info.address = session->address;
351  plugin->sic (plugin->sic_cls, session, &info);
352 }
353 
354 
366 static const char *
367 unix_plugin_address_to_string (void *cls, const void *addr, size_t addrlen)
368 {
369  static char rbuf[1024];
370  struct UnixAddress *ua = (struct UnixAddress *) addr;
371  char *addrstr;
372  size_t addr_str_len;
373  unsigned int off;
374 
375  if ((NULL == addr) || (sizeof(struct UnixAddress) > addrlen))
376  {
377  GNUNET_break (0);
378  return NULL;
379  }
380  addrstr = (char *) &ua[1];
381  addr_str_len = ntohl (ua->addrlen);
382 
383  if (addr_str_len != addrlen - sizeof(struct UnixAddress))
384  {
385  GNUNET_break (0);
386  return NULL;
387  }
388  if ('\0' != addrstr[addr_str_len - 1])
389  {
390  GNUNET_break (0);
391  return NULL;
392  }
393  if (strlen (addrstr) + 1 != addr_str_len)
394  {
395  GNUNET_break (0);
396  return NULL;
397  }
398 
399  off = 0;
400  if ('\0' == addrstr[0])
401  off++;
402  memset (rbuf, 0, sizeof(rbuf));
403  GNUNET_snprintf (rbuf,
404  sizeof(rbuf) - 1,
405  "%s.%u.%s%.*s",
406  PLUGIN_NAME,
407  ntohl (ua->options),
408  (off == 1) ? "@" : "",
409  (int) (addr_str_len - off),
410  &addrstr[off]);
411  return rbuf;
412 }
413 
414 
424 static int
426 {
427  struct Plugin *plugin = cls;
428  struct UNIXMessageWrapper *msgw;
429  struct UNIXMessageWrapper *next;
430 
432  "Disconnecting session for peer `%s' `%s'\n",
437  plugin->env->session_end (plugin->env->cls, session->address, session);
438  next = plugin->msg_head;
439  while (NULL != next)
440  {
441  msgw = next;
442  next = msgw->next;
443  if (msgw->session != session)
444  continue;
445  GNUNET_CONTAINER_DLL_remove (plugin->msg_head, plugin->msg_tail, msgw);
448  session->bytes_in_queue -= msgw->msgsize;
449  GNUNET_assert (plugin->bytes_in_queue >= msgw->msgsize);
450  plugin->bytes_in_queue -= msgw->msgsize;
451  if (NULL != msgw->cont)
452  msgw->cont (msgw->cont_cls,
453  &msgw->session->target,
455  msgw->payload,
456  0);
457  GNUNET_free (msgw->msg);
458  GNUNET_free (msgw);
459  }
462  &session->target,
463  session));
464  GNUNET_STATISTICS_set (plugin->env->stats,
465  "# UNIX sessions active",
467  plugin->session_map),
468  GNUNET_NO);
469  if (NULL != session->timeout_task)
470  {
472  session->timeout_task = NULL;
474  }
480  return GNUNET_OK;
481 }
482 
483 
489 static void
490 session_timeout (void *cls)
491 {
492  struct GNUNET_ATS_Session *session = cls;
493  struct GNUNET_TIME_Relative left;
494 
495  session->timeout_task = NULL;
497  if (0 != left.rel_value_us)
498  {
499  /* not actually our turn yet, but let's at least update
500  the monitor, it may think we're about to die ... */
501  notify_session_monitor (session->plugin,
502  session,
504  session->timeout_task =
506  return;
507  }
509  "Session %p was idle for %s, disconnecting\n",
510  session,
513  GNUNET_YES));
514  unix_plugin_session_disconnect (session->plugin, session);
515 }
516 
517 
525 static void
527 {
528  GNUNET_assert (NULL != session->timeout_task);
529  session->timeout =
531 }
532 
533 
541 static struct sockaddr_un *
542 unix_address_to_sockaddr (const char *unixpath, socklen_t *sock_len)
543 {
544  struct sockaddr_un *un;
545  size_t slen;
546 
547  GNUNET_assert (0 < strlen (unixpath)); /* sanity check */
548  un = GNUNET_new (struct sockaddr_un);
549  un->sun_family = AF_UNIX;
550  slen = strlen (unixpath);
551  if (slen >= sizeof(un->sun_path))
552  slen = sizeof(un->sun_path) - 1;
553  GNUNET_memcpy (un->sun_path, unixpath, slen);
554  un->sun_path[slen] = '\0';
555  slen = sizeof(struct sockaddr_un);
556 #if HAVE_SOCKADDR_UN_SUN_LEN
557  un->sun_len = (u_char) slen;
558 #endif
559  (*sock_len) = slen;
560  return un;
561 }
562 
563 
567 struct LookupCtx
568 {
573 
578 };
579 
580 
589 static int
590 lookup_session_it (void *cls,
591  const struct GNUNET_PeerIdentity *key,
592  void *value)
593 {
594  struct LookupCtx *lctx = cls;
595  struct GNUNET_ATS_Session *session = value;
596 
597  if (0 == GNUNET_HELLO_address_cmp (lctx->address, session->address))
598  {
599  lctx->res = session;
600  return GNUNET_NO;
601  }
602  return GNUNET_YES;
603 }
604 
605 
613 static struct GNUNET_ATS_Session *
615  const struct GNUNET_HELLO_Address *address)
616 {
617  struct LookupCtx lctx;
618 
619  lctx.address = address;
620  lctx.res = NULL;
622  &address->peer,
624  &lctx);
625  return lctx.res;
626 }
627 
628 
637 static unsigned int
639 {
640  return 3;
641 }
642 
643 
665 static ssize_t
666 unix_real_send (void *cls,
667  struct GNUNET_NETWORK_Handle *send_handle,
668  const struct GNUNET_PeerIdentity *target,
669  const char *msgbuf,
670  size_t msgbuf_size,
671  unsigned int priority,
673  const struct UnixAddress *addr,
674  size_t addrlen,
675  size_t payload,
677  void *cont_cls)
678 {
679  struct Plugin *plugin = cls;
680  ssize_t sent;
681  struct sockaddr_un *un;
682  socklen_t un_len;
683  const char *unixpath;
684 
685  if (NULL == send_handle)
686  {
687  GNUNET_break (0); /* We do not have a send handle */
688  return GNUNET_SYSERR;
689  }
690  if ((NULL == addr) || (0 == addrlen))
691  {
692  GNUNET_break (0); /* Can never send if we don't have an address */
693  return GNUNET_SYSERR;
694  }
695 
696  /* Prepare address */
697  unixpath = (const char *) &addr[1];
698  if (NULL == (un = unix_address_to_sockaddr (unixpath, &un_len)))
699  {
700  GNUNET_break (0);
701  return -1;
702  }
703 
704  if ((GNUNET_YES == plugin->is_abstract) &&
705  (0 != (UNIX_OPTIONS_USE_ABSTRACT_SOCKETS & ntohl (addr->options))))
706  {
707  un->sun_path[0] = '\0';
708  }
709 resend:
710  /* Send the data */
711  sent = GNUNET_NETWORK_socket_sendto (send_handle,
712  msgbuf,
713  msgbuf_size,
714  (const struct sockaddr *) un,
715  un_len);
716  if (GNUNET_SYSERR == sent)
717  {
718  if ((EAGAIN == errno) || (ENOBUFS == errno))
719  {
720  GNUNET_free (un);
721  return RETRY; /* We have to retry later */
722  }
723  if (EMSGSIZE == errno)
724  {
725  socklen_t size = 0;
726  socklen_t len = sizeof(size);
727 
729  send_handle,
730  SOL_SOCKET,
731  SO_SNDBUF,
732  &size,
733  &len);
734  if (size < msgbuf_size)
735  {
737  "Trying to increase socket buffer size from %u to %u for message size %u\n",
738  (unsigned int) size,
739  (unsigned int) ((msgbuf_size / 1000) + 2) * 1000,
740  (unsigned int) msgbuf_size);
741  size = ((msgbuf_size / 1000) + 2) * 1000;
742  if (GNUNET_OK ==
744  send_handle,
745  SOL_SOCKET,
746  SO_SNDBUF,
747  &size,
748  sizeof(size)))
749  goto resend; /* Increased buffer size, retry sending */
750  else
751  {
752  /* Could not increase buffer size: error, no retry */
754  GNUNET_free (un);
755  return GNUNET_SYSERR;
756  }
757  }
758  else
759  {
760  /* Buffer is bigger than message: error, no retry
761  * This should never happen!*/
762  GNUNET_break (0);
763  GNUNET_free (un);
764  return GNUNET_SYSERR;
765  }
766  }
767  }
768 
770  "UNIX transmitted %u-byte message to %s (%d: %s)\n",
771  (unsigned int) msgbuf_size,
772  GNUNET_a2s ((const struct sockaddr *) un, un_len),
773  (int) sent,
774  (sent < 0) ? strerror (errno) : "ok");
775  GNUNET_free (un);
776  return sent;
777 }
778 
779 
787 static enum GNUNET_NetworkType
788 unix_plugin_get_network (void *cls, struct GNUNET_ATS_Session *session)
789 {
790  GNUNET_assert (NULL != session);
791  return GNUNET_NT_LOOPBACK;
792 }
793 
794 
802 static enum GNUNET_NetworkType
804  const struct GNUNET_HELLO_Address *address)
805 {
806  return GNUNET_NT_LOOPBACK;
807 }
808 
809 
818 static struct GNUNET_ATS_Session *
820 {
821  struct Plugin *plugin = cls;
822  struct GNUNET_ATS_Session *session;
823  struct UnixAddress *ua;
824  char *addrstr;
825  uint32_t addr_str_len;
826  uint32_t addr_option;
827 
828  ua = (struct UnixAddress *) address->address;
829  if ((NULL == address->address) || (0 == address->address_length) ||
830  (sizeof(struct UnixAddress) > address->address_length))
831  {
832  GNUNET_break (0);
833  return NULL;
834  }
835  addrstr = (char *) &ua[1];
836  addr_str_len = ntohl (ua->addrlen);
837  addr_option = ntohl (ua->options);
838 
839  if ((0 != (UNIX_OPTIONS_USE_ABSTRACT_SOCKETS & addr_option)) &&
840  (GNUNET_NO == plugin->is_abstract))
841  {
842  return NULL;
843  }
844 
845  if (addr_str_len != address->address_length - sizeof(struct UnixAddress))
846  {
847  return NULL; /* This can be a legacy address */
848  }
849 
850  if ('\0' != addrstr[addr_str_len - 1])
851  {
852  GNUNET_break (0);
853  return NULL;
854  }
855  if (strlen (addrstr) + 1 != addr_str_len)
856  {
857  GNUNET_break (0);
858  return NULL;
859  }
860 
861  /* Check if a session for this address already exists */
862  if (NULL != (session = lookup_session (plugin, address)))
863  {
865  "Found existing session %p for address `%s'\n",
866  session,
868  address->address,
869  address->address_length));
870  return session;
871  }
872 
873  /* create a new session */
874  session = GNUNET_new (struct GNUNET_ATS_Session);
875  session->target = address->peer;
877  session->plugin = plugin;
878  session->timeout =
880  session->timeout_task =
883  session);
885  "Creating a new session %p for address `%s'\n",
886  session,
888  address->address,
889  address->address_length));
891  plugin->session_map,
892  &address->peer,
893  session,
895  GNUNET_STATISTICS_set (plugin->env->stats,
896  "# UNIX sessions active",
898  plugin->session_map),
899  GNUNET_NO);
902  return session;
903 }
904 
905 
915 static void
917  const struct GNUNET_PeerIdentity *peer,
918  struct GNUNET_ATS_Session *session)
919 {
920  struct Plugin *plugin = cls;
921 
922  if (GNUNET_OK !=
924  &session->target,
925  session))
926  {
927  GNUNET_break (0);
928  return;
929  }
930  reschedule_session_timeout (session);
931 }
932 
933 
943 static void
945  struct GNUNET_PeerIdentity *sender,
946  const struct GNUNET_MessageHeader *currhdr,
947  const struct UnixAddress *ua,
948  size_t ua_len)
949 {
950  struct GNUNET_ATS_Session *session;
952 
953  GNUNET_assert (ua_len >= sizeof(struct UnixAddress));
955  "Received message from %s\n",
956  unix_plugin_address_to_string (NULL, ua, ua_len));
957  GNUNET_STATISTICS_update (plugin->env->stats,
958  "# bytes received via UNIX",
959  ntohs (currhdr->size),
960  GNUNET_NO);
961 
962  /* Look for existing session */
964  sender,
965  PLUGIN_NAME,
966  ua,
967  ua_len,
968  GNUNET_HELLO_ADDRESS_INFO_NONE); /* UNIX does not have "inbound" sessions */
969  session = lookup_session (plugin, address);
970  if (NULL == session)
971  {
973  /* Notify transport and ATS about new inbound session */
974  plugin->env->session_start (NULL,
975  session->address,
976  session,
978  }
979  else
980  {
981  reschedule_session_timeout (session);
982  }
984  plugin->env->receive (plugin->env->cls, session->address, session, currhdr);
985 }
986 
987 
993 static void
995 {
996  char buf[65536] GNUNET_ALIGN;
997  struct UnixAddress *ua;
998  struct UNIXMessage *msg;
999  struct GNUNET_PeerIdentity sender;
1000  struct sockaddr_un un;
1001  socklen_t addrlen;
1002  ssize_t ret;
1003  int offset;
1004  int tsize;
1005  int is_abstract;
1006  char *msgbuf;
1007  const struct GNUNET_MessageHeader *currhdr;
1008  uint16_t csize;
1009  size_t ua_len;
1010 
1011  addrlen = sizeof(un);
1012  memset (&un, 0, sizeof(un));
1013  ret = GNUNET_NETWORK_socket_recvfrom (plugin->unix_sock.desc,
1014  buf,
1015  sizeof(buf),
1016  (struct sockaddr *) &un,
1017  &addrlen);
1018  if ((GNUNET_SYSERR == ret) && ((errno == EAGAIN) || (errno == ENOBUFS)))
1019  return;
1020  if (GNUNET_SYSERR == ret)
1021  {
1023  return;
1024  }
1025  else
1026  {
1028  "Read %d bytes from socket %s\n",
1029  (int) ret,
1030  un.sun_path);
1031  }
1032 
1033  GNUNET_assert (AF_UNIX == (un.sun_family));
1034  is_abstract = GNUNET_NO;
1035  if ('\0' == un.sun_path[0])
1036  {
1037  un.sun_path[0] = '@';
1038  is_abstract = GNUNET_YES;
1039  }
1040 
1041  ua_len = sizeof(struct UnixAddress) + strlen (un.sun_path) + 1;
1042  ua = GNUNET_malloc (ua_len);
1043  ua->addrlen = htonl (strlen (&un.sun_path[0]) + 1);
1044  GNUNET_memcpy (&ua[1], &un.sun_path[0], strlen (un.sun_path) + 1);
1045  if (is_abstract)
1047  else
1048  ua->options = htonl (UNIX_OPTIONS_NONE);
1049 
1050  msg = (struct UNIXMessage *) buf;
1051  csize = ntohs (msg->header.size);
1052  if ((csize < sizeof(struct UNIXMessage)) || (csize > ret))
1053  {
1054  GNUNET_break_op (0);
1055  GNUNET_free (ua);
1056  return;
1057  }
1058  msgbuf = (char *) &msg[1];
1059  GNUNET_memcpy (&sender, &msg->sender, sizeof(struct GNUNET_PeerIdentity));
1060  offset = 0;
1061  tsize = csize - sizeof(struct UNIXMessage);
1062  while (offset + sizeof(struct GNUNET_MessageHeader) <= tsize)
1063  {
1064  currhdr = (struct GNUNET_MessageHeader *) &msgbuf[offset];
1065  csize = ntohs (currhdr->size);
1066  if ((csize < sizeof(struct GNUNET_MessageHeader)) ||
1067  (csize > tsize - offset))
1068  {
1069  GNUNET_break_op (0);
1070  break;
1071  }
1072  unix_demultiplexer (plugin, &sender, currhdr, ua, ua_len);
1073  offset += csize;
1074  }
1075  GNUNET_free (ua);
1076 }
1077 
1078 
1084 static void
1086 {
1087  ssize_t sent = 0;
1088  struct UNIXMessageWrapper *msgw;
1089  struct GNUNET_ATS_Session *session;
1090  int did_delete;
1091 
1092  session = NULL;
1093  did_delete = GNUNET_NO;
1094  while (NULL != (msgw = plugin->msg_head))
1095  {
1097  break; /* Message is ready for sending */
1098  /* Message has a timeout */
1099  did_delete = GNUNET_YES;
1101  "Timeout for message with %u bytes \n",
1102  (unsigned int) msgw->msgsize);
1103  GNUNET_CONTAINER_DLL_remove (plugin->msg_head, plugin->msg_tail, msgw);
1104  session = msgw->session;
1105  session->msgs_in_queue--;
1106  GNUNET_assert (session->bytes_in_queue >= msgw->msgsize);
1107  session->bytes_in_queue -= msgw->msgsize;
1108  GNUNET_assert (plugin->bytes_in_queue >= msgw->msgsize);
1109  plugin->bytes_in_queue -= msgw->msgsize;
1110  GNUNET_STATISTICS_set (plugin->env->stats,
1111  "# bytes currently in UNIX buffers",
1112  plugin->bytes_in_queue,
1113  GNUNET_NO);
1114  GNUNET_STATISTICS_update (plugin->env->stats,
1115  "# UNIX bytes discarded",
1116  msgw->msgsize,
1117  GNUNET_NO);
1118  if (NULL != msgw->cont)
1119  msgw->cont (msgw->cont_cls,
1120  &msgw->session->target,
1121  GNUNET_SYSERR,
1122  msgw->payload,
1123  0);
1124  GNUNET_free (msgw->msg);
1125  GNUNET_free (msgw);
1126  }
1127  if (NULL == msgw)
1128  {
1129  if (GNUNET_YES == did_delete)
1131  return; /* Nothing to send at the moment */
1132  }
1133  session = msgw->session;
1134  sent = unix_real_send (plugin,
1135  plugin->unix_sock.desc,
1136  &session->target,
1137  (const char *) msgw->msg,
1138  msgw->msgsize,
1139  msgw->priority,
1140  msgw->timeout,
1141  msgw->session->address->address,
1142  msgw->session->address->address_length,
1143  msgw->payload,
1144  msgw->cont,
1145  msgw->cont_cls);
1146  if (RETRY == sent)
1147  {
1148  GNUNET_STATISTICS_update (plugin->env->stats,
1149  "# UNIX retry attempts",
1150  1,
1151  GNUNET_NO);
1153  return;
1154  }
1155  GNUNET_CONTAINER_DLL_remove (plugin->msg_head, plugin->msg_tail, msgw);
1156  session->msgs_in_queue--;
1157  GNUNET_assert (session->bytes_in_queue >= msgw->msgsize);
1158  session->bytes_in_queue -= msgw->msgsize;
1159  GNUNET_assert (plugin->bytes_in_queue >= msgw->msgsize);
1160  plugin->bytes_in_queue -= msgw->msgsize;
1161  GNUNET_STATISTICS_set (plugin->env->stats,
1162  "# bytes currently in UNIX buffers",
1163  plugin->bytes_in_queue,
1164  GNUNET_NO);
1166  if (GNUNET_SYSERR == sent)
1167  {
1168  /* failed and no retry */
1169  if (NULL != msgw->cont)
1170  msgw->cont (msgw->cont_cls,
1171  &msgw->session->target,
1172  GNUNET_SYSERR,
1173  msgw->payload,
1174  0);
1175  GNUNET_STATISTICS_update (plugin->env->stats,
1176  "# UNIX bytes discarded",
1177  msgw->msgsize,
1178  GNUNET_NO);
1179  GNUNET_free (msgw->msg);
1180  GNUNET_free (msgw);
1181  return;
1182  }
1183  /* successfully sent bytes */
1184  GNUNET_break (sent > 0);
1185  GNUNET_STATISTICS_update (plugin->env->stats,
1186  "# bytes transmitted via UNIX",
1187  msgw->msgsize,
1188  GNUNET_NO);
1189  if (NULL != msgw->cont)
1190  msgw->cont (msgw->cont_cls,
1191  &msgw->session->target,
1192  GNUNET_OK,
1193  msgw->payload,
1194  msgw->msgsize);
1195  GNUNET_free (msgw->msg);
1196  GNUNET_free (msgw);
1197 }
1198 
1199 
1206 static void
1208 {
1209  struct Plugin *plugin = cls;
1210  const struct GNUNET_SCHEDULER_TaskContext *tc;
1211 
1212  plugin->read_task = NULL;
1216  plugin->read_task =
1218  plugin->unix_sock.desc,
1220  plugin);
1221 }
1222 
1223 
1230 static void
1232 {
1233  struct Plugin *plugin = cls;
1234  const struct GNUNET_SCHEDULER_TaskContext *tc;
1235 
1236  plugin->write_task = NULL;
1240  if (NULL == plugin->msg_head)
1241  return; /* write queue empty */
1242  plugin->write_task =
1244  plugin->unix_sock.desc,
1246  plugin);
1247 }
1248 
1249 
1277 static ssize_t
1278 unix_plugin_send (void *cls,
1279  struct GNUNET_ATS_Session *session,
1280  const char *msgbuf,
1281  size_t msgbuf_size,
1282  unsigned int priority,
1283  struct GNUNET_TIME_Relative to,
1285  void *cont_cls)
1286 {
1287  struct Plugin *plugin = cls;
1288  struct UNIXMessageWrapper *wrapper;
1289  struct UNIXMessage *message;
1290  int ssize;
1291 
1292  if (GNUNET_OK !=
1294  &session->target,
1295  session))
1296  {
1298  "Invalid session for peer `%s' `%s'\n",
1299  GNUNET_i2s (&session->target),
1301  session->address->address,
1302  session->address->address_length));
1303  GNUNET_break (0);
1304  return GNUNET_SYSERR;
1305  }
1307  "Sending %lu bytes with session for peer `%s' `%s'\n",
1308  (unsigned long) msgbuf_size,
1309  GNUNET_i2s (&session->target),
1311  session->address->address,
1312  session->address->address_length));
1313  ssize = sizeof(struct UNIXMessage) + msgbuf_size;
1314  message = GNUNET_malloc (sizeof(struct UNIXMessage) + msgbuf_size);
1315  message->header.size = htons (ssize);
1316  message->header.type = htons (0);
1317  GNUNET_memcpy (&message->sender,
1318  plugin->env->my_identity,
1319  sizeof(struct GNUNET_PeerIdentity));
1320  GNUNET_memcpy (&message[1], msgbuf, msgbuf_size);
1321  wrapper = GNUNET_new (struct UNIXMessageWrapper);
1322  wrapper->msg = message;
1323  wrapper->msgsize = ssize;
1324  wrapper->payload = msgbuf_size;
1325  wrapper->priority = priority;
1327  wrapper->cont = cont;
1328  wrapper->cont_cls = cont_cls;
1329  wrapper->session = session;
1331  plugin->msg_tail,
1332  wrapper);
1333  plugin->bytes_in_queue += ssize;
1334  session->bytes_in_queue += ssize;
1335  session->msgs_in_queue++;
1336  GNUNET_STATISTICS_set (plugin->env->stats,
1337  "# bytes currently in UNIX buffers",
1338  plugin->bytes_in_queue,
1339  GNUNET_NO);
1341  if (NULL == plugin->write_task)
1342  plugin->write_task =
1344  plugin->unix_sock.desc,
1346  plugin);
1347  return ssize;
1348 }
1349 
1350 
1357 static int
1359 {
1360  struct Plugin *plugin = cls;
1361  struct sockaddr_un *un;
1362  socklen_t un_len;
1363 
1364  un = unix_address_to_sockaddr (plugin->unix_socket_path, &un_len);
1365  if (GNUNET_YES == plugin->is_abstract)
1366  {
1367  plugin->unix_socket_path[0] = '@';
1368  un->sun_path[0] = '\0';
1369  }
1370  plugin->unix_sock.desc =
1371  GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_DGRAM, 0);
1372  if (NULL == plugin->unix_sock.desc)
1373  {
1375  GNUNET_free (un);
1376  return GNUNET_SYSERR;
1377  }
1378  if ('\0' != un->sun_path[0])
1379  {
1380  if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (un->sun_path))
1381  {
1383  _ ("Cannot create path to `%s'\n"),
1384  un->sun_path);
1385  GNUNET_NETWORK_socket_close (plugin->unix_sock.desc);
1386  plugin->unix_sock.desc = NULL;
1387  GNUNET_free (un);
1388  return GNUNET_SYSERR;
1389  }
1390  }
1391  if (GNUNET_OK != GNUNET_NETWORK_socket_bind (plugin->unix_sock.desc,
1392  (const struct sockaddr *) un,
1393  un_len))
1394  {
1396  LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Cannot bind to `%s'\n"), un->sun_path);
1397  GNUNET_NETWORK_socket_close (plugin->unix_sock.desc);
1398  plugin->unix_sock.desc = NULL;
1399  GNUNET_free (un);
1400  return GNUNET_SYSERR;
1401  }
1402  LOG (GNUNET_ERROR_TYPE_DEBUG, "Bound to `%s'\n", plugin->unix_socket_path);
1403  plugin->read_task =
1405  plugin->unix_sock.desc,
1407  plugin);
1408  GNUNET_free (un);
1409  return 1;
1410 }
1411 
1412 
1429 static int
1430 unix_plugin_check_address (void *cls, const void *addr, size_t addrlen)
1431 {
1432  struct Plugin *plugin = cls;
1433  const struct UnixAddress *ua = addr;
1434  char *addrstr;
1435  size_t addr_str_len;
1436 
1437  if ((NULL == addr) || (0 == addrlen) ||
1438  (sizeof(struct UnixAddress) > addrlen))
1439  {
1440  GNUNET_break (0);
1441  return GNUNET_SYSERR;
1442  }
1443  addrstr = (char *) &ua[1];
1444  addr_str_len = ntohl (ua->addrlen);
1445  if ('\0' != addrstr[addr_str_len - 1])
1446  {
1447  GNUNET_break (0);
1448  return GNUNET_SYSERR;
1449  }
1450  if (strlen (addrstr) + 1 != addr_str_len)
1451  {
1452  GNUNET_break (0);
1453  return GNUNET_SYSERR;
1454  }
1455 
1456  if (0 == strcmp (plugin->unix_socket_path, addrstr))
1457  return GNUNET_OK;
1458  return GNUNET_SYSERR;
1459 }
1460 
1461 
1476 static void
1478  const char *type,
1479  const void *addr,
1480  size_t addrlen,
1481  int numeric,
1484  void *asc_cls)
1485 {
1486  const char *ret;
1487 
1488  if ((NULL != addr) && (addrlen > 0))
1489  ret = unix_plugin_address_to_string (NULL, addr, addrlen);
1490  else
1491  ret = NULL;
1492  asc (asc_cls, ret, (NULL == ret) ? GNUNET_SYSERR : GNUNET_OK);
1493  asc (asc_cls, NULL, GNUNET_OK);
1494 }
1495 
1496 
1509 static int
1511  const char *addr,
1512  uint16_t addrlen,
1513  void **buf,
1514  size_t *added)
1515 {
1516  struct UnixAddress *ua;
1517  char *address;
1518  char *plugin;
1519  char *optionstr;
1520  uint32_t options;
1521  size_t ua_size;
1522 
1523  /* Format unix.options.address */
1524  address = NULL;
1525  plugin = NULL;
1526  optionstr = NULL;
1527 
1528  if ((NULL == addr) || (addrlen == 0))
1529  {
1530  GNUNET_break (0);
1531  return GNUNET_SYSERR;
1532  }
1533  if ('\0' != addr[addrlen - 1])
1534  {
1535  GNUNET_break (0);
1536  return GNUNET_SYSERR;
1537  }
1538  if (strlen (addr) != addrlen - 1)
1539  {
1540  GNUNET_break (0);
1541  return GNUNET_SYSERR;
1542  }
1543  plugin = GNUNET_strdup (addr);
1544  optionstr = strchr (plugin, '.');
1545  if (NULL == optionstr)
1546  {
1547  GNUNET_break (0);
1548  GNUNET_free (plugin);
1549  return GNUNET_SYSERR;
1550  }
1551  optionstr[0] = '\0';
1552  optionstr++;
1553  options = atol (optionstr);
1554  address = strchr (optionstr, '.');
1555  if (NULL == address)
1556  {
1557  GNUNET_break (0);
1558  GNUNET_free (plugin);
1559  return GNUNET_SYSERR;
1560  }
1561  address[0] = '\0';
1562  address++;
1563  if (0 != strcmp (plugin, PLUGIN_NAME))
1564  {
1565  GNUNET_break (0);
1566  GNUNET_free (plugin);
1567  return GNUNET_SYSERR;
1568  }
1569 
1570  ua_size = sizeof(struct UnixAddress) + strlen (address) + 1;
1571  ua = GNUNET_malloc (ua_size);
1572  ua->options = htonl (options);
1573  ua->addrlen = htonl (strlen (address) + 1);
1574  GNUNET_memcpy (&ua[1], address, strlen (address) + 1);
1575  GNUNET_free (plugin);
1576 
1577  (*buf) = ua;
1578  (*added) = ua_size;
1579  return GNUNET_OK;
1580 }
1581 
1582 
1588 static void
1590 {
1591  struct Plugin *plugin = cls;
1592  struct GNUNET_HELLO_Address *address;
1593  size_t len;
1594  struct UnixAddress *ua;
1595  char *unix_path;
1596 
1597  len = sizeof(struct UnixAddress) + strlen (plugin->unix_socket_path) + 1;
1598  ua = GNUNET_malloc (len);
1599  ua->options = htonl (plugin->myoptions);
1600  ua->addrlen = htonl (strlen (plugin->unix_socket_path) + 1);
1601  unix_path = (char *) &ua[1];
1602  GNUNET_memcpy (unix_path,
1603  plugin->unix_socket_path,
1604  strlen (plugin->unix_socket_path) + 1);
1605 
1606  plugin->address_update_task = NULL;
1607  address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
1608  PLUGIN_NAME,
1609  ua,
1610  len,
1612  plugin->env->notify_address (plugin->env->cls, GNUNET_YES, address);
1613  GNUNET_free (ua);
1614  GNUNET_free (address);
1615 }
1616 
1617 
1626 static int
1628  const struct GNUNET_PeerIdentity *key,
1629  void *value)
1630 {
1631  struct Plugin *plugin = cls;
1632  struct GNUNET_ATS_Session *session = value;
1633 
1635  return GNUNET_YES;
1636 }
1637 
1638 
1646 static void
1648  const struct GNUNET_PeerIdentity *target)
1649 {
1650  struct Plugin *plugin = cls;
1651 
1653  target,
1655  plugin);
1656 }
1657 
1658 
1668 static int
1670  const struct GNUNET_PeerIdentity *peer,
1671  void *value)
1672 {
1673  struct Plugin *plugin = cls;
1674  struct GNUNET_ATS_Session *session = value;
1675 
1678  return GNUNET_OK;
1679 }
1680 
1681 
1694 static void
1697  void *sic_cls)
1698 {
1699  struct Plugin *plugin = cls;
1700 
1701  plugin->sic = sic;
1702  plugin->sic_cls = sic_cls;
1703  if (NULL != sic)
1704  {
1707  plugin);
1708  /* signal end of first iteration */
1709  sic (sic_cls, NULL, NULL);
1710  }
1711 }
1712 
1713 
1721 void *
1723 {
1726  struct Plugin *plugin;
1727  int sockets_created;
1728 
1729  if (NULL == env->receive)
1730  {
1731  /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
1732  initialize the plugin or the API */
1734  api->cls = NULL;
1735  api->address_pretty_printer = &unix_plugin_address_pretty_printer;
1736  api->address_to_string = &unix_plugin_address_to_string;
1737  api->string_to_address = &unix_plugin_string_to_address;
1738  return api;
1739  }
1740 
1741  plugin = GNUNET_new (struct Plugin);
1742  if (GNUNET_OK !=
1744  "transport-unix",
1745  "UNIXPATH",
1746  &plugin->unix_socket_path))
1747  {
1749  "transport-unix",
1750  "UNIXPATH");
1751  GNUNET_free (plugin);
1752  return NULL;
1753  }
1754 
1755  plugin->env = env;
1756 
1757  /* Initialize my flags */
1758 #ifdef __linux__
1759  plugin->is_abstract =
1761  "testing",
1762  "USE_ABSTRACT_SOCKETS");
1763 #endif
1764  plugin->myoptions = UNIX_OPTIONS_NONE;
1765  if (GNUNET_YES == plugin->is_abstract)
1767 
1769  api->cls = plugin;
1770  api->get_session = &unix_plugin_get_session;
1771  api->send = &unix_plugin_send;
1772  api->disconnect_peer = &unix_plugin_peer_disconnect;
1773  api->disconnect_session = &unix_plugin_session_disconnect;
1774  api->query_keepalive_factor = &unix_plugin_query_keepalive_factor;
1775  api->address_pretty_printer = &unix_plugin_address_pretty_printer;
1776  api->address_to_string = &unix_plugin_address_to_string;
1777  api->check_address = &unix_plugin_check_address;
1778  api->string_to_address = &unix_plugin_string_to_address;
1779  api->get_network = &unix_plugin_get_network;
1780  api->get_network_for_address = &unix_plugin_get_network_for_address;
1781  api->update_session_timeout = &unix_plugin_update_session_timeout;
1782  api->setup_monitor = &unix_plugin_setup_monitor;
1783  sockets_created = unix_transport_server_start (plugin);
1784  if ((0 == sockets_created) || (GNUNET_SYSERR == sockets_created))
1785  {
1786  LOG (GNUNET_ERROR_TYPE_WARNING, _ ("Failed to open UNIX listen socket\n"));
1787  GNUNET_free (api);
1788  GNUNET_free (plugin->unix_socket_path);
1789  GNUNET_free (plugin);
1790  return NULL;
1791  }
1793  plugin->address_update_task =
1795  return api;
1796 }
1797 
1798 
1805 void *
1807 {
1808  struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1809  struct Plugin *plugin = api->cls;
1810  struct GNUNET_HELLO_Address *address;
1811  struct UNIXMessageWrapper *msgw;
1812  struct UnixAddress *ua;
1813  size_t len;
1814  struct GNUNET_ATS_Session *session;
1815 
1816  if (NULL == plugin)
1817  {
1818  GNUNET_free (api);
1819  return NULL;
1820  }
1821  len = sizeof(struct UnixAddress) + strlen (plugin->unix_socket_path) + 1;
1822  ua = GNUNET_malloc (len);
1823  ua->options = htonl (plugin->myoptions);
1824  ua->addrlen = htonl (strlen (plugin->unix_socket_path) + 1);
1825  GNUNET_memcpy (&ua[1],
1826  plugin->unix_socket_path,
1827  strlen (plugin->unix_socket_path) + 1);
1828  address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
1829  PLUGIN_NAME,
1830  ua,
1831  len,
1833  plugin->env->notify_address (plugin->env->cls, GNUNET_NO, address);
1834 
1835  GNUNET_free (address);
1836  GNUNET_free (ua);
1837 
1838  while (NULL != (msgw = plugin->msg_head))
1839  {
1840  GNUNET_CONTAINER_DLL_remove (plugin->msg_head, plugin->msg_tail, msgw);
1841  session = msgw->session;
1842  session->msgs_in_queue--;
1843  GNUNET_assert (session->bytes_in_queue >= msgw->msgsize);
1844  session->bytes_in_queue -= msgw->msgsize;
1845  GNUNET_assert (plugin->bytes_in_queue >= msgw->msgsize);
1846  plugin->bytes_in_queue -= msgw->msgsize;
1847  if (NULL != msgw->cont)
1848  msgw->cont (msgw->cont_cls,
1849  &msgw->session->target,
1850  GNUNET_SYSERR,
1851  msgw->payload,
1852  0);
1853  GNUNET_free (msgw->msg);
1854  GNUNET_free (msgw);
1855  }
1856 
1857  if (NULL != plugin->read_task)
1858  {
1859  GNUNET_SCHEDULER_cancel (plugin->read_task);
1860  plugin->read_task = NULL;
1861  }
1862  if (NULL != plugin->write_task)
1863  {
1864  GNUNET_SCHEDULER_cancel (plugin->write_task);
1865  plugin->write_task = NULL;
1866  }
1867  if (NULL != plugin->address_update_task)
1868  {
1869  GNUNET_SCHEDULER_cancel (plugin->address_update_task);
1870  plugin->address_update_task = NULL;
1871  }
1872  if (NULL != plugin->unix_sock.desc)
1873  {
1875  GNUNET_NETWORK_socket_close (plugin->unix_sock.desc));
1876  plugin->unix_sock.desc = NULL;
1877  }
1880  plugin);
1882  GNUNET_break (0 == plugin->bytes_in_queue);
1883  GNUNET_free (plugin->unix_socket_path);
1884  GNUNET_free (plugin);
1885  GNUNET_free (api);
1886  return NULL;
1887 }
1888 
1889 
1890 /* end of plugin_transport_unix.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
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
struct TestcasePlugin * plugin
The process handle to the testbed service.
static char * address
GNS address for this phone.
struct GNUNET_HashCode key
The key used in the DHT.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static char * value
Value of the record to add/remove.
enum State state
current state of profiling
#define info
static unsigned long long payload
How much data are we currently storing in the database?
static char buf[2048]
static unsigned int csize
static int numeric
Option -n.
Helper library for handling HELLOs.
Constants for network protocols.
API to create, modify and access statistics.
Transport service plugin API.
enum GNUNET_GenericReturnValue 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.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
After how long do we consider a connection to a peer dead if we don't receive messages from the peer?
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:582
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multipeermap_contains_value(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Check if the map contains the given value under the given key.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
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).
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.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
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.
enum GNUNET_GenericReturnValue 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.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_allocate(const struct GNUNET_PeerIdentity *peer, const char *transport_name, const void *address, size_t address_length, enum GNUNET_HELLO_AddressInfo local_info)
Allocate an address struct.
Definition: address.c:63
#define GNUNET_HELLO_address_free(addr)
Free an address.
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_copy(const struct GNUNET_HELLO_Address *address)
Copy an address struct.
Definition: address.c:99
int GNUNET_HELLO_address_cmp(const struct GNUNET_HELLO_Address *a1, const struct GNUNET_HELLO_Address *a2)
Compare two addresses.
Definition: address.c:112
@ GNUNET_HELLO_ADDRESS_INFO_NONE
No additional information.
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_PACKED
gcc-ism to get packed structs.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#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.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
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_DEBUG
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#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.
enum GNUNET_GenericReturnValue 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:626
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:508
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:687
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:832
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:439
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:805
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:771
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:39
@ GNUNET_NT_LOOPBACK
Loopback (same host).
Definition: gnunet_nt_lib.h:48
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_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:1577
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:1506
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
@ GNUNET_SCHEDULER_REASON_READ_READY
The reading socket is ready.
@ GNUNET_SCHEDULER_REASON_WRITE_READY
The writing socket is ready.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
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
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:316
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
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
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
void(* GNUNET_TRANSPORT_SessionInfoCallback)(void *cls, struct GNUNET_ATS_Session *session, const struct GNUNET_TRANSPORT_SessionInfo *info)
Function called by the plugin with information about the current sessions managed by the plugin (for ...
void(* GNUNET_TRANSPORT_TransmitContinuation)(void *cls, const struct GNUNET_PeerIdentity *target, int result, size_t size_payload, size_t size_on_wire)
Function called by the GNUNET_TRANSPORT_TransmitFunction upon "completion".
void(* GNUNET_TRANSPORT_AddressStringCallback)(void *cls, const char *address, int res)
Function called by the pretty printer for the resolved address for each human-readable address obtain...
GNUNET_TRANSPORT_SessionState
Possible states of a session in a plugin.
@ GNUNET_TRANSPORT_SS_INIT
The session was created (first call for each session object).
@ GNUNET_TRANSPORT_SS_DONE
Session is being torn down and about to disappear.
@ GNUNET_TRANSPORT_SS_UP
Session is fully UP.
@ GNUNET_TRANSPORT_SS_UPDATE
This is just an update about the session, the state did not change.
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
static ssize_t unix_real_send(void *cls, struct GNUNET_NETWORK_Handle *send_handle, const struct GNUNET_PeerIdentity *target, const char *msgbuf, size_t msgbuf_size, unsigned int priority, struct GNUNET_TIME_Absolute timeout, const struct UnixAddress *addr, size_t addrlen, size_t payload, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
Actually send out the message, assume we've got the address and send_handle squared away!
#define PLUGIN_NAME
Name of the plugin.
static struct GNUNET_ATS_Session * unix_plugin_get_session(void *cls, const struct GNUNET_HELLO_Address *address)
Creates a new outbound session the transport service will use to send data to the peer.
static void unix_plugin_select_read(void *cls)
We have been notified that our socket has something to read.
static void unix_plugin_peer_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
Disconnect from a remote node.
static int unix_plugin_check_address(void *cls, const void *addr, size_t addrlen)
Function that will be called to check if a binary address for this plugin is well-formed and correspo...
void * libgnunet_plugin_transport_unix_init(void *cls)
The exported method.
static void address_notification(void *cls)
Notify transport service about address.
static void session_timeout(void *cls)
Session was idle for too long, so disconnect it.
static void unix_plugin_do_read(struct Plugin *plugin)
Read from UNIX domain socket (it is ready).
static struct GNUNET_ATS_Session * lookup_session(struct Plugin *plugin, const struct GNUNET_HELLO_Address *address)
Find an existing session by address.
static struct sockaddr_un * unix_address_to_sockaddr(const char *unixpath, socklen_t *sock_len)
Convert unix path to a struct sockaddr_un *
static void unix_plugin_address_pretty_printer(void *cls, const char *type, const void *addr, size_t addrlen, int numeric, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
Convert the transports address to a nice, human-readable format.
static void reschedule_session_timeout(struct GNUNET_ATS_Session *session)
Increment session timeout due to activity.
static unsigned int unix_plugin_query_keepalive_factor(void *cls)
Function that is called to get the keepalive factor.
static int unix_transport_server_start(void *cls)
Create a slew of UNIX sockets.
static int unix_plugin_session_disconnect(void *cls, struct GNUNET_ATS_Session *session)
Functions with this signature are called whenever we need to close a session due to a disconnect or f...
UNIX_ADDRESS_OPTIONS
Options for UNIX Domain addresses.
@ UNIX_OPTIONS_USE_ABSTRACT_SOCKETS
Linux abstract domain sockets should be used.
@ UNIX_OPTIONS_NONE
No special options.
static int get_session_delete_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Function called on sessions to disconnect.
static enum GNUNET_NetworkType unix_plugin_get_network_for_address(void *cls, const struct GNUNET_HELLO_Address *address)
Function obtain the network type for a session.
static enum GNUNET_NetworkType unix_plugin_get_network(void *cls, struct GNUNET_ATS_Session *session)
Function obtain the network type for a session.
static void unix_plugin_setup_monitor(void *cls, GNUNET_TRANSPORT_SessionInfoCallback sic, void *sic_cls)
Begin monitoring sessions of a plugin.
static int lookup_session_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Function called to find a session by address.
static void unix_demultiplexer(struct Plugin *plugin, struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *currhdr, const struct UnixAddress *ua, size_t ua_len)
Demultiplexer for UNIX messages.
static const char * unix_plugin_address_to_string(void *cls, const void *addr, size_t addrlen)
Function called for a quick conversion of the binary address to a numeric address.
static int unix_plugin_string_to_address(void *cls, const char *addr, uint16_t addrlen, void **buf, size_t *added)
Function called to convert a string address to a binary address.
static void unix_plugin_update_session_timeout(void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_ATS_Session *session)
Function that will be called whenever the transport service wants to notify the plugin that a session...
static ssize_t unix_plugin_send(void *cls, struct GNUNET_ATS_Session *session, const char *msgbuf, size_t msgbuf_size, unsigned int priority, struct GNUNET_TIME_Relative to, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
Function that can be used by the transport service to transmit a message using the plugin.
#define RETRY
Return code we give on 'send' if we failed to send right now but it makes sense to retry later.
void * libgnunet_plugin_transport_unix_done(void *cls)
Shutdown the plugin.
#define LOG(kind,...)
static int send_session_info_iter(void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
Return information about the given session to the monitor callback.
static void unix_plugin_select_write(void *cls)
We have been notified that our socket is ready to write.
static void notify_session_monitor(struct Plugin *plugin, struct GNUNET_ATS_Session *session, enum GNUNET_TRANSPORT_SessionState state)
If a session monitor is attached, notify it about the new session state.
static void unix_plugin_do_write(struct Plugin *plugin)
Write to UNIX domain socket (it is ready).
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:431
Session handle for connections.
struct GNUNET_PeerIdentity target
To whom are we talking to.
struct Plugin * plugin
Pointer to the global plugin struct.
unsigned int msgs_in_queue
Number of messages waiting for transmission to this peer.
struct GNUNET_TIME_Absolute timeout
When does this session time out.
struct GNUNET_HELLO_Address * address
Address.
struct GNUNET_ATS_Session * next
Stored in a linked list.
unsigned long long bytes_in_queue
Number of bytes waiting for transmission to this peer.
struct GNUNET_SCHEDULER_Task * timeout_task
Session timeout task.
struct GNUNET_ATS_Session * prev
Stored in a linked list.
void * cls
Closure for all of the callbacks.
Internal representation of the hash map.
An address for communicating with a peer.
size_t address_length
Number of bytes in address.
const void * address
Binary representation of the address (plugin-specific).
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.
handle to a socket
Definition: network.c:53
The identity of the host (wraps the signing key of the peer).
Context information passed to each scheduler task.
enum GNUNET_SCHEDULER_Reason reason
Reason why the task is run now.
Entry in list of pending tasks.
Definition: scheduler.c:136
Time for absolute times used by GNUnet, in microseconds.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
The transport service will pass a pointer to a struct of this type as the first and only argument to ...
void * cls
Closure for the various callbacks.
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
void * cls
Closure for all of the callbacks.
Information about a plugin's session.
Closure to lookup_queue_it().
const struct GNUNET_HELLO_Address * address
Address we are looking for.
struct GNUNET_ATS_Session * res
Location to store the session, if found.
struct Queue * res
Location to store the queue, if found.
Handle for a plugin.
Definition: block.c:38
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47
void * sic_cls
Closure for sic.
int is_abstract
Are we using an abstract UNIX domain socket?
char * unix_socket_path
Path of our unix domain socket (/tmp/unix-plugin)
struct GNUNET_SCHEDULER_Task * read_task
Task that reads incoming UDP packets.
unsigned long long bytes_in_queue
Number of bytes we currently have in our write queues.
struct UNIXMessageWrapper * msg_head
Head of queue of messages to transmit.
struct GNUNET_SCHEDULER_Task * address_update_task
ID of task used to update our addresses when one expires.
struct UNIXMessageWrapper * msg_tail
Tail of queue of messages to transmit.
struct UNIX_Sock_Info unix_sock
socket that we transmit all data with
struct GNUNET_DATACACHE_PluginEnvironment * env
Our execution environment.
uint32_t myoptions
Address options.
GNUNET_TRANSPORT_SessionInfoCallback sic
Function to call about session status changes.
struct GNUNET_SCHEDULER_Task * write_task
ID of write task.
struct GNUNET_CONTAINER_MultiPeerMap * session_map
Sessions (map from peer identity to struct GNUNET_ATS_Session)
Information we track for a message awaiting transmission.
size_t payload
Number of bytes of payload encapsulated in msg.
struct UNIXMessageWrapper * next
We keep messages in a doubly linked list.
struct UNIXMessageWrapper * prev
We keep messages in a doubly linked list.
struct GNUNET_TIME_Absolute timeout
Timeout for this message.
struct UNIXMessage * msg
The actual payload (allocated separately right now).
unsigned int priority
Priority of the message (ignored, just dragged along in UNIX).
size_t msgsize
Number of bytes in msg.
GNUNET_TRANSPORT_TransmitContinuation cont
Function to call upon transmission.
void * cont_cls
Closure for cont.
struct GNUNET_ATS_Session * session
Session this message belongs to.
UNIX Message-Packet header.
struct GNUNET_MessageHeader header
Message header.
struct GNUNET_PeerIdentity sender
What is the identity of the sender (GNUNET_hash of public key)
Information we keep for each of our listen sockets.
struct GNUNET_NETWORK_Handle * desc
The network handle.
Binary format for an UNIX Domain Socket address in GNUnet.
uint32_t options
Options to use for the address, in NBO.
uint32_t addrlen
Length of the address (path length), in NBO.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
common internal definitions for transport service