GNUnet  0.10.x
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 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
72 
73 #define LOG(kind,...) GNUNET_log_from (kind, "transport-unix",__VA_ARGS__)
74 
75 
77 
82 {
87 
92 
93  /* followed by actual path */
94 };
95 
96 
100 struct UNIXMessage
101 {
105  struct GNUNET_MessageHeader header;
106 
110  struct GNUNET_PeerIdentity sender;
111 
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 {
179 
183  struct GNUNET_ATS_Session *next;
184 
188  struct GNUNET_ATS_Session *prev;
189 
196  struct GNUNET_PeerIdentity target;
197 
201  struct Plugin *plugin;
202 
207 
211  unsigned long long bytes_in_queue;
212 
216  struct GNUNET_TIME_Absolute timeout;
217 
222 
226  unsigned int msgs_in_queue;
227 
228 };
229 
230 
234 struct Plugin;
235 
236 
241 {
246 };
247 
248 
252 struct Plugin
253 {
254 
258  struct GNUNET_SCHEDULER_Task * address_update_task;
259 
264 
269 
273  unsigned long long bytes_in_queue;
274 
279 
284 
289 
294 
299 
304 
308  void *sic_cls;
309 
314 
318  uint32_t myoptions;
319 
324 
325 };
326 
327 
336 static void
338  struct GNUNET_ATS_Session *session,
340 {
341  struct GNUNET_TRANSPORT_SessionInfo info;
342 
343  if (NULL == plugin->sic)
344  return;
345  memset (&info, 0, sizeof (info));
346  info.state = state;
347  info.is_inbound = GNUNET_SYSERR; /* hard to say */
348  info.num_msg_pending = session->msgs_in_queue;
349  info.num_bytes_pending = session->bytes_in_queue;
350  /* info.receive_delay remains zero as this is not supported by UNIX
351  (cannot selectively not receive from 'some' peer while continuing
352  to receive from others) */
353  info.session_timeout = session->timeout;
354  info.address = session->address;
355  plugin->sic (plugin->sic_cls,
356  session,
357  &info);
358 }
359 
360 
372 static const char *
374  const void *addr,
375  size_t addrlen)
376 {
377  static char rbuf[1024];
378  struct UnixAddress *ua = (struct UnixAddress *) addr;
379  char *addrstr;
380  size_t addr_str_len;
381  unsigned int off;
382 
383  if ((NULL == addr) || (sizeof (struct UnixAddress) > addrlen))
384  {
385  GNUNET_break(0);
386  return NULL;
387  }
388  addrstr = (char *) &ua[1];
389  addr_str_len = ntohl (ua->addrlen);
390 
391  if (addr_str_len != addrlen - sizeof(struct UnixAddress))
392  {
393  GNUNET_break(0);
394  return NULL;
395  }
396  if ('\0' != addrstr[addr_str_len - 1])
397  {
398  GNUNET_break(0);
399  return NULL;
400  }
401  if (strlen (addrstr) + 1 != addr_str_len)
402  {
403  GNUNET_break(0);
404  return NULL;
405  }
406 
407  off = 0;
408  if ('\0' == addrstr[0])
409  off++;
410  memset (rbuf, 0, sizeof (rbuf));
411  GNUNET_snprintf (rbuf,
412  sizeof (rbuf) - 1,
413  "%s.%u.%s%.*s",
414  PLUGIN_NAME,
415  ntohl (ua->options),
416  (off == 1) ? "@" : "",
417  (int) (addr_str_len - off),
418  &addrstr[off]);
419  return rbuf;
420 }
421 
422 
432 static int
434  struct GNUNET_ATS_Session *session)
435 {
436  struct Plugin *plugin = cls;
437  struct UNIXMessageWrapper *msgw;
438  struct UNIXMessageWrapper *next;
439 
441  "Disconnecting session for peer `%s' `%s'\n",
442  GNUNET_i2s (&session->target),
444  session->address->address,
445  session->address->address_length));
446  plugin->env->session_end (plugin->env->cls,
447  session->address,
448  session);
449  next = plugin->msg_head;
450  while (NULL != next)
451  {
452  msgw = next;
453  next = msgw->next;
454  if (msgw->session != session)
455  continue;
457  plugin->msg_tail,
458  msgw);
459  session->msgs_in_queue--;
460  GNUNET_assert (session->bytes_in_queue >= msgw->msgsize);
461  session->bytes_in_queue -= msgw->msgsize;
462  GNUNET_assert (plugin->bytes_in_queue >= msgw->msgsize);
463  plugin->bytes_in_queue -= msgw->msgsize;
464  if (NULL != msgw->cont)
465  msgw->cont (msgw->cont_cls,
466  &msgw->session->target,
468  msgw->payload, 0);
469  GNUNET_free (msgw->msg);
470  GNUNET_free (msgw);
471  }
474  &session->target,
475  session));
476  GNUNET_STATISTICS_set (plugin->env->stats,
477  "# UNIX sessions active",
479  GNUNET_NO);
480  if (NULL != session->timeout_task)
481  {
483  session->timeout_task = NULL;
485  }
486  notify_session_monitor (plugin,
487  session,
490  GNUNET_break (0 == session->bytes_in_queue);
491  GNUNET_break (0 == session->msgs_in_queue);
492  GNUNET_free (session);
493  return GNUNET_OK;
494 }
495 
496 
502 static void
503 session_timeout (void *cls)
504 {
505  struct GNUNET_ATS_Session *session = cls;
506  struct GNUNET_TIME_Relative left;
507 
508  session->timeout_task = NULL;
510  if (0 != left.rel_value_us)
511  {
512  /* not actually our turn yet, but let's at least update
513  the monitor, it may think we're about to die ... */
514  notify_session_monitor (session->plugin,
515  session,
519  session);
520  return;
521  }
523  "Session %p was idle for %s, disconnecting\n",
524  session,
526  GNUNET_YES));
527  unix_plugin_session_disconnect (session->plugin, session);
528 }
529 
530 
538 static void
540 {
541  GNUNET_assert (NULL != session->timeout_task);
543 }
544 
545 
553 static struct sockaddr_un *
554 unix_address_to_sockaddr (const char *unixpath,
555  socklen_t *sock_len)
556 {
557  struct sockaddr_un *un;
558  size_t slen;
559 
560  GNUNET_assert (0 < strlen (unixpath)); /* sanity check */
561  un = GNUNET_new (struct sockaddr_un);
562  un->sun_family = AF_UNIX;
563  slen = strlen (unixpath);
564  if (slen >= sizeof (un->sun_path))
565  slen = sizeof (un->sun_path) - 1;
566  GNUNET_memcpy (un->sun_path, unixpath, slen);
567  un->sun_path[slen] = '\0';
568  slen = sizeof (struct sockaddr_un);
569 #if HAVE_SOCKADDR_UN_SUN_LEN
570  un->sun_len = (u_char) slen;
571 #endif
572  (*sock_len) = slen;
573  return un;
574 }
575 
576 
580 struct LookupCtx
581 {
586 
591 };
592 
593 
602 static int
603 lookup_session_it (void *cls,
604  const struct GNUNET_PeerIdentity * key,
605  void *value)
606 {
607  struct LookupCtx *lctx = cls;
608  struct GNUNET_ATS_Session *session = value;
609 
610  if (0 == GNUNET_HELLO_address_cmp (lctx->address,
611  session->address))
612  {
613  lctx->res = session;
614  return GNUNET_NO;
615  }
616  return GNUNET_YES;
617 }
618 
619 
627 static struct GNUNET_ATS_Session *
629  const struct GNUNET_HELLO_Address *address)
630 {
631  struct LookupCtx lctx;
632 
633  lctx.address = address;
634  lctx.res = NULL;
636  &address->peer,
637  &lookup_session_it, &lctx);
638  return lctx.res;
639 }
640 
641 
650 static unsigned int
652 {
653  return 3;
654 }
655 
656 
678 static ssize_t
679 unix_real_send (void *cls,
680  struct GNUNET_NETWORK_Handle *send_handle,
681  const struct GNUNET_PeerIdentity *target,
682  const char *msgbuf,
683  size_t msgbuf_size,
684  unsigned int priority,
686  const struct UnixAddress *addr,
687  size_t addrlen,
688  size_t payload,
690  void *cont_cls)
691 {
692  struct Plugin *plugin = cls;
693  ssize_t sent;
694  struct sockaddr_un *un;
695  socklen_t un_len;
696  const char *unixpath;
697 
698  if (NULL == send_handle)
699  {
700  GNUNET_break (0); /* We do not have a send handle */
701  return GNUNET_SYSERR;
702  }
703  if ((NULL == addr) || (0 == addrlen))
704  {
705  GNUNET_break (0); /* Can never send if we don't have an address */
706  return GNUNET_SYSERR;
707  }
708 
709  /* Prepare address */
710  unixpath = (const char *) &addr[1];
711  if (NULL == (un = unix_address_to_sockaddr (unixpath,
712  &un_len)))
713  {
714  GNUNET_break (0);
715  return -1;
716  }
717 
718  if ((GNUNET_YES == plugin->is_abstract) &&
719  (0 != (UNIX_OPTIONS_USE_ABSTRACT_SOCKETS & ntohl(addr->options) )) )
720  {
721  un->sun_path[0] = '\0';
722  }
723 resend:
724  /* Send the data */
725  sent = GNUNET_NETWORK_socket_sendto (send_handle,
726  msgbuf,
727  msgbuf_size,
728  (const struct sockaddr *) un,
729  un_len);
730  if (GNUNET_SYSERR == sent)
731  {
732  if ( (EAGAIN == errno) ||
733  (ENOBUFS == errno) )
734  {
735  GNUNET_free (un);
736  return RETRY; /* We have to retry later */
737  }
738  if (EMSGSIZE == errno)
739  {
740  socklen_t size = 0;
741  socklen_t len = sizeof (size);
742 
744  send_handle, SOL_SOCKET, SO_SNDBUF, &size,
745  &len);
746  if (size < msgbuf_size)
747  {
749  "Trying to increase socket buffer size from %u to %u for message size %u\n",
750  (unsigned int) size,
751  (unsigned int) ((msgbuf_size / 1000) + 2) * 1000,
752  (unsigned int) msgbuf_size);
753  size = ((msgbuf_size / 1000) + 2) * 1000;
754  if (GNUNET_OK ==
756  SOL_SOCKET, SO_SNDBUF,
757  &size, sizeof (size)))
758  goto resend; /* Increased buffer size, retry sending */
759  else
760  {
761  /* Could not increase buffer size: error, no retry */
763  GNUNET_free (un);
764  return GNUNET_SYSERR;
765  }
766  }
767  else
768  {
769  /* Buffer is bigger than message: error, no retry
770  * This should never happen!*/
771  GNUNET_break (0);
772  GNUNET_free (un);
773  return GNUNET_SYSERR;
774  }
775  }
776  }
777 
779  "UNIX transmitted %u-byte message to %s (%d: %s)\n",
780  (unsigned int) msgbuf_size,
781  GNUNET_a2s ((const struct sockaddr *)un, un_len),
782  (int) sent,
783  (sent < 0) ? STRERROR (errno) : "ok");
784  GNUNET_free (un);
785  return sent;
786 }
787 
788 
796 static enum GNUNET_NetworkType
798  struct GNUNET_ATS_Session *session)
799 {
800  GNUNET_assert (NULL != session);
801  return GNUNET_NT_LOOPBACK;
802 }
803 
804 
812 static enum GNUNET_NetworkType
814  const struct GNUNET_HELLO_Address *address)
815 
816 {
817  return GNUNET_NT_LOOPBACK;
818 }
819 
820 
829 static struct GNUNET_ATS_Session *
831  const struct GNUNET_HELLO_Address *address)
832 {
833  struct Plugin *plugin = cls;
834  struct GNUNET_ATS_Session *session;
835  struct UnixAddress *ua;
836  char * addrstr;
837  uint32_t addr_str_len;
838  uint32_t addr_option;
839 
840  ua = (struct UnixAddress *) address->address;
841  if ((NULL == address->address) || (0 == address->address_length) ||
842  (sizeof (struct UnixAddress) > address->address_length))
843  {
844  GNUNET_break (0);
845  return NULL;
846  }
847  addrstr = (char *) &ua[1];
848  addr_str_len = ntohl (ua->addrlen);
849  addr_option = ntohl (ua->options);
850 
851  if ( (0 != (UNIX_OPTIONS_USE_ABSTRACT_SOCKETS & addr_option)) &&
852  (GNUNET_NO == plugin->is_abstract))
853  {
854  return NULL;
855  }
856 
857  if (addr_str_len != address->address_length - sizeof (struct UnixAddress))
858  {
859  return NULL; /* This can be a legacy address */
860  }
861 
862  if ('\0' != addrstr[addr_str_len - 1])
863  {
864  GNUNET_break (0);
865  return NULL;
866  }
867  if (strlen (addrstr) + 1 != addr_str_len)
868  {
869  GNUNET_break (0);
870  return NULL;
871  }
872 
873  /* Check if a session for this address already exists */
874  if (NULL != (session = lookup_session (plugin,
875  address)))
876  {
878  "Found existing session %p for address `%s'\n",
879  session,
881  address->address,
882  address->address_length));
883  return session;
884  }
885 
886  /* create a new session */
887  session = GNUNET_new (struct GNUNET_ATS_Session);
888  session->target = address->peer;
889  session->address = GNUNET_HELLO_address_copy (address);
890  session->plugin = plugin;
894  session);
896  "Creating a new session %p for address `%s'\n",
897  session,
899  address->address,
900  address->address_length));
902  &address->peer, session,
904  GNUNET_STATISTICS_set (plugin->env->stats,
905  "# UNIX sessions active",
907  GNUNET_NO);
908  notify_session_monitor (plugin,
909  session,
911  notify_session_monitor (plugin,
912  session,
914  return session;
915 }
916 
917 
927 static void
929  const struct GNUNET_PeerIdentity *peer,
930  struct GNUNET_ATS_Session *session)
931 {
932  struct Plugin *plugin = cls;
933 
934  if (GNUNET_OK !=
936  &session->target,
937  session))
938  {
939  GNUNET_break (0);
940  return;
941  }
942  reschedule_session_timeout (session);
943 }
944 
945 
955 static void
957  struct GNUNET_PeerIdentity *sender,
958  const struct GNUNET_MessageHeader *currhdr,
959  const struct UnixAddress *ua,
960  size_t ua_len)
961 {
962  struct GNUNET_ATS_Session *session;
964 
965  GNUNET_assert (ua_len >= sizeof (struct UnixAddress));
967  "Received message from %s\n",
968  unix_plugin_address_to_string (NULL, ua, ua_len));
969  GNUNET_STATISTICS_update (plugin->env->stats,
970  "# bytes received via UNIX",
971  ntohs (currhdr->size),
972  GNUNET_NO);
973 
974  /* Look for existing session */
975  address = GNUNET_HELLO_address_allocate (sender,
976  PLUGIN_NAME,
977  ua, ua_len,
978  GNUNET_HELLO_ADDRESS_INFO_NONE); /* UNIX does not have "inbound" sessions */
979  session = lookup_session (plugin, address);
980  if (NULL == session)
981  {
982  session = unix_plugin_get_session (plugin, address);
983  /* Notify transport and ATS about new inbound session */
984  plugin->env->session_start (NULL,
985  session->address,
986  session,
988  }
989  else
990  {
991  reschedule_session_timeout (session);
992  }
993  GNUNET_HELLO_address_free (address);
994  plugin->env->receive (plugin->env->cls,
995  session->address,
996  session,
997  currhdr);
998 }
999 
1000 
1006 static void
1008 {
1009  char buf[65536] GNUNET_ALIGN;
1010  struct UnixAddress *ua;
1011  struct UNIXMessage *msg;
1012  struct GNUNET_PeerIdentity sender;
1013  struct sockaddr_un un;
1014  socklen_t addrlen;
1015  ssize_t ret;
1016  int offset;
1017  int tsize;
1018  int is_abstract;
1019  char *msgbuf;
1020  const struct GNUNET_MessageHeader *currhdr;
1021  uint16_t csize;
1022  size_t ua_len;
1023 
1024  addrlen = sizeof (un);
1025  memset (&un, 0, sizeof (un));
1027  buf, sizeof (buf),
1028  (struct sockaddr *) &un,
1029  &addrlen);
1030  if ((GNUNET_SYSERR == ret) && ((errno == EAGAIN) || (errno == ENOBUFS)))
1031  return;
1032  if (GNUNET_SYSERR == ret)
1033  {
1035  "recvfrom");
1036  return;
1037  }
1038  else
1039  {
1041  "Read %d bytes from socket %s\n",
1042  (int) ret,
1043  un.sun_path);
1044  }
1045 
1046  GNUNET_assert (AF_UNIX == (un.sun_family));
1047  is_abstract = GNUNET_NO;
1048  if ('\0' == un.sun_path[0])
1049  {
1050  un.sun_path[0] = '@';
1051  is_abstract = GNUNET_YES;
1052  }
1053 
1054  ua_len = sizeof (struct UnixAddress) + strlen (un.sun_path) + 1;
1055  ua = GNUNET_malloc (ua_len);
1056  ua->addrlen = htonl (strlen (&un.sun_path[0]) +1);
1057  GNUNET_memcpy (&ua[1], &un.sun_path[0], strlen (un.sun_path) + 1);
1058  if (is_abstract)
1059  ua->options = htonl(UNIX_OPTIONS_USE_ABSTRACT_SOCKETS);
1060  else
1061  ua->options = htonl(UNIX_OPTIONS_NONE);
1062 
1063  msg = (struct UNIXMessage *) buf;
1064  csize = ntohs (msg->header.size);
1065  if ((csize < sizeof (struct UNIXMessage)) || (csize > ret))
1066  {
1067  GNUNET_break_op (0);
1068  GNUNET_free (ua);
1069  return;
1070  }
1071  msgbuf = (char *) &msg[1];
1072  GNUNET_memcpy (&sender,
1073  &msg->sender,
1074  sizeof (struct GNUNET_PeerIdentity));
1075  offset = 0;
1076  tsize = csize - sizeof (struct UNIXMessage);
1077  while (offset + sizeof (struct GNUNET_MessageHeader) <= tsize)
1078  {
1079  currhdr = (struct GNUNET_MessageHeader *) &msgbuf[offset];
1080  csize = ntohs (currhdr->size);
1081  if ((csize < sizeof (struct GNUNET_MessageHeader)) ||
1082  (csize > tsize - offset))
1083  {
1084  GNUNET_break_op (0);
1085  break;
1086  }
1087  unix_demultiplexer (plugin, &sender, currhdr, ua, ua_len);
1088  offset += csize;
1089  }
1090  GNUNET_free (ua);
1091 }
1092 
1093 
1099 static void
1101 {
1102  ssize_t sent = 0;
1103  struct UNIXMessageWrapper *msgw;
1104  struct GNUNET_ATS_Session *session;
1105  int did_delete;
1106 
1107  session = NULL;
1108  did_delete = GNUNET_NO;
1109  while (NULL != (msgw = plugin->msg_head))
1110  {
1112  break; /* Message is ready for sending */
1113  /* Message has a timeout */
1114  did_delete = GNUNET_YES;
1116  "Timeout for message with %u bytes \n",
1117  (unsigned int) msgw->msgsize);
1119  plugin->msg_tail,
1120  msgw);
1121  session = msgw->session;
1122  session->msgs_in_queue--;
1123  GNUNET_assert (session->bytes_in_queue >= msgw->msgsize);
1124  session->bytes_in_queue -= msgw->msgsize;
1125  GNUNET_assert (plugin->bytes_in_queue >= msgw->msgsize);
1126  plugin->bytes_in_queue -= msgw->msgsize;
1127  GNUNET_STATISTICS_set (plugin->env->stats,
1128  "# bytes currently in UNIX buffers",
1129  plugin->bytes_in_queue,
1130  GNUNET_NO);
1131  GNUNET_STATISTICS_update (plugin->env->stats,
1132  "# UNIX bytes discarded",
1133  msgw->msgsize,
1134  GNUNET_NO);
1135  if (NULL != msgw->cont)
1136  msgw->cont (msgw->cont_cls,
1137  &msgw->session->target,
1138  GNUNET_SYSERR,
1139  msgw->payload,
1140  0);
1141  GNUNET_free (msgw->msg);
1142  GNUNET_free (msgw);
1143  }
1144  if (NULL == msgw)
1145  {
1146  if (GNUNET_YES == did_delete)
1147  notify_session_monitor (plugin,
1148  session,
1150  return; /* Nothing to send at the moment */
1151  }
1152  session = msgw->session;
1153  sent = unix_real_send (plugin,
1154  plugin->unix_sock.desc,
1155  &session->target,
1156  (const char *) msgw->msg,
1157  msgw->msgsize,
1158  msgw->priority,
1159  msgw->timeout,
1160  msgw->session->address->address,
1161  msgw->session->address->address_length,
1162  msgw->payload,
1163  msgw->cont, msgw->cont_cls);
1164  if (RETRY == sent)
1165  {
1166  GNUNET_STATISTICS_update (plugin->env->stats,
1167  "# UNIX retry attempts",
1168  1, GNUNET_NO);
1169  notify_session_monitor (plugin,
1170  session,
1172  return;
1173  }
1175  plugin->msg_tail,
1176  msgw);
1177  session->msgs_in_queue--;
1178  GNUNET_assert (session->bytes_in_queue >= msgw->msgsize);
1179  session->bytes_in_queue -= msgw->msgsize;
1180  GNUNET_assert (plugin->bytes_in_queue >= msgw->msgsize);
1181  plugin->bytes_in_queue -= msgw->msgsize;
1182  GNUNET_STATISTICS_set (plugin->env->stats,
1183  "# bytes currently in UNIX buffers",
1184  plugin->bytes_in_queue, GNUNET_NO);
1185  notify_session_monitor (plugin,
1186  session,
1188  if (GNUNET_SYSERR == sent)
1189  {
1190  /* failed and no retry */
1191  if (NULL != msgw->cont)
1192  msgw->cont (msgw->cont_cls,
1193  &msgw->session->target,
1194  GNUNET_SYSERR,
1195  msgw->payload, 0);
1196  GNUNET_STATISTICS_update (plugin->env->stats,
1197  "# UNIX bytes discarded",
1198  msgw->msgsize,
1199  GNUNET_NO);
1200  GNUNET_free (msgw->msg);
1201  GNUNET_free (msgw);
1202  return;
1203  }
1204  /* successfully sent bytes */
1205  GNUNET_break (sent > 0);
1206  GNUNET_STATISTICS_update (plugin->env->stats,
1207  "# bytes transmitted via UNIX",
1208  msgw->msgsize,
1209  GNUNET_NO);
1210  if (NULL != msgw->cont)
1211  msgw->cont (msgw->cont_cls,
1212  &msgw->session->target,
1213  GNUNET_OK,
1214  msgw->payload,
1215  msgw->msgsize);
1216  GNUNET_free (msgw->msg);
1217  GNUNET_free (msgw);
1218 }
1219 
1220 
1227 static void
1229 {
1230  struct Plugin *plugin = cls;
1231  const struct GNUNET_SCHEDULER_TaskContext *tc;
1232 
1233  plugin->read_task = NULL;
1235  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY))
1236  unix_plugin_do_read (plugin);
1237  plugin->read_task =
1239  plugin->unix_sock.desc,
1240  &unix_plugin_select_read, plugin);
1241 }
1242 
1243 
1250 static void
1252 {
1253  struct Plugin *plugin = cls;
1254  const struct GNUNET_SCHEDULER_TaskContext *tc;
1255 
1256  plugin->write_task = NULL;
1259  unix_plugin_do_write (plugin);
1260  if (NULL == plugin->msg_head)
1261  return; /* write queue empty */
1262  plugin->write_task =
1264  plugin->unix_sock.desc,
1265  &unix_plugin_select_write, plugin);
1266 }
1267 
1268 
1296 static ssize_t
1297 unix_plugin_send (void *cls,
1298  struct GNUNET_ATS_Session *session,
1299  const char *msgbuf,
1300  size_t msgbuf_size,
1301  unsigned int priority,
1302  struct GNUNET_TIME_Relative to,
1304  void *cont_cls)
1305 {
1306  struct Plugin *plugin = cls;
1307  struct UNIXMessageWrapper *wrapper;
1308  struct UNIXMessage *message;
1309  int ssize;
1310 
1311  if (GNUNET_OK !=
1313  &session->target,
1314  session))
1315  {
1317  "Invalid session for peer `%s' `%s'\n",
1318  GNUNET_i2s (&session->target),
1320  session->address->address,
1321  session->address->address_length));
1322  GNUNET_break (0);
1323  return GNUNET_SYSERR;
1324  }
1326  "Sending %u bytes with session for peer `%s' `%s'\n",
1327  msgbuf_size,
1328  GNUNET_i2s (&session->target),
1330  session->address->address,
1331  session->address->address_length));
1332  ssize = sizeof (struct UNIXMessage) + msgbuf_size;
1333  message = GNUNET_malloc (sizeof (struct UNIXMessage) + msgbuf_size);
1334  message->header.size = htons (ssize);
1335  message->header.type = htons (0);
1336  GNUNET_memcpy (&message->sender, plugin->env->my_identity,
1337  sizeof (struct GNUNET_PeerIdentity));
1338  GNUNET_memcpy (&message[1], msgbuf, msgbuf_size);
1339  wrapper = GNUNET_new (struct UNIXMessageWrapper);
1340  wrapper->msg = message;
1341  wrapper->msgsize = ssize;
1342  wrapper->payload = msgbuf_size;
1343  wrapper->priority = priority;
1345  to);
1346  wrapper->cont = cont;
1347  wrapper->cont_cls = cont_cls;
1348  wrapper->session = session;
1350  plugin->msg_tail,
1351  wrapper);
1352  plugin->bytes_in_queue += ssize;
1353  session->bytes_in_queue += ssize;
1354  session->msgs_in_queue++;
1355  GNUNET_STATISTICS_set (plugin->env->stats,
1356  "# bytes currently in UNIX buffers",
1357  plugin->bytes_in_queue,
1358  GNUNET_NO);
1359  notify_session_monitor (plugin,
1360  session,
1362  if (NULL == plugin->write_task)
1363  plugin->write_task =
1365  plugin->unix_sock.desc,
1366  &unix_plugin_select_write, plugin);
1367  return ssize;
1368 }
1369 
1370 
1377 static int
1379 {
1380  struct Plugin *plugin = cls;
1381  struct sockaddr_un *un;
1382  socklen_t un_len;
1383 
1385  &un_len);
1386  if (GNUNET_YES == plugin->is_abstract)
1387  {
1388  plugin->unix_socket_path[0] = '@';
1389  un->sun_path[0] = '\0';
1390  }
1391  plugin->unix_sock.desc =
1392  GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_DGRAM, 0);
1393  if (NULL == plugin->unix_sock.desc)
1394  {
1396  GNUNET_free (un);
1397  return GNUNET_SYSERR;
1398  }
1399  if ('\0' != un->sun_path[0])
1400  {
1401  if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (un->sun_path))
1402  {
1403  LOG (GNUNET_ERROR_TYPE_ERROR, _("Cannot create path to `%s'\n"),
1404  un->sun_path);
1406  plugin->unix_sock.desc = NULL;
1407  GNUNET_free (un);
1408  return GNUNET_SYSERR;
1409  }
1410  }
1411  if (GNUNET_OK !=
1413  (const struct sockaddr *) un, un_len))
1414  {
1416  LOG (GNUNET_ERROR_TYPE_ERROR, _("Cannot bind to `%s'\n"),
1417  un->sun_path);
1419  plugin->unix_sock.desc = NULL;
1420  GNUNET_free (un);
1421  return GNUNET_SYSERR;
1422  }
1424  "Bound to `%s'\n",
1425  plugin->unix_socket_path);
1426  plugin->read_task =
1428  plugin->unix_sock.desc,
1429  &unix_plugin_select_read, plugin);
1430  GNUNET_free (un);
1431  return 1;
1432 }
1433 
1434 
1451 static int
1453  const void *addr,
1454  size_t addrlen)
1455 {
1456  struct Plugin* plugin = cls;
1457  const struct UnixAddress *ua = addr;
1458  char *addrstr;
1459  size_t addr_str_len;
1460 
1461  if ( (NULL == addr) ||
1462  (0 == addrlen) ||
1463  (sizeof (struct UnixAddress) > addrlen) )
1464  {
1465  GNUNET_break (0);
1466  return GNUNET_SYSERR;
1467  }
1468  addrstr = (char *) &ua[1];
1469  addr_str_len = ntohl (ua->addrlen);
1470  if ('\0' != addrstr[addr_str_len - 1])
1471  {
1472  GNUNET_break (0);
1473  return GNUNET_SYSERR;
1474  }
1475  if (strlen (addrstr) + 1 != addr_str_len)
1476  {
1477  GNUNET_break (0);
1478  return GNUNET_SYSERR;
1479  }
1480 
1481  if (0 == strcmp (plugin->unix_socket_path, addrstr))
1482  return GNUNET_OK;
1483  return GNUNET_SYSERR;
1484 }
1485 
1486 
1501 static void
1503  const void *addr,
1504  size_t addrlen,
1505  int numeric,
1508  void *asc_cls)
1509 {
1510  const char *ret;
1511 
1512  if ( (NULL != addr) && (addrlen > 0))
1513  ret = unix_plugin_address_to_string (NULL,
1514  addr,
1515  addrlen);
1516  else
1517  ret = NULL;
1518  asc (asc_cls,
1519  ret,
1520  (NULL == ret) ? GNUNET_SYSERR : GNUNET_OK);
1521  asc (asc_cls, NULL, GNUNET_OK);
1522 }
1523 
1524 
1537 static int
1539  const char *addr,
1540  uint16_t addrlen,
1541  void **buf, size_t *added)
1542 {
1543  struct UnixAddress *ua;
1544  char *address;
1545  char *plugin;
1546  char *optionstr;
1547  uint32_t options;
1548  size_t ua_size;
1549 
1550  /* Format unix.options.address */
1551  address = NULL;
1552  plugin = NULL;
1553  optionstr = NULL;
1554 
1555  if ((NULL == addr) || (addrlen == 0))
1556  {
1557  GNUNET_break (0);
1558  return GNUNET_SYSERR;
1559  }
1560  if ('\0' != addr[addrlen - 1])
1561  {
1562  GNUNET_break (0);
1563  return GNUNET_SYSERR;
1564  }
1565  if (strlen (addr) != addrlen - 1)
1566  {
1567  GNUNET_break (0);
1568  return GNUNET_SYSERR;
1569  }
1570  plugin = GNUNET_strdup (addr);
1571  optionstr = strchr (plugin, '.');
1572  if (NULL == optionstr)
1573  {
1574  GNUNET_break (0);
1575  GNUNET_free (plugin);
1576  return GNUNET_SYSERR;
1577  }
1578  optionstr[0] = '\0';
1579  optionstr++;
1580  options = atol (optionstr);
1581  address = strchr (optionstr, '.');
1582  if (NULL == address)
1583  {
1584  GNUNET_break (0);
1585  GNUNET_free (plugin);
1586  return GNUNET_SYSERR;
1587  }
1588  address[0] = '\0';
1589  address++;
1590  if (0 != strcmp(plugin, PLUGIN_NAME))
1591  {
1592  GNUNET_break (0);
1593  GNUNET_free (plugin);
1594  return GNUNET_SYSERR;
1595  }
1596 
1597  ua_size = sizeof (struct UnixAddress) + strlen (address) + 1;
1598  ua = GNUNET_malloc (ua_size);
1599  ua->options = htonl (options);
1600  ua->addrlen = htonl (strlen (address) + 1);
1601  GNUNET_memcpy (&ua[1], address, strlen (address) + 1);
1602  GNUNET_free (plugin);
1603 
1604  (*buf) = ua;
1605  (*added) = ua_size;
1606  return GNUNET_OK;
1607 }
1608 
1609 
1615 static void
1617 {
1618  struct Plugin *plugin = cls;
1619  struct GNUNET_HELLO_Address *address;
1620  size_t len;
1621  struct UnixAddress *ua;
1622  char *unix_path;
1623 
1624  len = sizeof (struct UnixAddress) + strlen (plugin->unix_socket_path) + 1;
1625  ua = GNUNET_malloc (len);
1626  ua->options = htonl (plugin->myoptions);
1627  ua->addrlen = htonl(strlen (plugin->unix_socket_path) + 1);
1628  unix_path = (char *) &ua[1];
1629  GNUNET_memcpy (unix_path, plugin->unix_socket_path, strlen (plugin->unix_socket_path) + 1);
1630 
1631  plugin->address_update_task = NULL;
1632  address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
1633  PLUGIN_NAME,
1634  ua,
1635  len,
1637  plugin->env->notify_address (plugin->env->cls,
1638  GNUNET_YES,
1639  address);
1640  GNUNET_free (ua);
1641  GNUNET_free (address);
1642 }
1643 
1644 
1653 static int
1655  const struct GNUNET_PeerIdentity *key,
1656  void *value)
1657 {
1658  struct Plugin *plugin = cls;
1659  struct GNUNET_ATS_Session *session = value;
1660 
1661  unix_plugin_session_disconnect (plugin, session);
1662  return GNUNET_YES;
1663 }
1664 
1665 
1673 static void
1675  const struct GNUNET_PeerIdentity *target)
1676 {
1677  struct Plugin *plugin = cls;
1678 
1680  target,
1681  &get_session_delete_it, plugin);
1682 }
1683 
1684 
1694 static int
1696  const struct GNUNET_PeerIdentity *peer,
1697  void *value)
1698 {
1699  struct Plugin *plugin = cls;
1700  struct GNUNET_ATS_Session *session = value;
1701 
1702  notify_session_monitor (plugin,
1703  session,
1705  notify_session_monitor (plugin,
1706  session,
1708  return GNUNET_OK;
1709 }
1710 
1711 
1724 static void
1727  void *sic_cls)
1728 {
1729  struct Plugin *plugin = cls;
1730 
1731  plugin->sic = sic;
1732  plugin->sic_cls = sic_cls;
1733  if (NULL != sic)
1734  {
1737  plugin);
1738  /* signal end of first iteration */
1739  sic (sic_cls, NULL, NULL);
1740  }
1741 }
1742 
1743 
1751 void *
1753 {
1756  struct Plugin *plugin;
1757  int sockets_created;
1758 
1759  if (NULL == env->receive)
1760  {
1761  /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
1762  initialze the plugin or the API */
1764  api->cls = NULL;
1768  return api;
1769  }
1770 
1771  plugin = GNUNET_new (struct Plugin);
1772  if (GNUNET_OK !=
1774  "transport-unix",
1775  "UNIXPATH",
1776  &plugin->unix_socket_path))
1777  {
1779  "transport-unix",
1780  "UNIXPATH");
1781  GNUNET_free (plugin);
1782  return NULL;
1783  }
1784 
1785  plugin->env = env;
1786 
1787  /* Initialize my flags */
1788 #ifdef LINUX
1790  "testing",
1791  "USE_ABSTRACT_SOCKETS");
1792 #endif
1793  plugin->myoptions = UNIX_OPTIONS_NONE;
1794  if (GNUNET_YES == plugin->is_abstract)
1796 
1798  api->cls = plugin;
1800  api->send = &unix_plugin_send;
1812  sockets_created = unix_transport_server_start (plugin);
1813  if ((0 == sockets_created) || (GNUNET_SYSERR == sockets_created))
1814  {
1816  _("Failed to open UNIX listen socket\n"));
1817  GNUNET_free (api);
1818  GNUNET_free (plugin->unix_socket_path);
1819  GNUNET_free (plugin);
1820  return NULL;
1821  }
1824  plugin);
1825  return api;
1826 }
1827 
1828 
1835 void *
1837 {
1838  struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1839  struct Plugin *plugin = api->cls;
1840  struct GNUNET_HELLO_Address *address;
1841  struct UNIXMessageWrapper * msgw;
1842  struct UnixAddress *ua;
1843  size_t len;
1844  struct GNUNET_ATS_Session *session;
1845 
1846  if (NULL == plugin)
1847  {
1848  GNUNET_free (api);
1849  return NULL;
1850  }
1851  len = sizeof (struct UnixAddress) + strlen (plugin->unix_socket_path) + 1;
1852  ua = GNUNET_malloc (len);
1853  ua->options = htonl (plugin->myoptions);
1854  ua->addrlen = htonl(strlen (plugin->unix_socket_path) + 1);
1855  GNUNET_memcpy (&ua[1],
1856  plugin->unix_socket_path,
1857  strlen (plugin->unix_socket_path) + 1);
1858  address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
1859  PLUGIN_NAME,
1860  ua, len,
1862  plugin->env->notify_address (plugin->env->cls,
1863  GNUNET_NO,
1864  address);
1865 
1866  GNUNET_free (address);
1867  GNUNET_free (ua);
1868 
1869  while (NULL != (msgw = plugin->msg_head))
1870  {
1871  GNUNET_CONTAINER_DLL_remove (plugin->msg_head,
1872  plugin->msg_tail,
1873  msgw);
1874  session = msgw->session;
1875  session->msgs_in_queue--;
1876  GNUNET_assert (session->bytes_in_queue >= msgw->msgsize);
1877  session->bytes_in_queue -= msgw->msgsize;
1878  GNUNET_assert (plugin->bytes_in_queue >= msgw->msgsize);
1879  plugin->bytes_in_queue -= msgw->msgsize;
1880  if (NULL != msgw->cont)
1881  msgw->cont (msgw->cont_cls,
1882  &msgw->session->target,
1883  GNUNET_SYSERR,
1884  msgw->payload, 0);
1885  GNUNET_free (msgw->msg);
1886  GNUNET_free (msgw);
1887  }
1888 
1889  if (NULL != plugin->read_task)
1890  {
1891  GNUNET_SCHEDULER_cancel (plugin->read_task);
1892  plugin->read_task = NULL;
1893  }
1894  if (NULL != plugin->write_task)
1895  {
1896  GNUNET_SCHEDULER_cancel (plugin->write_task);
1897  plugin->write_task = NULL;
1898  }
1899  if (NULL != plugin->address_update_task)
1900  {
1901  GNUNET_SCHEDULER_cancel (plugin->address_update_task);
1902  plugin->address_update_task = NULL;
1903  }
1904  if (NULL != plugin->unix_sock.desc)
1905  {
1907  GNUNET_NETWORK_socket_close (plugin->unix_sock.desc));
1908  plugin->unix_sock.desc = NULL;
1909  }
1910  GNUNET_CONTAINER_multipeermap_iterate (plugin->session_map,
1912  plugin);
1913  GNUNET_CONTAINER_multipeermap_destroy (plugin->session_map);
1914  GNUNET_break (0 == plugin->bytes_in_queue);
1915  GNUNET_free (plugin->unix_socket_path);
1916  GNUNET_free (plugin);
1917  GNUNET_free (api);
1918  return NULL;
1919 }
1920 
1921 /* end of plugin_transport_unix.c */
static void session_timeout(void *cls)
Session was idle for too long, so disconnect it.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
size_t address_length
Number of bytes in address.
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:1005
uint32_t addrlen
Length of the address (path length), in NBO.
Session is being torn down and about to disappear.
const struct GNUNET_SCHEDULER_TaskContext * GNUNET_SCHEDULER_get_task_context(void)
Obtain the reasoning why the current task was started.
Definition: scheduler.c:746
GNUNET_TRANSPORT_SessionInfoCallback sic
Function to call about session status changes.
Information we keep for each of our listen sockets.
#define PLUGIN_NAME
Name of the plugin.
uint32_t num_bytes_pending
Number of bytes pending transmission for this session.
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...
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
GNUNET_TRANSPORT_CreateSession get_session
Function that will be called tell the plugin to create a session object.
GNUNET_TRANSPORT_AddressToString address_to_string
Function that will be called to convert a binary address to a string (numeric conversion only)...
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:73
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
uint64_t rel_value_us
The actual value.
const void * address
Binary representation of the address (plugin-specific).
#define RETRY
Return code we give on &#39;send&#39; if we failed to send right now but it makes sense to retry later...
GNUNET_TRANSPORT_TransmitContinuation cont
Function to call upon transmission.
common internal definitions for transport service
unsigned int msgs_in_queue
Number of messages waiting for transmission to this peer.
static void unix_plugin_select_write(void *cls)
We have been notified that our socket is ready to write.
struct GNUNET_SCHEDULER_Task * timeout_task
Session timeout task.
struct GNUNET_NETWORK_Handle * desc
The network handle.
char * unix_socket_path
Path of our unix domain socket (/tmp/unix-plugin)
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
#define LOG(kind,...)
The reading socket is ready.
Context information passed to each scheduler task.
struct Plugin * plugin
Pointer to the global plugin struct.
struct GNUNET_ATS_Session * next
Stored in a linked list.
struct GNUNET_MessageHeader header
Message header.
GNUNET_TRANSPORT_TransmitFunction send
Function that the transport service will use to transmit data to another peer.
struct UNIXMessage * msg
The actual payload (allocated separately right now).
GNUNET_TRANSPORT_DisconnectPeerFunction disconnect_peer
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
struct GNUNET_TIME_Absolute timeout
Timeout for this message.
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 int get_session_delete_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Function called on sessions to disconnect.
int is_inbound
GNUNET_YES if this is an inbound connection, GNUNET_NO if this is an outbound connection, GNUNET_SYSERR if connections of this plugin are so fundamentally bidirectional that they have no &#39;initiator&#39;
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:245
enum GNUNET_TRANSPORT_SessionState state
New state of the session.
struct GNUNET_ATS_Session * prev
Stored in a linked list.
No special options.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define STRERROR(i)
Definition: plibc.h:676
static void unix_plugin_select_read(void *cls)
We have been notified that our socket has something to read.
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:417
GNUNET_TRANSPORT_DisconnectSessionFunction disconnect_session
Function that can be used to force the plugin to disconnect from the given peer and cancel all previo...
size_t msgsize
Number of bytes in msg.
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
GNUNET_TRANSPORT_SessionMonitorSetup setup_monitor
Function to monitor the sessions managed by the plugin.
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:763
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:522
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:1548
struct GNUNET_TIME_Absolute timeout
When does this session time out.
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:833
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:81
static int numeric
Option -n.
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.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Add a given relative duration to the given start time.
Definition: time.c:393
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct GNUNET_HELLO_Address * address
Address.
unsigned int priority
Priority of the message (ignored, just dragged along in UNIX).
struct GNUNET_SCHEDULER_Task * read_task
ID of read task.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
const struct GNUNET_HELLO_Address * address
Address used by the session.
unsigned long long bytes_in_queue
Number of bytes waiting for transmission to this peer.
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
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
enum GNUNET_SCHEDULER_Reason reason
Reason why the task is run now.
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:35
uint32_t num_msg_pending
Number of messages pending transmission for this session.
#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 * address_update_task
ID of task used to update our addresses when one expires.
Binary format for an UNIX Domain Socket address in GNUnet.
#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.
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47
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.
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
GNUNET_TRANSPORT_PluginReceiveCallback receive
Function that should be called by the transport plugin whenever a message is received.
GNUNET_TRANSPORT_UpdateSessionTimeout update_session_timeout
Function that will be called whenever the transport service wants to notify the plugin that a session...
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 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 struct GNUNET_ATS_SolverFunctions * plugin
Our solver.
#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...
Information about a plugin&#39;s session.
int GNUNET_HELLO_address_cmp(const struct GNUNET_HELLO_Address *a1, const struct GNUNET_HELLO_Address *a2)
Compare two addresses.
Definition: address.c:130
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:1246
void * cls
Closure for the various callbacks.
enum State state
current state of profiling
struct UNIXMessageWrapper * msg_head
Head of queue of messages to transmit.
UNIX Message-Packet header.
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition: gnunet-arm.c:114
void * cls
Closure for all of the callbacks.
static unsigned int csize
#define GNUNET_memcpy(dst, src, n)
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
struct UNIX_Sock_Info unix_sock
socket that we transmit all data with
static void address_notification(void *cls)
Notify transport service about address.
static char * value
Value of the record to add/remove.
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_StringToAddress string_to_address
Function that will be called to convert a string address to binary (numeric conversion only)...
struct GNUNET_CONTAINER_MultiPeerMap * session_map
Sessions (map from peer identity to struct GNUNET_ATS_Session)
Information about ongoing sessions of the transport client.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
static struct sockaddr_un * unix_address_to_sockaddr(const char *unixpath, socklen_t *sock_len)
Convert unix path to a struct sockaddr_un *
struct GNUNET_DATACACHE_PluginEnvironment * env
Our execution environment.
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:1273
The transport service will pass a pointer to a struct of this type as the first and only argument to ...
static void unix_plugin_peer_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
Disconnect from a remote node.
GNUNET_TRANSPORT_GetNetworkType get_network
Function to obtain the network type for a session.
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:727
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:968
static char buf[2048]
static struct GNUNET_ATS_Session * lookup_session(struct Plugin *plugin, const struct GNUNET_HELLO_Address *address)
Find an existing session by address.
Information we track for a message awaiting transmission.
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 ...
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
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)...
static enum GNUNET_NetworkType unix_plugin_get_network(void *cls, struct GNUNET_ATS_Session *session)
Function obtain the network type for a session.
struct GNUNET_TIME_Absolute session_timeout
At what time will this session timeout (unless activity happens)?
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 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...
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
void * cont_cls
Closure for cont.
struct UNIXMessageWrapper * prev
We keep messages in a doubly linked list.
The writing socket is ready.
static void unix_plugin_setup_monitor(void *cls, GNUNET_TRANSPORT_SessionInfoCallback sic, void *sic_cls)
Begin monitoring sessions of a plugin.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
uint32_t options
Options to use for the address, in NBO.
struct GNUNET_HashCode key
The key used in the DHT.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static unsigned int size
Size of the "table".
Definition: peer.c:67
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 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.
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
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".
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
static struct GNUNET_SCHEDULER_Task * timeout_task
Task to be run on timeout.
Definition: gnunet-arm.c:119
size_t payload
Number of bytes of payload encapsulated in msg.
int is_abstract
Are we using an abstract UNIX domain socket?
static void reschedule_session_timeout(struct GNUNET_ATS_Session *session)
Increment session timeout due to activity.
Loopback (same host).
Definition: gnunet_nt_lib.h:45
struct GNUNET_PeerIdentity peer
For which peer is this an address?
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...
static unsigned long long payload
How much data are we currently storing in the database?
struct GNUNET_SCHEDULER_Task * write_task
ID of write task.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
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...
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...
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.
This is just an update about the session, the state did not change.
#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 void unix_plugin_do_read(struct Plugin *plugin)
Read from UNIX domain socket (it is ready).
static unsigned int unix_plugin_query_keepalive_factor(void *cls)
Function that is called to get the keepalive factor.
const struct GNUNET_HELLO_Address * address
Address we are looking for.
GNUNET_TRANSPORT_QueryKeepaliveFactorFunction query_keepalive_factor
Function that is used to query keepalive factor.
The identity of the host (wraps the signing key of the peer).
No additional information.
int 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.
#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...
#define GNUNET_PACKED
gcc-ism to get packed structs.
unsigned long long bytes_in_queue
Number of bytes we currently have in our write queues.
Handle for a plugin.
Definition: block.c:37
Linux abstract domain sockets should be used.
struct GNUNET_PeerIdentity target
To whom are we talking to.
static struct GNUNET_NETWORK_Handle * unix_sock
socket that we transmit all data with
An address for communicating with a peer.
static int lookup_session_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Function called to find a session by address.
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_copy(const struct GNUNET_HELLO_Address *address)
Copy an address struct.
Definition: address.c:109
The session was created (first call for each session object).
Entry in list of pending tasks.
Definition: scheduler.c:134
struct Queue * res
Location to store the queue, if found.
struct GNUNET_ATS_Session * session
Session this message belongs to.
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.
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&#39;ve got the address and send_handle squared away! ...
handle to a socket
Definition: network.c:46
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.
struct UNIXMessageWrapper * next
We keep messages in a doubly linked list.
static void unix_plugin_do_write(struct Plugin *plugin)
Write to UNIX domain socket (it is ready).
void * libgnunet_plugin_transport_unix_init(void *cls)
The exported method.
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
void * cls
Closure to use for callbacks.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
GNUNET_TRANSPORT_AddressPrettyPrinter address_pretty_printer
Function to pretty-print addresses.
Header for all communications.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:80
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:1478
struct GNUNET_ATS_Session * res
Location to store the session, if found.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
uint32_t myoptions
Address options.
GNUNET_TRANSPORT_CheckAddress check_address
Function that will be called to check if a binary address for this plugin is well-formed and correspo...
GNUNET_TRANSPORT_SessionState
Possible states of a session in a plugin.
int 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".
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:856
static int unix_transport_server_start(void *cls)
Create a slew of UNIX sockets.
UNIX_ADDRESS_OPTIONS
Options for UNIX Domain addresses.
struct GNUNET_PeerIdentity sender
What is the identity of the sender (GNUNET_hash of public key)
static char * address
GNS address for this phone.
void * libgnunet_plugin_transport_unix_done(void *cls)
Shutdown the plugin.
struct UNIXMessageWrapper * msg_tail
Tail of queue of messages to transmit.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:604
#define GNUNET_HELLO_address_free(addr)
Free an address.
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.
void * sic_cls
Closure for sic.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
GNUNET_TRANSPORT_GetNetworkTypeForAddress get_network_for_address
Function to obtain the network type for an address.
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:1037
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965