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 
59 
64 };
65 
66 
70 #define HOSTNAME_RESOLVE_TIMEOUT \
71  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 
81 struct UnixAddress {
86 
91 
92  /* followed by actual path */
93 };
94 
95 
99 struct UNIXMessage {
103  struct GNUNET_MessageHeader header;
104 
108  struct GNUNET_PeerIdentity sender;
109 };
110 
112 
113 
122 
127 
131  struct UNIXMessage *msg;
132 
137 
142 
146  void *cont_cls;
147 
152 
156  size_t msgsize;
157 
161  size_t payload;
162 
166  unsigned int priority;
167 };
168 
169 
173 struct GNUNET_ATS_Session {
177  struct GNUNET_ATS_Session *next;
178 
182  struct GNUNET_ATS_Session *prev;
183 
190  struct GNUNET_PeerIdentity target;
191 
195  struct Plugin *plugin;
196 
201 
205  unsigned long long bytes_in_queue;
206 
210  struct GNUNET_TIME_Absolute timeout;
211 
216 
220  unsigned int msgs_in_queue;
221 };
222 
223 
227 struct Plugin;
228 
229 
238 };
239 
240 
244 struct Plugin {
248  struct GNUNET_SCHEDULER_Task *address_update_task;
249 
254 
259 
263  unsigned long long bytes_in_queue;
264 
269 
274 
279 
284 
289 
294 
298  void *sic_cls;
299 
304 
308  uint32_t myoptions;
309 
314 };
315 
316 
325 static void
327  struct GNUNET_ATS_Session *session,
329 {
330  struct GNUNET_TRANSPORT_SessionInfo info;
331 
332  if (NULL == plugin->sic)
333  return;
334  memset(&info, 0, sizeof(info));
335  info.state = state;
336  info.is_inbound = GNUNET_SYSERR; /* hard to say */
337  info.num_msg_pending = session->msgs_in_queue;
338  info.num_bytes_pending = session->bytes_in_queue;
339  /* info.receive_delay remains zero as this is not supported by UNIX
340  (cannot selectively not receive from 'some' peer while continuing
341  to receive from others) */
342  info.session_timeout = session->timeout;
343  info.address = session->address;
344  plugin->sic(plugin->sic_cls, session, &info);
345 }
346 
347 
359 static const char *
360 unix_plugin_address_to_string(void *cls, const void *addr, size_t addrlen)
361 {
362  static char rbuf[1024];
363  struct UnixAddress *ua = (struct UnixAddress *)addr;
364  char *addrstr;
365  size_t addr_str_len;
366  unsigned int off;
367 
368  if ((NULL == addr) || (sizeof(struct UnixAddress) > addrlen))
369  {
370  GNUNET_break(0);
371  return NULL;
372  }
373  addrstr = (char *)&ua[1];
374  addr_str_len = ntohl(ua->addrlen);
375 
376  if (addr_str_len != addrlen - sizeof(struct UnixAddress))
377  {
378  GNUNET_break(0);
379  return NULL;
380  }
381  if ('\0' != addrstr[addr_str_len - 1])
382  {
383  GNUNET_break(0);
384  return NULL;
385  }
386  if (strlen(addrstr) + 1 != addr_str_len)
387  {
388  GNUNET_break(0);
389  return NULL;
390  }
391 
392  off = 0;
393  if ('\0' == addrstr[0])
394  off++;
395  memset(rbuf, 0, sizeof(rbuf));
396  GNUNET_snprintf(rbuf,
397  sizeof(rbuf) - 1,
398  "%s.%u.%s%.*s",
399  PLUGIN_NAME,
400  ntohl(ua->options),
401  (off == 1) ? "@" : "",
402  (int)(addr_str_len - off),
403  &addrstr[off]);
404  return rbuf;
405 }
406 
407 
417 static int
419 {
420  struct Plugin *plugin = cls;
421  struct UNIXMessageWrapper *msgw;
422  struct UNIXMessageWrapper *next;
423 
425  "Disconnecting session for peer `%s' `%s'\n",
426  GNUNET_i2s(&session->target),
428  session->address->address,
429  session->address->address_length));
430  plugin->env->session_end(plugin->env->cls, session->address, session);
431  next = plugin->msg_head;
432  while (NULL != next)
433  {
434  msgw = next;
435  next = msgw->next;
436  if (msgw->session != session)
437  continue;
438  GNUNET_CONTAINER_DLL_remove(plugin->msg_head, plugin->msg_tail, msgw);
439  session->msgs_in_queue--;
440  GNUNET_assert(session->bytes_in_queue >= msgw->msgsize);
441  session->bytes_in_queue -= msgw->msgsize;
442  GNUNET_assert(plugin->bytes_in_queue >= msgw->msgsize);
443  plugin->bytes_in_queue -= msgw->msgsize;
444  if (NULL != msgw->cont)
445  msgw->cont(msgw->cont_cls,
446  &msgw->session->target,
448  msgw->payload,
449  0);
450  GNUNET_free(msgw->msg);
451  GNUNET_free(msgw);
452  }
455  &session->target,
456  session));
457  GNUNET_STATISTICS_set(plugin->env->stats,
458  "# UNIX sessions active",
460  plugin->session_map),
461  GNUNET_NO);
462  if (NULL != session->timeout_task)
463  {
465  session->timeout_task = NULL;
467  }
470  GNUNET_break(0 == session->bytes_in_queue);
471  GNUNET_break(0 == session->msgs_in_queue);
472  GNUNET_free(session);
473  return GNUNET_OK;
474 }
475 
476 
482 static void
483 session_timeout(void *cls)
484 {
485  struct GNUNET_ATS_Session *session = cls;
486  struct GNUNET_TIME_Relative left;
487 
488  session->timeout_task = NULL;
490  if (0 != left.rel_value_us)
491  {
492  /* not actually our turn yet, but let's at least update
493  the monitor, it may think we're about to die ... */
495  session,
497  session->timeout_task =
499  return;
500  }
502  "Session %p was idle for %s, disconnecting\n",
503  session,
506  GNUNET_YES));
507  unix_plugin_session_disconnect(session->plugin, session);
508 }
509 
510 
518 static void
520 {
521  GNUNET_assert(NULL != session->timeout_task);
522  session->timeout =
524 }
525 
526 
534 static struct sockaddr_un *
535 unix_address_to_sockaddr(const char *unixpath, socklen_t *sock_len)
536 {
537  struct sockaddr_un *un;
538  size_t slen;
539 
540  GNUNET_assert(0 < strlen(unixpath)); /* sanity check */
541  un = GNUNET_new(struct sockaddr_un);
542  un->sun_family = AF_UNIX;
543  slen = strlen(unixpath);
544  if (slen >= sizeof(un->sun_path))
545  slen = sizeof(un->sun_path) - 1;
546  GNUNET_memcpy(un->sun_path, unixpath, slen);
547  un->sun_path[slen] = '\0';
548  slen = sizeof(struct sockaddr_un);
549 #if HAVE_SOCKADDR_UN_SUN_LEN
550  un->sun_len = (u_char)slen;
551 #endif
552  (*sock_len) = slen;
553  return un;
554 }
555 
556 
560 struct LookupCtx {
565 
570 };
571 
572 
581 static int
583  const struct GNUNET_PeerIdentity *key,
584  void *value)
585 {
586  struct LookupCtx *lctx = cls;
587  struct GNUNET_ATS_Session *session = value;
588 
589  if (0 == GNUNET_HELLO_address_cmp(lctx->address, session->address))
590  {
591  lctx->res = session;
592  return GNUNET_NO;
593  }
594  return GNUNET_YES;
595 }
596 
597 
605 static struct GNUNET_ATS_Session *
607  const struct GNUNET_HELLO_Address *address)
608 {
609  struct LookupCtx lctx;
610 
611  lctx.address = address;
612  lctx.res = NULL;
614  &address->peer,
616  &lctx);
617  return lctx.res;
618 }
619 
620 
629 static unsigned int
631 {
632  return 3;
633 }
634 
635 
657 static ssize_t
658 unix_real_send(void *cls,
659  struct GNUNET_NETWORK_Handle *send_handle,
660  const struct GNUNET_PeerIdentity *target,
661  const char *msgbuf,
662  size_t msgbuf_size,
663  unsigned int priority,
665  const struct UnixAddress *addr,
666  size_t addrlen,
667  size_t payload,
669  void *cont_cls)
670 {
671  struct Plugin *plugin = cls;
672  ssize_t sent;
673  struct sockaddr_un *un;
674  socklen_t un_len;
675  const char *unixpath;
676 
677  if (NULL == send_handle)
678  {
679  GNUNET_break(0); /* We do not have a send handle */
680  return GNUNET_SYSERR;
681  }
682  if ((NULL == addr) || (0 == addrlen))
683  {
684  GNUNET_break(0); /* Can never send if we don't have an address */
685  return GNUNET_SYSERR;
686  }
687 
688  /* Prepare address */
689  unixpath = (const char *)&addr[1];
690  if (NULL == (un = unix_address_to_sockaddr(unixpath, &un_len)))
691  {
692  GNUNET_break(0);
693  return -1;
694  }
695 
696  if ((GNUNET_YES == plugin->is_abstract) &&
697  (0 != (UNIX_OPTIONS_USE_ABSTRACT_SOCKETS & ntohl(addr->options))))
698  {
699  un->sun_path[0] = '\0';
700  }
701 resend:
702  /* Send the data */
703  sent = GNUNET_NETWORK_socket_sendto(send_handle,
704  msgbuf,
705  msgbuf_size,
706  (const struct sockaddr *)un,
707  un_len);
708  if (GNUNET_SYSERR == sent)
709  {
710  if ((EAGAIN == errno) || (ENOBUFS == errno))
711  {
712  GNUNET_free(un);
713  return RETRY; /* We have to retry later */
714  }
715  if (EMSGSIZE == errno)
716  {
717  socklen_t size = 0;
718  socklen_t len = sizeof(size);
719 
721  send_handle,
722  SOL_SOCKET,
723  SO_SNDBUF,
724  &size,
725  &len);
726  if (size < msgbuf_size)
727  {
729  "Trying to increase socket buffer size from %u to %u for message size %u\n",
730  (unsigned int)size,
731  (unsigned int)((msgbuf_size / 1000) + 2) * 1000,
732  (unsigned int)msgbuf_size);
733  size = ((msgbuf_size / 1000) + 2) * 1000;
734  if (GNUNET_OK ==
736  send_handle,
737  SOL_SOCKET,
738  SO_SNDBUF,
739  &size,
740  sizeof(size)))
741  goto resend; /* Increased buffer size, retry sending */
742  else
743  {
744  /* Could not increase buffer size: error, no retry */
746  GNUNET_free(un);
747  return GNUNET_SYSERR;
748  }
749  }
750  else
751  {
752  /* Buffer is bigger than message: error, no retry
753  * This should never happen!*/
754  GNUNET_break(0);
755  GNUNET_free(un);
756  return GNUNET_SYSERR;
757  }
758  }
759  }
760 
762  "UNIX transmitted %u-byte message to %s (%d: %s)\n",
763  (unsigned int)msgbuf_size,
764  GNUNET_a2s((const struct sockaddr *)un, un_len),
765  (int)sent,
766  (sent < 0) ? strerror(errno) : "ok");
767  GNUNET_free(un);
768  return sent;
769 }
770 
771 
779 static enum GNUNET_NetworkType
780 unix_plugin_get_network(void *cls, struct GNUNET_ATS_Session *session)
781 {
782  GNUNET_assert(NULL != session);
783  return GNUNET_NT_LOOPBACK;
784 }
785 
786 
794 static enum GNUNET_NetworkType
796  const struct GNUNET_HELLO_Address *address)
797 {
798  return GNUNET_NT_LOOPBACK;
799 }
800 
801 
810 static struct GNUNET_ATS_Session *
812 {
813  struct Plugin *plugin = cls;
814  struct GNUNET_ATS_Session *session;
815  struct UnixAddress *ua;
816  char *addrstr;
817  uint32_t addr_str_len;
818  uint32_t addr_option;
819 
820  ua = (struct UnixAddress *)address->address;
821  if ((NULL == address->address) || (0 == address->address_length) ||
822  (sizeof(struct UnixAddress) > address->address_length))
823  {
824  GNUNET_break(0);
825  return NULL;
826  }
827  addrstr = (char *)&ua[1];
828  addr_str_len = ntohl(ua->addrlen);
829  addr_option = ntohl(ua->options);
830 
831  if ((0 != (UNIX_OPTIONS_USE_ABSTRACT_SOCKETS & addr_option)) &&
832  (GNUNET_NO == plugin->is_abstract))
833  {
834  return NULL;
835  }
836 
837  if (addr_str_len != address->address_length - sizeof(struct UnixAddress))
838  {
839  return NULL; /* This can be a legacy address */
840  }
841 
842  if ('\0' != addrstr[addr_str_len - 1])
843  {
844  GNUNET_break(0);
845  return NULL;
846  }
847  if (strlen(addrstr) + 1 != addr_str_len)
848  {
849  GNUNET_break(0);
850  return NULL;
851  }
852 
853  /* Check if a session for this address already exists */
854  if (NULL != (session = lookup_session(plugin, address)))
855  {
857  "Found existing session %p for address `%s'\n",
858  session,
860  address->address,
861  address->address_length));
862  return session;
863  }
864 
865  /* create a new session */
866  session = GNUNET_new(struct GNUNET_ATS_Session);
867  session->target = address->peer;
868  session->address = GNUNET_HELLO_address_copy(address);
869  session->plugin = plugin;
870  session->timeout =
872  session->timeout_task =
875  session);
877  "Creating a new session %p for address `%s'\n",
878  session,
880  address->address,
881  address->address_length));
883  plugin->session_map,
884  &address->peer,
885  session,
887  GNUNET_STATISTICS_set(plugin->env->stats,
888  "# UNIX sessions active",
890  plugin->session_map),
891  GNUNET_NO);
894  return session;
895 }
896 
897 
907 static void
909  const struct GNUNET_PeerIdentity *peer,
910  struct GNUNET_ATS_Session *session)
911 {
912  struct Plugin *plugin = cls;
913 
914  if (GNUNET_OK !=
916  &session->target,
917  session))
918  {
919  GNUNET_break(0);
920  return;
921  }
923 }
924 
925 
935 static void
937  struct GNUNET_PeerIdentity *sender,
938  const struct GNUNET_MessageHeader *currhdr,
939  const struct UnixAddress *ua,
940  size_t ua_len)
941 {
942  struct GNUNET_ATS_Session *session;
944 
945  GNUNET_assert(ua_len >= sizeof(struct UnixAddress));
947  "Received message from %s\n",
948  unix_plugin_address_to_string(NULL, ua, ua_len));
949  GNUNET_STATISTICS_update(plugin->env->stats,
950  "# bytes received via UNIX",
951  ntohs(currhdr->size),
952  GNUNET_NO);
953 
954  /* Look for existing session */
956  sender,
957  PLUGIN_NAME,
958  ua,
959  ua_len,
960  GNUNET_HELLO_ADDRESS_INFO_NONE); /* UNIX does not have "inbound" sessions */
961  session = lookup_session(plugin, address);
962  if (NULL == session)
963  {
964  session = unix_plugin_get_session(plugin, address);
965  /* Notify transport and ATS about new inbound session */
966  plugin->env->session_start(NULL,
967  session->address,
968  session,
970  }
971  else
972  {
974  }
975  GNUNET_HELLO_address_free(address);
976  plugin->env->receive(plugin->env->cls, session->address, session, currhdr);
977 }
978 
979 
985 static void
987 {
988  char buf[65536] GNUNET_ALIGN;
989  struct UnixAddress *ua;
990  struct UNIXMessage *msg;
991  struct GNUNET_PeerIdentity sender;
992  struct sockaddr_un un;
993  socklen_t addrlen;
994  ssize_t ret;
995  int offset;
996  int tsize;
997  int is_abstract;
998  char *msgbuf;
999  const struct GNUNET_MessageHeader *currhdr;
1000  uint16_t csize;
1001  size_t ua_len;
1002 
1003  addrlen = sizeof(un);
1004  memset(&un, 0, sizeof(un));
1006  buf,
1007  sizeof(buf),
1008  (struct sockaddr *)&un,
1009  &addrlen);
1010  if ((GNUNET_SYSERR == ret) && ((errno == EAGAIN) || (errno == ENOBUFS)))
1011  return;
1012  if (GNUNET_SYSERR == ret)
1013  {
1015  return;
1016  }
1017  else
1018  {
1020  "Read %d bytes from socket %s\n",
1021  (int)ret,
1022  un.sun_path);
1023  }
1024 
1025  GNUNET_assert(AF_UNIX == (un.sun_family));
1026  is_abstract = GNUNET_NO;
1027  if ('\0' == un.sun_path[0])
1028  {
1029  un.sun_path[0] = '@';
1030  is_abstract = GNUNET_YES;
1031  }
1032 
1033  ua_len = sizeof(struct UnixAddress) + strlen(un.sun_path) + 1;
1034  ua = GNUNET_malloc(ua_len);
1035  ua->addrlen = htonl(strlen(&un.sun_path[0]) + 1);
1036  GNUNET_memcpy(&ua[1], &un.sun_path[0], strlen(un.sun_path) + 1);
1037  if (is_abstract)
1038  ua->options = htonl(UNIX_OPTIONS_USE_ABSTRACT_SOCKETS);
1039  else
1040  ua->options = htonl(UNIX_OPTIONS_NONE);
1041 
1042  msg = (struct UNIXMessage *)buf;
1043  csize = ntohs(msg->header.size);
1044  if ((csize < sizeof(struct UNIXMessage)) || (csize > ret))
1045  {
1046  GNUNET_break_op(0);
1047  GNUNET_free(ua);
1048  return;
1049  }
1050  msgbuf = (char *)&msg[1];
1051  GNUNET_memcpy(&sender, &msg->sender, sizeof(struct GNUNET_PeerIdentity));
1052  offset = 0;
1053  tsize = csize - sizeof(struct UNIXMessage);
1054  while (offset + sizeof(struct GNUNET_MessageHeader) <= tsize)
1055  {
1056  currhdr = (struct GNUNET_MessageHeader *)&msgbuf[offset];
1057  csize = ntohs(currhdr->size);
1058  if ((csize < sizeof(struct GNUNET_MessageHeader)) ||
1059  (csize > tsize - offset))
1060  {
1061  GNUNET_break_op(0);
1062  break;
1063  }
1064  unix_demultiplexer(plugin, &sender, currhdr, ua, ua_len);
1065  offset += csize;
1066  }
1067  GNUNET_free(ua);
1068 }
1069 
1070 
1076 static void
1078 {
1079  ssize_t sent = 0;
1080  struct UNIXMessageWrapper *msgw;
1081  struct GNUNET_ATS_Session *session;
1082  int did_delete;
1083 
1084  session = NULL;
1085  did_delete = GNUNET_NO;
1086  while (NULL != (msgw = plugin->msg_head))
1087  {
1089  break; /* Message is ready for sending */
1090  /* Message has a timeout */
1091  did_delete = GNUNET_YES;
1093  "Timeout for message with %u bytes \n",
1094  (unsigned int)msgw->msgsize);
1095  GNUNET_CONTAINER_DLL_remove(plugin->msg_head, plugin->msg_tail, msgw);
1096  session = msgw->session;
1097  session->msgs_in_queue--;
1098  GNUNET_assert(session->bytes_in_queue >= msgw->msgsize);
1099  session->bytes_in_queue -= msgw->msgsize;
1100  GNUNET_assert(plugin->bytes_in_queue >= msgw->msgsize);
1101  plugin->bytes_in_queue -= msgw->msgsize;
1102  GNUNET_STATISTICS_set(plugin->env->stats,
1103  "# bytes currently in UNIX buffers",
1104  plugin->bytes_in_queue,
1105  GNUNET_NO);
1106  GNUNET_STATISTICS_update(plugin->env->stats,
1107  "# UNIX bytes discarded",
1108  msgw->msgsize,
1109  GNUNET_NO);
1110  if (NULL != msgw->cont)
1111  msgw->cont(msgw->cont_cls,
1112  &msgw->session->target,
1113  GNUNET_SYSERR,
1114  msgw->payload,
1115  0);
1116  GNUNET_free(msgw->msg);
1117  GNUNET_free(msgw);
1118  }
1119  if (NULL == msgw)
1120  {
1121  if (GNUNET_YES == did_delete)
1123  return; /* Nothing to send at the moment */
1124  }
1125  session = msgw->session;
1126  sent = unix_real_send(plugin,
1127  plugin->unix_sock.desc,
1128  &session->target,
1129  (const char *)msgw->msg,
1130  msgw->msgsize,
1131  msgw->priority,
1132  msgw->timeout,
1133  msgw->session->address->address,
1134  msgw->session->address->address_length,
1135  msgw->payload,
1136  msgw->cont,
1137  msgw->cont_cls);
1138  if (RETRY == sent)
1139  {
1140  GNUNET_STATISTICS_update(plugin->env->stats,
1141  "# UNIX retry attempts",
1142  1,
1143  GNUNET_NO);
1145  return;
1146  }
1147  GNUNET_CONTAINER_DLL_remove(plugin->msg_head, plugin->msg_tail, msgw);
1148  session->msgs_in_queue--;
1149  GNUNET_assert(session->bytes_in_queue >= msgw->msgsize);
1150  session->bytes_in_queue -= msgw->msgsize;
1151  GNUNET_assert(plugin->bytes_in_queue >= msgw->msgsize);
1152  plugin->bytes_in_queue -= msgw->msgsize;
1153  GNUNET_STATISTICS_set(plugin->env->stats,
1154  "# bytes currently in UNIX buffers",
1155  plugin->bytes_in_queue,
1156  GNUNET_NO);
1158  if (GNUNET_SYSERR == sent)
1159  {
1160  /* failed and no retry */
1161  if (NULL != msgw->cont)
1162  msgw->cont(msgw->cont_cls,
1163  &msgw->session->target,
1164  GNUNET_SYSERR,
1165  msgw->payload,
1166  0);
1167  GNUNET_STATISTICS_update(plugin->env->stats,
1168  "# UNIX bytes discarded",
1169  msgw->msgsize,
1170  GNUNET_NO);
1171  GNUNET_free(msgw->msg);
1172  GNUNET_free(msgw);
1173  return;
1174  }
1175  /* successfully sent bytes */
1176  GNUNET_break(sent > 0);
1177  GNUNET_STATISTICS_update(plugin->env->stats,
1178  "# bytes transmitted via UNIX",
1179  msgw->msgsize,
1180  GNUNET_NO);
1181  if (NULL != msgw->cont)
1182  msgw->cont(msgw->cont_cls,
1183  &msgw->session->target,
1184  GNUNET_OK,
1185  msgw->payload,
1186  msgw->msgsize);
1187  GNUNET_free(msgw->msg);
1188  GNUNET_free(msgw);
1189 }
1190 
1191 
1198 static void
1200 {
1201  struct Plugin *plugin = cls;
1202  const struct GNUNET_SCHEDULER_TaskContext *tc;
1203 
1204  plugin->read_task = NULL;
1206  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY))
1207  unix_plugin_do_read(plugin);
1208  plugin->read_task =
1210  plugin->unix_sock.desc,
1212  plugin);
1213 }
1214 
1215 
1222 static void
1224 {
1225  struct Plugin *plugin = cls;
1226  const struct GNUNET_SCHEDULER_TaskContext *tc;
1227 
1228  plugin->write_task = NULL;
1231  unix_plugin_do_write(plugin);
1232  if (NULL == plugin->msg_head)
1233  return; /* write queue empty */
1234  plugin->write_task =
1236  plugin->unix_sock.desc,
1238  plugin);
1239 }
1240 
1241 
1269 static ssize_t
1271  struct GNUNET_ATS_Session *session,
1272  const char *msgbuf,
1273  size_t msgbuf_size,
1274  unsigned int priority,
1275  struct GNUNET_TIME_Relative to,
1277  void *cont_cls)
1278 {
1279  struct Plugin *plugin = cls;
1280  struct UNIXMessageWrapper *wrapper;
1281  struct UNIXMessage *message;
1282  int ssize;
1283 
1284  if (GNUNET_OK !=
1286  &session->target,
1287  session))
1288  {
1290  "Invalid session for peer `%s' `%s'\n",
1291  GNUNET_i2s(&session->target),
1293  session->address->address,
1294  session->address->address_length));
1295  GNUNET_break(0);
1296  return GNUNET_SYSERR;
1297  }
1299  "Sending %u bytes with session for peer `%s' `%s'\n",
1300  msgbuf_size,
1301  GNUNET_i2s(&session->target),
1303  session->address->address,
1304  session->address->address_length));
1305  ssize = sizeof(struct UNIXMessage) + msgbuf_size;
1306  message = GNUNET_malloc(sizeof(struct UNIXMessage) + msgbuf_size);
1307  message->header.size = htons(ssize);
1308  message->header.type = htons(0);
1309  GNUNET_memcpy(&message->sender,
1310  plugin->env->my_identity,
1311  sizeof(struct GNUNET_PeerIdentity));
1312  GNUNET_memcpy(&message[1], msgbuf, msgbuf_size);
1313  wrapper = GNUNET_new(struct UNIXMessageWrapper);
1314  wrapper->msg = message;
1315  wrapper->msgsize = ssize;
1316  wrapper->payload = msgbuf_size;
1317  wrapper->priority = priority;
1319  wrapper->cont = cont;
1320  wrapper->cont_cls = cont_cls;
1321  wrapper->session = session;
1323  plugin->msg_tail,
1324  wrapper);
1325  plugin->bytes_in_queue += ssize;
1326  session->bytes_in_queue += ssize;
1327  session->msgs_in_queue++;
1328  GNUNET_STATISTICS_set(plugin->env->stats,
1329  "# bytes currently in UNIX buffers",
1330  plugin->bytes_in_queue,
1331  GNUNET_NO);
1333  if (NULL == plugin->write_task)
1334  plugin->write_task =
1336  plugin->unix_sock.desc,
1338  plugin);
1339  return ssize;
1340 }
1341 
1342 
1349 static int
1351 {
1352  struct Plugin *plugin = cls;
1353  struct sockaddr_un *un;
1354  socklen_t un_len;
1355 
1356  un = unix_address_to_sockaddr(plugin->unix_socket_path, &un_len);
1357  if (GNUNET_YES == plugin->is_abstract)
1358  {
1359  plugin->unix_socket_path[0] = '@';
1360  un->sun_path[0] = '\0';
1361  }
1362  plugin->unix_sock.desc =
1363  GNUNET_NETWORK_socket_create(AF_UNIX, SOCK_DGRAM, 0);
1364  if (NULL == plugin->unix_sock.desc)
1365  {
1367  GNUNET_free(un);
1368  return GNUNET_SYSERR;
1369  }
1370  if ('\0' != un->sun_path[0])
1371  {
1372  if (GNUNET_OK != GNUNET_DISK_directory_create_for_file(un->sun_path))
1373  {
1375  _("Cannot create path to `%s'\n"),
1376  un->sun_path);
1378  plugin->unix_sock.desc = NULL;
1379  GNUNET_free(un);
1380  return GNUNET_SYSERR;
1381  }
1382  }
1384  (const struct sockaddr *)un,
1385  un_len))
1386  {
1388  LOG(GNUNET_ERROR_TYPE_ERROR, _("Cannot bind to `%s'\n"), un->sun_path);
1390  plugin->unix_sock.desc = NULL;
1391  GNUNET_free(un);
1392  return GNUNET_SYSERR;
1393  }
1394  LOG(GNUNET_ERROR_TYPE_DEBUG, "Bound to `%s'\n", plugin->unix_socket_path);
1395  plugin->read_task =
1397  plugin->unix_sock.desc,
1399  plugin);
1400  GNUNET_free(un);
1401  return 1;
1402 }
1403 
1404 
1421 static int
1422 unix_plugin_check_address(void *cls, const void *addr, size_t addrlen)
1423 {
1424  struct Plugin *plugin = cls;
1425  const struct UnixAddress *ua = addr;
1426  char *addrstr;
1427  size_t addr_str_len;
1428 
1429  if ((NULL == addr) || (0 == addrlen) ||
1430  (sizeof(struct UnixAddress) > addrlen))
1431  {
1432  GNUNET_break(0);
1433  return GNUNET_SYSERR;
1434  }
1435  addrstr = (char *)&ua[1];
1436  addr_str_len = ntohl(ua->addrlen);
1437  if ('\0' != addrstr[addr_str_len - 1])
1438  {
1439  GNUNET_break(0);
1440  return GNUNET_SYSERR;
1441  }
1442  if (strlen(addrstr) + 1 != addr_str_len)
1443  {
1444  GNUNET_break(0);
1445  return GNUNET_SYSERR;
1446  }
1447 
1448  if (0 == strcmp(plugin->unix_socket_path, addrstr))
1449  return GNUNET_OK;
1450  return GNUNET_SYSERR;
1451 }
1452 
1453 
1468 static void
1470  const char *type,
1471  const void *addr,
1472  size_t addrlen,
1473  int numeric,
1476  void *asc_cls)
1477 {
1478  const char *ret;
1479 
1480  if ((NULL != addr) && (addrlen > 0))
1481  ret = unix_plugin_address_to_string(NULL, addr, addrlen);
1482  else
1483  ret = NULL;
1484  asc(asc_cls, ret, (NULL == ret) ? GNUNET_SYSERR : GNUNET_OK);
1485  asc(asc_cls, NULL, GNUNET_OK);
1486 }
1487 
1488 
1501 static int
1503  const char *addr,
1504  uint16_t addrlen,
1505  void **buf,
1506  size_t *added)
1507 {
1508  struct UnixAddress *ua;
1509  char *address;
1510  char *plugin;
1511  char *optionstr;
1512  uint32_t options;
1513  size_t ua_size;
1514 
1515  /* Format unix.options.address */
1516  address = NULL;
1517  plugin = NULL;
1518  optionstr = NULL;
1519 
1520  if ((NULL == addr) || (addrlen == 0))
1521  {
1522  GNUNET_break(0);
1523  return GNUNET_SYSERR;
1524  }
1525  if ('\0' != addr[addrlen - 1])
1526  {
1527  GNUNET_break(0);
1528  return GNUNET_SYSERR;
1529  }
1530  if (strlen(addr) != addrlen - 1)
1531  {
1532  GNUNET_break(0);
1533  return GNUNET_SYSERR;
1534  }
1535  plugin = GNUNET_strdup(addr);
1536  optionstr = strchr(plugin, '.');
1537  if (NULL == optionstr)
1538  {
1539  GNUNET_break(0);
1540  GNUNET_free(plugin);
1541  return GNUNET_SYSERR;
1542  }
1543  optionstr[0] = '\0';
1544  optionstr++;
1545  options = atol(optionstr);
1546  address = strchr(optionstr, '.');
1547  if (NULL == address)
1548  {
1549  GNUNET_break(0);
1550  GNUNET_free(plugin);
1551  return GNUNET_SYSERR;
1552  }
1553  address[0] = '\0';
1554  address++;
1555  if (0 != strcmp(plugin, PLUGIN_NAME))
1556  {
1557  GNUNET_break(0);
1558  GNUNET_free(plugin);
1559  return GNUNET_SYSERR;
1560  }
1561 
1562  ua_size = sizeof(struct UnixAddress) + strlen(address) + 1;
1563  ua = GNUNET_malloc(ua_size);
1564  ua->options = htonl(options);
1565  ua->addrlen = htonl(strlen(address) + 1);
1566  GNUNET_memcpy(&ua[1], address, strlen(address) + 1);
1567  GNUNET_free(plugin);
1568 
1569  (*buf) = ua;
1570  (*added) = ua_size;
1571  return GNUNET_OK;
1572 }
1573 
1574 
1580 static void
1582 {
1583  struct Plugin *plugin = cls;
1584  struct GNUNET_HELLO_Address *address;
1585  size_t len;
1586  struct UnixAddress *ua;
1587  char *unix_path;
1588 
1589  len = sizeof(struct UnixAddress) + strlen(plugin->unix_socket_path) + 1;
1590  ua = GNUNET_malloc(len);
1591  ua->options = htonl(plugin->myoptions);
1592  ua->addrlen = htonl(strlen(plugin->unix_socket_path) + 1);
1593  unix_path = (char *)&ua[1];
1594  GNUNET_memcpy(unix_path,
1595  plugin->unix_socket_path,
1596  strlen(plugin->unix_socket_path) + 1);
1597 
1598  plugin->address_update_task = NULL;
1599  address = GNUNET_HELLO_address_allocate(plugin->env->my_identity,
1600  PLUGIN_NAME,
1601  ua,
1602  len,
1604  plugin->env->notify_address(plugin->env->cls, GNUNET_YES, address);
1605  GNUNET_free(ua);
1606  GNUNET_free(address);
1607 }
1608 
1609 
1618 static int
1620  const struct GNUNET_PeerIdentity *key,
1621  void *value)
1622 {
1623  struct Plugin *plugin = cls;
1624  struct GNUNET_ATS_Session *session = value;
1625 
1626  unix_plugin_session_disconnect(plugin, session);
1627  return GNUNET_YES;
1628 }
1629 
1630 
1638 static void
1640  const struct GNUNET_PeerIdentity *target)
1641 {
1642  struct Plugin *plugin = cls;
1643 
1645  target,
1647  plugin);
1648 }
1649 
1650 
1660 static int
1662  const struct GNUNET_PeerIdentity *peer,
1663  void *value)
1664 {
1665  struct Plugin *plugin = cls;
1666  struct GNUNET_ATS_Session *session = value;
1667 
1670  return GNUNET_OK;
1671 }
1672 
1673 
1686 static void
1689  void *sic_cls)
1690 {
1691  struct Plugin *plugin = cls;
1692 
1693  plugin->sic = sic;
1694  plugin->sic_cls = sic_cls;
1695  if (NULL != sic)
1696  {
1699  plugin);
1700  /* signal end of first iteration */
1701  sic(sic_cls, NULL, NULL);
1702  }
1703 }
1704 
1705 
1713 void *
1715 {
1718  struct Plugin *plugin;
1719  int sockets_created;
1720 
1721  if (NULL == env->receive)
1722  {
1723  /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
1724  initialze the plugin or the API */
1726  api->cls = NULL;
1730  return api;
1731  }
1732 
1733  plugin = GNUNET_new(struct Plugin);
1734  if (GNUNET_OK !=
1736  "transport-unix",
1737  "UNIXPATH",
1738  &plugin->unix_socket_path))
1739  {
1741  "transport-unix",
1742  "UNIXPATH");
1743  GNUNET_free(plugin);
1744  return NULL;
1745  }
1746 
1747  plugin->env = env;
1748 
1749  /* Initialize my flags */
1750 #ifdef LINUX
1751  plugin->is_abstract =
1753  "testing",
1754  "USE_ABSTRACT_SOCKETS");
1755 #endif
1756  plugin->myoptions = UNIX_OPTIONS_NONE;
1757  if (GNUNET_YES == plugin->is_abstract)
1759 
1761  api->cls = plugin;
1763  api->send = &unix_plugin_send;
1775  sockets_created = unix_transport_server_start(plugin);
1776  if ((0 == sockets_created) || (GNUNET_SYSERR == sockets_created))
1777  {
1778  LOG(GNUNET_ERROR_TYPE_WARNING, _("Failed to open UNIX listen socket\n"));
1779  GNUNET_free(api);
1780  GNUNET_free(plugin->unix_socket_path);
1781  GNUNET_free(plugin);
1782  return NULL;
1783  }
1785  plugin->address_update_task =
1787  return api;
1788 }
1789 
1790 
1797 void *
1799 {
1800  struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1801  struct Plugin *plugin = api->cls;
1802  struct GNUNET_HELLO_Address *address;
1803  struct UNIXMessageWrapper *msgw;
1804  struct UnixAddress *ua;
1805  size_t len;
1806  struct GNUNET_ATS_Session *session;
1807 
1808  if (NULL == plugin)
1809  {
1810  GNUNET_free(api);
1811  return NULL;
1812  }
1813  len = sizeof(struct UnixAddress) + strlen(plugin->unix_socket_path) + 1;
1814  ua = GNUNET_malloc(len);
1815  ua->options = htonl(plugin->myoptions);
1816  ua->addrlen = htonl(strlen(plugin->unix_socket_path) + 1);
1817  GNUNET_memcpy(&ua[1],
1818  plugin->unix_socket_path,
1819  strlen(plugin->unix_socket_path) + 1);
1820  address = GNUNET_HELLO_address_allocate(plugin->env->my_identity,
1821  PLUGIN_NAME,
1822  ua,
1823  len,
1825  plugin->env->notify_address(plugin->env->cls, GNUNET_NO, address);
1826 
1827  GNUNET_free(address);
1828  GNUNET_free(ua);
1829 
1830  while (NULL != (msgw = plugin->msg_head))
1831  {
1832  GNUNET_CONTAINER_DLL_remove(plugin->msg_head, plugin->msg_tail, msgw);
1833  session = msgw->session;
1834  session->msgs_in_queue--;
1835  GNUNET_assert(session->bytes_in_queue >= msgw->msgsize);
1836  session->bytes_in_queue -= msgw->msgsize;
1837  GNUNET_assert(plugin->bytes_in_queue >= msgw->msgsize);
1838  plugin->bytes_in_queue -= msgw->msgsize;
1839  if (NULL != msgw->cont)
1840  msgw->cont(msgw->cont_cls,
1841  &msgw->session->target,
1842  GNUNET_SYSERR,
1843  msgw->payload,
1844  0);
1845  GNUNET_free(msgw->msg);
1846  GNUNET_free(msgw);
1847  }
1848 
1849  if (NULL != plugin->read_task)
1850  {
1851  GNUNET_SCHEDULER_cancel(plugin->read_task);
1852  plugin->read_task = NULL;
1853  }
1854  if (NULL != plugin->write_task)
1855  {
1856  GNUNET_SCHEDULER_cancel(plugin->write_task);
1857  plugin->write_task = NULL;
1858  }
1859  if (NULL != plugin->address_update_task)
1860  {
1861  GNUNET_SCHEDULER_cancel(plugin->address_update_task);
1862  plugin->address_update_task = NULL;
1863  }
1864  if (NULL != plugin->unix_sock.desc)
1865  {
1867  GNUNET_NETWORK_socket_close(plugin->unix_sock.desc));
1868  plugin->unix_sock.desc = NULL;
1869  }
1870  GNUNET_CONTAINER_multipeermap_iterate(plugin->session_map,
1872  plugin);
1873  GNUNET_CONTAINER_multipeermap_destroy(plugin->session_map);
1874  GNUNET_break(0 == plugin->bytes_in_queue);
1875  GNUNET_free(plugin->unix_socket_path);
1876  GNUNET_free(plugin);
1877  GNUNET_free(api);
1878  return NULL;
1879 }
1880 
1881 /* 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:871
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:737
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:246
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.
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:410
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:671
int GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition: network.c:474
Closure to lookup_queue_it().
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1537
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
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:681
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
#define GNUNET_NO
Definition: gnunet_common.h:78
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:75
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:46
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:181
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:1237
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
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:1264
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:686
ssize_t GNUNET_NETWORK_socket_sendto(const struct GNUNET_NETWORK_Handle *desc, const void *message, size_t length, const struct sockaddr *dest_addr, socklen_t dest_len)
Send data to a particular destination (always non-blocking).
Definition: network.c:838
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:76
static unsigned int size
Size of the "table".
Definition: peer.c:66
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:44
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:131
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:77
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1467
struct GNUNET_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:742
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:548
#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:900
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956