2 This file is part of GNUnet
3 Copyright (C) 2010-2014, 2018 GNUnet e.V.
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file transport/gnunet-communicator-unix.c
23 * @brief Transport plugin using unix domain sockets (!)
24 * Clearly, can only be used locally on Unix/Linux hosts...
25 * ONLY INTENDED FOR TESTING!!!
26 * @author Christian Grothoff
27 * @author Nathan Evans
30 #include "gnunet_util_lib.h"
31 #include "gnunet_protocols.h"
32 #include "gnunet_constants.h"
33 #include "gnunet_nt_lib.h"
34 #include "gnunet_statistics_service.h"
35 #include "gnunet_transport_communication_service.h"
38 * How many messages do we keep at most in the queue to the
39 * transport service before we start to drop (default,
40 * can be changed via the configuration file).
41 * Should be _below_ the level of the communicator API, as
42 * otherwise we may read messages just to have them dropped
43 * by the communicator API.
45 #define DEFAULT_MAX_QUEUE_LENGTH 8000
48 * Address prefix used by the communicator.
50 #define COMMUNICATOR_ADDRESS_PREFIX "unix"
53 * Configuration section used by the communicator.
55 #define COMMUNICATOR_CONFIG_SECTION "communicator-unix"
60 #define UNIX_MTU UINT16_MAX
62 GNUNET_NETWORK_STRUCT_BEGIN
65 * UNIX Message-Packet header.
72 struct GNUNET_MessageHeader header;
75 * What is the identity of the sender (GNUNET_hash of public key)
77 struct GNUNET_PeerIdentity sender;
80 GNUNET_NETWORK_STRUCT_END
89 * Queues with pending messages (!) are kept in a DLL.
94 * Queues with pending messages (!) are kept in a DLL.
99 * To whom are we talking to.
101 struct GNUNET_PeerIdentity target;
104 * Address of the other peer.
106 struct sockaddr_un *address;
109 * Length of the address.
111 socklen_t address_len;
114 * Message currently scheduled for transmission, non-NULL if and only
115 * if this queue is in the #queue_head DLL.
117 struct UNIXMessage *msg;
120 * Message queue we are providing for the #ch.
122 struct GNUNET_MQ_Handle *mq;
125 * handle for this queue with the #ch.
127 struct GNUNET_TRANSPORT_QueueHandle *qh;
130 * Number of bytes we currently have in our write queue.
132 unsigned long long bytes_in_queue;
135 * Timeout for this queue.
137 struct GNUNET_TIME_Absolute timeout;
140 * Queue timeout task.
142 struct GNUNET_SCHEDULER_Task *timeout_task;
148 static struct GNUNET_PeerIdentity my_identity;
153 static struct GNUNET_SCHEDULER_Task *read_task;
158 static struct GNUNET_SCHEDULER_Task *write_task;
161 * Number of messages we currently have in our queues towards the transport service.
163 static unsigned long long delivering_messages;
166 * Maximum queue length before we stop reading towards the transport service.
168 static unsigned long long max_queue_length;
171 * For logging statistics.
173 static struct GNUNET_STATISTICS_Handle *stats;
178 static struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
181 * Queues (map from peer identity to `struct Queue`)
183 static struct GNUNET_CONTAINER_MultiPeerMap *queue_map;
186 * Head of queue of messages to transmit.
188 static struct Queue *queue_head;
191 * Tail of queue of messages to transmit.
193 static struct Queue *queue_tail;
196 * socket that we transmit all data with
198 static struct GNUNET_NETWORK_Handle *unix_sock;
201 * Handle to the operation that publishes our address.
203 static struct GNUNET_TRANSPORT_AddressIdentifier *ai;
207 * Functions with this signature are called whenever we need
208 * to close a queue due to a disconnect or failure to
209 * establish a connection.
211 * @param queue queue to close down
214 queue_destroy (struct Queue *queue)
216 struct GNUNET_MQ_Handle *mq;
218 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
219 "Disconnecting queue for peer `%s'\n",
220 GNUNET_i2s (&queue->target));
221 if (0 != queue->bytes_in_queue)
223 GNUNET_CONTAINER_DLL_remove (queue_head, queue_tail, queue);
224 queue->bytes_in_queue = 0;
226 if (NULL != (mq = queue->mq))
229 GNUNET_MQ_destroy (mq);
233 GNUNET_CONTAINER_multipeermap_remove (queue_map, &queue->target, queue));
234 GNUNET_STATISTICS_set (stats,
236 GNUNET_CONTAINER_multipeermap_size (queue_map),
238 if (NULL != queue->timeout_task)
240 GNUNET_SCHEDULER_cancel (queue->timeout_task);
241 queue->timeout_task = NULL;
243 GNUNET_free (queue->address);
249 * Queue was idle for too long, so disconnect it
251 * @param cls the `struct Queue *` to disconnect
254 queue_timeout (void *cls)
256 struct Queue *queue = cls;
257 struct GNUNET_TIME_Relative left;
259 queue->timeout_task = NULL;
260 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
261 if (0 != left.rel_value_us)
263 /* not actually our turn yet, but let's at least update
264 the monitor, it may think we're about to die ... */
265 queue->timeout_task =
266 GNUNET_SCHEDULER_add_delayed (left, &queue_timeout, queue);
269 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
270 "Queue %p was idle for %s, disconnecting\n",
272 GNUNET_STRINGS_relative_time_to_string (
273 GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
275 queue_destroy (queue);
280 * Increment queue timeout due to activity. We do not immediately
281 * notify the monitor here as that might generate excessive
284 * @param queue queue for which the timeout should be rescheduled
287 reschedule_queue_timeout (struct Queue *queue)
289 GNUNET_assert (NULL != queue->timeout_task);
291 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
296 * Convert unix path to a `struct sockaddr_un *`
298 * @param unixpath path to convert
299 * @param[out] sock_len set to the length of the address
300 * @param is_abstract is this an abstract @a unixpath
301 * @return converted unix path
303 static struct sockaddr_un *
304 unix_address_to_sockaddr (const char *unixpath, socklen_t *sock_len)
306 struct sockaddr_un *un;
309 GNUNET_assert (0 < strlen (unixpath)); /* sanity check */
310 un = GNUNET_new (struct sockaddr_un);
311 un->sun_family = AF_UNIX;
312 slen = strlen (unixpath);
313 if (slen >= sizeof(un->sun_path))
314 slen = sizeof(un->sun_path) - 1;
315 GNUNET_memcpy (un->sun_path, unixpath, slen);
316 un->sun_path[slen] = '\0';
317 slen = sizeof(struct sockaddr_un);
318 #if HAVE_SOCKADDR_UN_SUN_LEN
319 un->sun_len = (u_char) slen;
322 if ('@' == un->sun_path[0])
323 un->sun_path[0] = '\0';
329 * Closure to #lookup_queue_it().
334 * Location to store the queue, if found.
339 * Address we are looking for.
341 const struct sockaddr_un *un;
344 * Number of bytes in @a un
351 * Function called to find a queue by address.
353 * @param cls the `struct LookupCtx *`
354 * @param key peer we are looking for (unused)
355 * @param value a queue
356 * @return #GNUNET_YES if not found (continue looking), #GNUNET_NO on success
359 lookup_queue_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
361 struct LookupCtx *lctx = cls;
362 struct Queue *queue = value;
364 if ((queue->address_len == lctx->un_len) &&
365 (0 == memcmp (lctx->un, queue->address, queue->address_len)))
375 * Find an existing queue by address.
377 * @param plugin the plugin
378 * @param address the address to find
379 * @return NULL if queue was not found
381 static struct Queue *
382 lookup_queue (const struct GNUNET_PeerIdentity *peer,
383 const struct sockaddr_un *un,
386 struct LookupCtx lctx;
389 lctx.un_len = un_len;
391 GNUNET_CONTAINER_multipeermap_get_multiple (queue_map,
400 * We have been notified that our socket is ready to write.
401 * Then reschedule this function to be called again once more is available.
406 select_write_cb (void *cls)
408 struct Queue *queue = queue_tail;
409 const struct GNUNET_MessageHeader *msg = &queue->msg->header;
410 size_t msg_size = ntohs (msg->size);
413 /* take queue of the ready list */
417 sent = GNUNET_NETWORK_socket_sendto (unix_sock,
420 (const struct sockaddr *) queue->address,
422 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
423 "UNIX transmitted message to %s (%d/%u: %s)\n",
424 GNUNET_i2s (&queue->target),
426 (unsigned int) msg_size,
427 (sent < 0) ? strerror (errno) : "ok");
430 GNUNET_CONTAINER_DLL_remove (queue_head, queue_tail, queue);
431 if (NULL != queue_head)
432 write_task = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
438 GNUNET_free (queue->msg);
440 GNUNET_MQ_impl_send_continue (queue->mq);
441 GNUNET_STATISTICS_update (stats,
445 reschedule_queue_timeout (queue);
446 return; /* all good */
448 GNUNET_STATISTICS_update (stats,
449 "# network transmission failures",
452 write_task = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
460 /* We should retry later... */
461 GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "send");
466 socklen_t len = sizeof(size);
468 GNUNET_NETWORK_socket_getsockopt (unix_sock,
473 if (size > ntohs (msg->size))
475 /* Buffer is bigger than message: error, no retry
476 * This should never happen!*/
481 GNUNET_ERROR_TYPE_WARNING,
482 "Trying to increase socket buffer size from %u to %u for message size %u\n",
484 (unsigned int) ((msg_size / 1000) + 2) * 1000,
485 (unsigned int) msg_size);
486 size = ((msg_size / 1000) + 2) * 1000;
487 if (GNUNET_OK == GNUNET_NETWORK_socket_setsockopt (unix_sock,
492 goto resend; /* Increased buffer size, retry sending */
493 /* Ok, then just try very modest increase */
495 if (GNUNET_OK == GNUNET_NETWORK_socket_setsockopt (unix_sock,
500 goto resend; /* Increased buffer size, retry sending */
501 /* Could not increase buffer size: error, no retry */
502 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "setsockopt");
507 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "send");
514 * Signature of functions implementing the sending functionality of a
517 * @param mq the message queue
518 * @param msg the message to send
519 * @param impl_state our `struct Queue`
522 mq_send (struct GNUNET_MQ_Handle *mq,
523 const struct GNUNET_MessageHeader *msg,
526 struct Queue *queue = impl_state;
527 size_t msize = ntohs (msg->size);
529 GNUNET_assert (mq == queue->mq);
530 GNUNET_assert (NULL == queue->msg);
531 // Convert to UNIXMessage
532 queue->msg = GNUNET_malloc (msize + sizeof (struct UNIXMessage));
533 queue->msg->header.size = htons (msize + sizeof (struct UNIXMessage));
534 queue->msg->sender = my_identity;
535 memcpy (&queue->msg[1], msg, msize);
536 GNUNET_CONTAINER_DLL_insert (queue_head, queue_tail, queue);
537 GNUNET_assert (NULL != unix_sock);
538 if (NULL == write_task)
539 write_task = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
547 * Signature of functions implementing the destruction of a message
548 * queue. Implementations must not free @a mq, but should take care
551 * @param mq the message queue to destroy
552 * @param impl_state our `struct Queue`
555 mq_destroy (struct GNUNET_MQ_Handle *mq, void *impl_state)
557 struct Queue *queue = impl_state;
562 queue_destroy (queue);
568 * Implementation function that cancels the currently sent message.
570 * @param mq message queue
571 * @param impl_state our `struct Queue`
574 mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
576 struct Queue *queue = impl_state;
578 GNUNET_assert (NULL != queue->msg);
580 GNUNET_CONTAINER_DLL_remove (queue_head, queue_tail, queue);
581 GNUNET_assert (NULL != write_task);
582 if (NULL == queue_head)
584 GNUNET_SCHEDULER_cancel (write_task);
591 * Generic error handler, called with the appropriate
592 * error code and the same closure specified at the creation of
594 * Not every message queue implementation supports an error handler.
596 * @param cls our `struct Queue`
597 * @param error error code
600 mq_error (void *cls, enum GNUNET_MQ_Error error)
602 struct Queue *queue = cls;
604 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
605 "UNIX MQ error in queue to %s: %d\n",
606 GNUNET_i2s (&queue->target),
608 queue_destroy (queue);
613 * Creates a new outbound queue the transport service will use to send
614 * data to another peer.
616 * @param peer the target peer
617 * @param cs inbound or outbound queue
618 * @param un the address
619 * @param un_len number of bytes in @a un
620 * @return the queue or NULL of max connections exceeded
622 static struct Queue *
623 setup_queue (const struct GNUNET_PeerIdentity *target,
624 enum GNUNET_TRANSPORT_ConnectionStatus cs,
625 const struct sockaddr_un *un,
630 queue = GNUNET_new (struct Queue);
631 queue->target = *target;
632 queue->address = GNUNET_memdup (un, un_len);
633 queue->address_len = un_len;
634 (void) GNUNET_CONTAINER_multipeermap_put (
638 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
639 GNUNET_STATISTICS_set (stats,
641 GNUNET_CONTAINER_multipeermap_size (queue_map),
644 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
645 queue->timeout_task =
646 GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
649 queue->mq = GNUNET_MQ_queue_for_callbacks (&mq_send,
659 if ('\0' == un->sun_path[0])
660 GNUNET_asprintf (&foreign_addr,
662 COMMUNICATOR_ADDRESS_PREFIX,
665 GNUNET_asprintf (&foreign_addr,
667 COMMUNICATOR_ADDRESS_PREFIX,
669 queue->qh = GNUNET_TRANSPORT_communicator_mq_add (ch,
676 GNUNET_free (foreign_addr);
683 * We have been notified that our socket has something to read. Do the
684 * read and reschedule this function to be called again once more is
690 select_read_cb (void *cls);
694 * Function called when message was successfully passed to
695 * transport service. Continue read activity.
698 * @param success #GNUNET_OK on success
701 receive_complete_cb (void *cls, int success)
704 delivering_messages--;
705 if (GNUNET_OK != success)
706 GNUNET_STATISTICS_update (stats,
707 "# transport transmission failures",
710 if ((NULL == read_task) && (delivering_messages < max_queue_length) &&
712 read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
720 * We have been notified that our socket has something to read. Do the
721 * read and reschedule this function to be called again once more is
727 select_read_cb (void *cls)
729 char buf[65536] GNUNET_ALIGN;
731 const struct UNIXMessage *msg;
732 struct sockaddr_un un;
737 GNUNET_assert (NULL != unix_sock);
738 read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
742 addrlen = sizeof(un);
743 memset (&un, 0, sizeof(un));
744 ret = GNUNET_NETWORK_socket_recvfrom (unix_sock,
747 (struct sockaddr *) &un,
749 if ((-1 == ret) && ((EAGAIN == errno) || (ENOBUFS == errno)))
753 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "recvfrom");
756 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
757 "Read %d bytes from socket %s\n",
760 GNUNET_assert (AF_UNIX == (un.sun_family));
761 msg = (struct UNIXMessage *) buf;
762 msize = ntohs (msg->header.size);
763 if ((msize < sizeof(struct UNIXMessage)) || (msize > ret))
765 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
766 "Wrong message size: %d bytes\n",
771 queue = lookup_queue (&msg->sender, &un, addrlen);
774 setup_queue (&msg->sender, GNUNET_TRANSPORT_CS_INBOUND, &un, addrlen);
776 reschedule_queue_timeout (queue);
780 GNUNET_ERROR_TYPE_ERROR,
782 "Maximum number of UNIX connections exceeded, dropping incoming message\n"));
787 uint16_t tsize = msize - sizeof(struct UNIXMessage);
789 const struct GNUNET_MessageHeader *currhdr;
790 struct GNUNET_MessageHeader al_hdr;
792 currhdr = (const struct GNUNET_MessageHeader *) &msg[1];
793 /* ensure aligned access */
794 memcpy (&al_hdr, currhdr, sizeof(al_hdr));
795 if ((tsize < sizeof(struct GNUNET_MessageHeader)) ||
796 (tsize != ntohs(al_hdr.size)))
801 ret = GNUNET_TRANSPORT_communicator_receive (ch,
804 GNUNET_TIME_UNIT_FOREVER_REL,
805 &receive_complete_cb,
807 if (GNUNET_SYSERR == ret)
809 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
810 "Transport not up!\n");
811 return; /* transport not up */
813 if (GNUNET_NO == ret)
815 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
816 "Error sending message to transport\n");
819 delivering_messages++;
821 if (delivering_messages >= max_queue_length)
823 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
824 "Back pressure %llu\n", delivering_messages);
826 /* we should try to apply 'back pressure' */
827 GNUNET_SCHEDULER_cancel (read_task);
834 * Function called by the transport service to initialize a
835 * message queue given address information about another peer.
836 * If and when the communication channel is established, the
837 * communicator must call #GNUNET_TRANSPORT_communicator_mq_add()
838 * to notify the service that the channel is now up. It is
839 * the responsibility of the communicator to manage sane
840 * retries and timeouts for any @a peer/@a address combination
841 * provided by the transport service. Timeouts and retries
842 * do not need to be signalled to the transport service.
845 * @param peer identity of the other peer
846 * @param address where to send the message, human-readable
847 * communicator-specific format, 0-terminated, UTF-8
848 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the provided address is invalid
851 mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
855 struct sockaddr_un *un;
859 if (0 != strncmp (address,
860 COMMUNICATOR_ADDRESS_PREFIX "-",
861 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
864 return GNUNET_SYSERR;
866 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
867 un = unix_address_to_sockaddr (path, &un_len);
868 queue = lookup_queue (peer, un, un_len);
871 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
872 "Address `%s' for %s ignored, queue exists\n",
878 queue = setup_queue (peer, GNUNET_TRANSPORT_CS_OUTBOUND, un, un_len);
882 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
883 "Failed to setup queue to %s at `%s'\n",
893 * Iterator over all message queues to clean up.
896 * @param target unused
897 * @param value the queue to destroy
898 * @return #GNUNET_OK to continue to iterate
901 get_queue_delete_it (void *cls,
902 const struct GNUNET_PeerIdentity *target,
905 struct Queue *queue = value;
909 queue_destroy (queue);
915 * Shutdown the UNIX communicator.
917 * @param cls NULL (always)
920 do_shutdown (void *cls)
922 if (NULL != read_task)
924 GNUNET_SCHEDULER_cancel (read_task);
927 if (NULL != write_task)
929 GNUNET_SCHEDULER_cancel (write_task);
932 if (NULL != unix_sock)
934 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (unix_sock));
937 GNUNET_CONTAINER_multipeermap_iterate (queue_map, &get_queue_delete_it, NULL);
938 GNUNET_CONTAINER_multipeermap_destroy (queue_map);
941 GNUNET_TRANSPORT_communicator_address_remove (ai);
946 GNUNET_TRANSPORT_communicator_disconnect (ch);
951 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
958 * Function called when the transport service has received an
959 * acknowledgement for this communicator (!) via a different return
962 * Not applicable for UNIX.
965 * @param sender which peer sent the notification
969 enc_notify_cb (void *cls,
970 const struct GNUNET_PeerIdentity *sender,
971 const struct GNUNET_MessageHeader *msg)
981 * Setup communicator and launch network interactions.
983 * @param cls NULL (always)
984 * @param args remaining command-line arguments
985 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
986 * @param cfg configuration
992 const struct GNUNET_CONFIGURATION_Handle *cfg)
994 char *unix_socket_path;
995 struct sockaddr_un *un;
998 struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
1001 delivering_messages = 0;
1003 my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
1004 if (NULL == my_private_key)
1007 GNUNET_ERROR_TYPE_ERROR,
1009 "UNIX communicator is lacking key configuration settings. Exiting.\n"));
1010 GNUNET_SCHEDULER_shutdown ();
1013 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_identity.public_key);
1016 GNUNET_CONFIGURATION_get_value_filename (cfg,
1017 COMMUNICATOR_CONFIG_SECTION,
1021 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1022 COMMUNICATOR_CONFIG_SECTION,
1027 GNUNET_CONFIGURATION_get_value_number (cfg,
1028 COMMUNICATOR_CONFIG_SECTION,
1031 max_queue_length = DEFAULT_MAX_QUEUE_LENGTH;
1033 un = unix_address_to_sockaddr (unix_socket_path, &un_len);
1036 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1037 "Failed to setup UNIX domain socket address with path `%s'\n",
1039 GNUNET_free (unix_socket_path);
1042 unix_sock = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_DGRAM, 0);
1043 if (NULL == unix_sock)
1045 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
1047 GNUNET_free (unix_socket_path);
1050 if (('\0' != un->sun_path[0]) &&
1051 (GNUNET_OK != GNUNET_DISK_directory_create_for_file (un->sun_path)))
1053 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1054 _ ("Cannot create path to `%s'\n"),
1056 GNUNET_NETWORK_socket_close (unix_sock);
1059 GNUNET_free (unix_socket_path);
1062 if (GNUNET_OK != GNUNET_NETWORK_socket_bind (unix_sock,
1063 (const struct sockaddr *) un,
1066 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "bind", un->sun_path);
1067 GNUNET_NETWORK_socket_close (unix_sock);
1070 GNUNET_free (unix_socket_path);
1074 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Bound to `%s'\n", unix_socket_path);
1075 stats = GNUNET_STATISTICS_create ("C-UNIX", cfg);
1076 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1077 read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1081 queue_map = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
1082 ch = GNUNET_TRANSPORT_communicator_connect (cfg,
1083 COMMUNICATOR_CONFIG_SECTION,
1084 COMMUNICATOR_ADDRESS_PREFIX,
1085 GNUNET_TRANSPORT_CC_RELIABLE,
1093 GNUNET_SCHEDULER_shutdown ();
1094 GNUNET_free (unix_socket_path);
1097 GNUNET_asprintf (&my_addr,
1099 COMMUNICATOR_ADDRESS_PREFIX,
1101 GNUNET_free (unix_socket_path);
1102 ai = GNUNET_TRANSPORT_communicator_address_add (ch,
1105 GNUNET_TIME_UNIT_FOREVER_REL);
1106 GNUNET_free (my_addr);
1111 * The main function for the UNIX communicator.
1113 * @param argc number of arguments from the command line
1114 * @param argv command line arguments
1115 * @return 0 ok, 1 on error
1118 main (int argc, char *const *argv)
1120 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1121 GNUNET_GETOPT_OPTION_END
1125 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1129 GNUNET_PROGRAM_run (argc,
1131 "gnunet-communicator-unix",
1132 _ ("GNUnet UNIX domain socket communicator"),
1138 GNUNET_free ((void *) argv);
1143 #if defined(__linux__) && defined(__GLIBC__)
1147 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
1149 void __attribute__ ((constructor))
1150 GNUNET_ARM_memory_init ()
1152 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
1153 mallopt (M_TOP_PAD, 1 * 1024);
1160 /* end of gnunet-communicator-unix.c */