コード例 #1
0
ファイル: nat_test.c プロジェクト: tg-x/gnunet
/**
 * Activity on our listen socket. Accept the
 * incoming connection.
 *
 * @param cls the `struct GNUNET_NAT_Test`
 * @param tc scheduler context
 */
static void
do_accept (void *cls,
           const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct GNUNET_NAT_Test *tst = cls;
  struct GNUNET_NETWORK_Handle *s;
  struct NatActivity *wl;

  tst->ltask = NULL;
  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
    return;
  tst->ltask =
      GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, tst->lsock,
                                     &do_accept, tst);
  s = GNUNET_NETWORK_socket_accept (tst->lsock, NULL, NULL);
  if (NULL == s)
  {
    GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, "accept");
    return;                     /* odd error */
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Got an inbound connection, waiting for data\n");
  wl = GNUNET_new (struct NatActivity);
  wl->sock = s;
  wl->h = tst;
  wl->rtask =
    GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
                                   wl->sock,
                                   &do_read, wl);
  GNUNET_CONTAINER_DLL_insert (tst->na_head, tst->na_tail, wl);
}
コード例 #2
0
ファイル: test_stun.c プロジェクト: GNUnet/gnunet
/**
 * Function called with the result of the STUN request transmission attempt.
 *
 * @param cls unused
 * @param error status code from STUN
 */
static void
request_callback (void *cls,
                  enum GNUNET_NAT_StatusCode error)
{
  rh = NULL;
  if (GNUNET_NAT_ERROR_SUCCESS == error)
  {
    /* all good, start to receive */
    ltask4 = GNUNET_SCHEDULER_add_read_net (TIMEOUT,
                                            lsock4,
                                            &do_udp_read,
                                            NULL);
    return;
  }
  if (error == GNUNET_NAT_ERROR_NOT_ONLINE)
  {
    ret = 77; /* report 'skip' */
    fprintf (stderr,
             "System is offline, cannot test STUN request.\n");
  }
  else
  {
    ret = error;
  }
  stop();
}
コード例 #3
0
ファイル: connection.c プロジェクト: h4ck3rm1k3/gnunet-debian
/**
 * We've succeeded in establishing a connection.
 *
 * @param connection the connection we tried to establish
 */
static void
connect_success_continuation (struct GNUNET_CONNECTION_Handle *connection)
{
  LOG (GNUNET_ERROR_TYPE_DEBUG, 
       "Connection to `%s' succeeded! (%p)\n",
       GNUNET_a2s (connection->addr, connection->addrlen), connection);
  /* trigger jobs that waited for the connection */
  if (NULL != connection->receiver)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Connection succeeded, starting with receiving data (%p)\n", 
	 connection);
    GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->read_task);
    connection->read_task =
      GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining
                                     (connection->receive_timeout), connection->sock,
                                     &receive_ready, connection);
  }
  if (NULL != connection->nth.notify_ready)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Connection succeeded, starting with sending data (%p)\n",
         connection);
    GNUNET_assert (connection->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK);
    GNUNET_SCHEDULER_cancel (connection->nth.timeout_task);
    connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK;
    GNUNET_assert (connection->write_task == GNUNET_SCHEDULER_NO_TASK);
    connection->write_task =
        GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining
                                        (connection->nth.transmit_timeout), connection->sock,
                                        &transmit_ready, connection);
  }
}
コード例 #4
0
ファイル: nat_test.c プロジェクト: tg-x/gnunet
/**
 * Activity on our incoming socket.  Read data from the
 * incoming connection.
 *
 * @param cls the `struct GNUNET_NAT_Test`
 * @param tc scheduler context
 */
static void
do_udp_read (void *cls,
             const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct GNUNET_NAT_Test *tst = cls;
  uint16_t data;

  tst->ltask =
      GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
                                     tst->lsock,
                                     &do_udp_read, tst);
  if ((NULL != tc->write_ready) &&
      (GNUNET_NETWORK_fdset_isset (tc->read_ready, tst->lsock)) &&
      (sizeof (data) ==
       GNUNET_NETWORK_socket_recv (tst->lsock, &data, sizeof (data))))
  {
    if (data == tst->data)
      tst->report (tst->report_cls, GNUNET_NAT_ERROR_SUCCESS);
    else
      LOG (GNUNET_ERROR_TYPE_DEBUG,
           "Received data mismatches expected value\n");
  }
  else
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Failed to receive data from inbound connection\n");
}
コード例 #5
0
static void
task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct sockaddr_in v4;

  ls = open_listen_socket ();
  lsock = GNUNET_CONNECTION_create_from_existing (ls);
  GNUNET_assert (lsock != NULL);

#if HAVE_SOCKADDR_IN_SIN_LEN
  v4.sin_len = sizeof (v4);
#endif
  v4.sin_family = AF_INET;
  v4.sin_port = htons (PORT);
  v4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
  csock =
      GNUNET_CONNECTION_create_from_sockaddr (AF_INET,
                                              (const struct sockaddr *) &v4,
                                              sizeof (v4));
  GNUNET_assert (csock != NULL);
  GNUNET_assert (NULL !=
                 GNUNET_CONNECTION_notify_transmit_ready (csock, 12,
                                                          GNUNET_TIME_UNIT_SECONDS,
                                                          &make_hello, NULL));
  GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, ls, &run_accept,
                                 cls);
}
コード例 #6
0
ファイル: connection.c プロジェクト: h4ck3rm1k3/gnunet-debian
/**
 * Receive data from the given connection.  Note that this function will
 * call "receiver" asynchronously using the scheduler.  It will
 * "immediately" return.  Note that there MUST only be one active
 * receive call per connection at any given point in time (so do not
 * call receive again until the receiver callback has been invoked).
 *
 * @param connection connection handle
 * @param max maximum number of bytes to read
 * @param timeout maximum amount of time to wait
 * @param receiver function to call with received data
 * @param receiver_cls closure for receiver
 */
void
GNUNET_CONNECTION_receive (struct GNUNET_CONNECTION_Handle *connection, size_t max,
                           struct GNUNET_TIME_Relative timeout,
                           GNUNET_CONNECTION_Receiver receiver,
                           void *receiver_cls)
{
  GNUNET_assert ((GNUNET_SCHEDULER_NO_TASK == connection->read_task) &&
                 (NULL == connection->receiver));
  GNUNET_assert (NULL != receiver);
  connection->receiver = receiver;
  connection->receiver_cls = receiver_cls;
  connection->receive_timeout = GNUNET_TIME_relative_to_absolute (timeout);
  connection->max = max;
  if (NULL != connection->sock)
  {
    connection->read_task =
      GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining
                                     (connection->receive_timeout), connection->sock,
                                     &receive_ready, connection);
    return;
  }
  if ((NULL == connection->dns_active) && (NULL == connection->ap_head))
  {
    connection->receiver = NULL;
    receiver (receiver_cls, NULL, 0, NULL, 0, ETIMEDOUT);
    return;
  }
}
コード例 #7
0
ファイル: nat_auto.c プロジェクト: muggenhor/GNUnet
/**
 * Test if NAT has been punched
 *
 * @param ah auto setup context
 */
static void
test_nat_punched (struct GNUNET_NAT_AutoHandle *ah)
{

  struct GNUNET_CLIENT_Connection *client;
  struct GNUNET_NAT_TestMessage msg;


  if (ah->stun_ip)
  {
    LOG (GNUNET_ERROR_TYPE_INFO,
         "Asking gnunet-nat-server to connect to `%s'\n",
         ah->stun_ip);


    msg.header.size = htons (sizeof (struct GNUNET_NAT_TestMessage));
    msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAT_TEST);
    msg.dst_ipv4 = inet_addr(ah->stun_ip);
    msg.dport = htons(ah->stun_port);
    msg.data = port;
    msg.is_tcp = htonl ((uint32_t) GNUNET_NO);

    client = GNUNET_CLIENT_connect ("gnunet-nat-server", ah->cfg);
    if (NULL == client)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                  _("Failed to connect to `gnunet-nat-server'\n"));
      return;
    }

    GNUNET_break (GNUNET_OK ==
                  GNUNET_CLIENT_transmit_and_get_response (client, &msg.header,
                                                           NAT_SERVER_TIMEOUT,
                                                           GNUNET_YES, NULL,
                                                           NULL));
    if (NULL != ltask4)
    {
      GNUNET_SCHEDULER_cancel (ltask4);
      ltask4 = GNUNET_SCHEDULER_add_read_net (NAT_SERVER_TIMEOUT,
                                              lsock4, &do_udp_read, ah);
    }

  }
  else
  {
    LOG (GNUNET_ERROR_TYPE_INFO,
         "We don't have a STUN IP");
    next_phase(ah);
  }


}
コード例 #8
0
ファイル: connection.c プロジェクト: h4ck3rm1k3/gnunet-debian
/**
 * This function is called once we either timeout
 * or have data ready to read.
 *
 * @param cls connection to read from
 * @param tc scheduler context
 */
static void
receive_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct GNUNET_CONNECTION_Handle *connection = cls;
  char buffer[connection->max];
  ssize_t ret;
  GNUNET_CONNECTION_Receiver receiver;

  connection->read_task = GNUNET_SCHEDULER_NO_TASK;
  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
  {
    /* ignore shutdown request, go again immediately */
    connection->read_task =
        GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining
                                       (connection->receive_timeout), connection->sock,
                                       &receive_ready, connection);
    return;
  }
  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT))
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
	 "Receive from `%s' encounters error: timeout (%p)\n",
	 GNUNET_a2s (connection->addr, connection->addrlen),
	 GNUNET_TIME_absolute_get_duration (connection->receive_timeout).rel_value,
	 connection);
    signal_receive_timeout (connection);
    return;
  }
  if (NULL == connection->sock)
  {
    /* connect failed for good */
    signal_receive_error (connection, ECONNREFUSED);
    return;
  }
  GNUNET_assert (GNUNET_NETWORK_fdset_isset (tc->read_ready, connection->sock));
RETRY:
  ret = GNUNET_NETWORK_socket_recv (connection->sock, buffer, connection->max);
  if (-1 == ret)
  {
    if (EINTR == errno)
      goto RETRY;
    signal_receive_error (connection, errno);
    return;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "receive_ready read %u/%u bytes from `%s' (%p)!\n", (unsigned int) ret,
       connection->max, GNUNET_a2s (connection->addr, connection->addrlen), connection);
  GNUNET_assert (NULL != (receiver = connection->receiver));
  connection->receiver = NULL;
  receiver (connection->receiver_cls, buffer, ret, connection->addr, connection->addrlen, 0);
}
コード例 #9
0
ファイル: test_connection.c プロジェクト: GNUnet/gnunet
static void
task (void *cls)
{
  ls = open_listen_socket ();
  lsock = GNUNET_CONNECTION_create_from_existing (ls);
  GNUNET_assert (lsock != NULL);
  csock = GNUNET_CONNECTION_create_from_connect (cfg, "localhost", PORT);
  GNUNET_assert (csock != NULL);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test asks for write notification\n");
  GNUNET_assert (NULL !=
                 GNUNET_CONNECTION_notify_transmit_ready (csock, 12,
                                                          GNUNET_TIME_UNIT_SECONDS,
                                                          &make_hello, NULL));
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test prepares to accept\n");
  GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, ls, &run_accept,
                                 cls);
}
コード例 #10
0
ファイル: nat_auto.c プロジェクト: muggenhor/GNUnet
/**
 * Determine our external IPv4 address and port using an external STUN server
 *
 * @param ah auto setup context
 */
static void
test_stun (struct GNUNET_NAT_AutoHandle *ah)
{

  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running STUN test\n");

  /* Get port from the configuration */
  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_number (ah->cfg,
                                             "transport-udp",
                                             "PORT",
                                             &port))
  {
    port = 2086;
  }

  //Lets create the socket
  lsock4 = bind_v4 ();
  if (NULL == lsock4)
  {
    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
    next_phase(ah);
    return;
  }
  else
  {
    //Lets call our function now when it accepts
    ltask4 = GNUNET_SCHEDULER_add_read_net (NAT_SERVER_TIMEOUT,
                                            lsock4, &do_udp_read, ah);

  }


  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "STUN service listens on port %u\n",
              port);
  if (GNUNET_NO == GNUNET_NAT_stun_make_request (stun_server, stun_port,
                                                 lsock4, &request_callback,
                                                 NULL))
  {
    /*An error happened*/
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "STUN error, stopping\n");
    stop_stun ();
    next_phase (ah);
  }
}
コード例 #11
0
ファイル: gnunet-nat.c プロジェクト: GNUnet/gnunet
/**
 * Task to receive incoming packets for STUN processing.
 */
static void
stun_read_task (void *cls)
{
  ssize_t size;
  
  rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
					 ls,
					 &stun_read_task,
					 NULL);
  size = GNUNET_NETWORK_socket_recvfrom_amount (ls);
  if (size > 0)
  {
    GNUNET_break (0);
    GNUNET_SCHEDULER_shutdown ();
    global_ret = 1;
    return;
  }
  {
    char buf[size + 1];
    struct sockaddr_storage sa;
    socklen_t salen = sizeof (sa);
    ssize_t ret;
    
    ret = GNUNET_NETWORK_socket_recvfrom (ls,
					  buf,
					  size + 1,
					  (struct sockaddr *) &sa,
					  &salen);
    if (ret != size)
    {
      GNUNET_break (0);
      GNUNET_SCHEDULER_shutdown ();
      global_ret = 1;
      return;
    }
    (void) GNUNET_NAT_stun_handle_packet (nh,
					  (const struct sockaddr *) &sa,
					  salen,
					  buf,
					  ret);
  }
}
コード例 #12
0
ファイル: test_stun.c プロジェクト: GNUnet/gnunet
/**
 * Activity on our incoming socket.  Read data from the
 * incoming connection.
 *
 * @param cls
 */
static void
do_udp_read (void *cls)
{
  //struct GNUNET_NAT_Test *tst = cls;
  unsigned char reply_buf[1024];
  ssize_t rlen;
  struct sockaddr_in answer;
  const struct GNUNET_SCHEDULER_TaskContext *tc;

  ltask4 = NULL;
  tc = GNUNET_SCHEDULER_get_task_context ();
  if ( (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) ||
       (! GNUNET_NETWORK_fdset_isset (tc->read_ready,
                                      lsock4)) )
  {
    fprintf (stderr,
             "Timeout waiting for STUN response\n");
    stop();
  }
  rlen = GNUNET_NETWORK_socket_recv (lsock4,
                                     reply_buf,
                                     sizeof (reply_buf));
  memset (&answer,
          0,
          sizeof(struct sockaddr_in));
  if (GNUNET_OK !=
      GNUNET_NAT_stun_handle_packet (reply_buf,
                                     rlen,
                                     &answer))
  {
    fprintf (stderr,
             "Unexpected UDP packet, trying to read more\n");
    ltask4 = GNUNET_SCHEDULER_add_read_net (TIMEOUT,
                                            lsock4,
                                            &do_udp_read, NULL);
    return;
  }
  ret = 0;
  print_answer (&answer);
  stop ();
}
コード例 #13
0
/**
 * Task triggered whenever we receive a SIGCHLD (child
 * process died).
 *
 * @param cls closure, NULL if we need to self-restart
 * @param tc context
 */
static void
maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct ServiceList *pos;
  struct ServiceList *next;
  struct ServiceListeningInfo *sli;
  const char *statstr;
  int statcode;
  int ret;
  char c[16];
  enum GNUNET_OS_ProcessStatusType statusType;
  unsigned long statusCode;
  const struct GNUNET_DISK_FileHandle *pr;

  pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ);
  child_death_task = GNUNET_SCHEDULER_NO_TASK;
  if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY))
    {
      /* shutdown scheduled us, ignore! */
      child_death_task =
	GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
					pr, &maint_child_death, NULL);
      return;
    }
  /* consume the signal */
  GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c)));

  /* check for services that died (WAITPID) */
  next = running_head;
  while (NULL != (pos = next))
    {
      next = pos->next;

      if (pos->proc == NULL)
      {
	if (GNUNET_YES == in_shutdown)
	  free_service (pos);
	continue;
      }
      if ((GNUNET_SYSERR ==
	   (ret =
	    GNUNET_OS_process_status (pos->proc, &statusType, &statusCode)))
	  || ((ret == GNUNET_NO) || (statusType == GNUNET_OS_PROCESS_STOPPED)
	      || (statusType == GNUNET_OS_PROCESS_RUNNING)))
	continue;
      if (statusType == GNUNET_OS_PROCESS_EXITED)
      {
	statstr = _( /* process termination method */ "exit");
	statcode = statusCode;
      }
      else if (statusType == GNUNET_OS_PROCESS_SIGNALED)
      {
	statstr = _( /* process termination method */ "signal");
	statcode = statusCode;
      }
      else
      {
	statstr = _( /* process termination method */ "unknown");
	statcode = 0;
      }
      if (0 != pos->killed_at.abs_value)
      {
	GNUNET_log (GNUNET_ERROR_TYPE_INFO,
		    _("Service `%s' took %llu ms to terminate\n"),
		    pos->name,
		    GNUNET_TIME_absolute_get_duration (pos->killed_at).rel_value);
      }
      GNUNET_OS_process_destroy (pos->proc);
      pos->proc = NULL;
      if (NULL != pos->killing_client)
	{
	  signal_result (pos->killing_client, pos->name,
			 GNUNET_ARM_PROCESS_DOWN);
	  GNUNET_SERVER_client_drop (pos->killing_client);
	  pos->killing_client = NULL;
	  /* process can still be re-started on-demand, ensure it is re-started if there is demand */
	  for (sli = pos->listen_head; NULL != sli; sli = sli->next)
	    {
	      GNUNET_break (GNUNET_SCHEDULER_NO_TASK == sli->accept_task);
	      sli->accept_task =
		GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
					       sli->listen_socket,
					       &accept_connection, sli);
	    }
	  continue;
	}
      if (GNUNET_YES != in_shutdown)
	{
	  if ((statusType == GNUNET_OS_PROCESS_EXITED) && (statcode == 0))
	    {
	      /* process terminated normally, allow restart at any time */
	      pos->restart_at.abs_value = 0;
	    }
          else
            {
	      if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
	        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
			    _
			    ("Service `%s' terminated with status %s/%d, will restart in %llu ms\n"),
			    pos->name, statstr, statcode, pos->backoff.rel_value);
	      /* schedule restart */
	      pos->restart_at = GNUNET_TIME_relative_to_absolute (pos->backoff);
	      pos->backoff =
	        GNUNET_TIME_relative_min (EXPONENTIAL_BACKOFF_THRESHOLD,
				          GNUNET_TIME_relative_multiply
				          (pos->backoff, 2));
            }
	  if (GNUNET_SCHEDULER_NO_TASK != child_restart_task)
	    GNUNET_SCHEDULER_cancel (child_restart_task);
	  child_restart_task =
	    GNUNET_SCHEDULER_add_with_priority
	    (GNUNET_SCHEDULER_PRIORITY_IDLE, 
	     &delayed_restart_task, NULL);
	}
      else
	{
	  free_service (pos);
	}
    }
  child_death_task =
    GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
				    pr, &maint_child_death, NULL);
  if ((NULL == running_head) && (GNUNET_YES == in_shutdown))
    do_shutdown ();
}
コード例 #14
0
/**
 * Task run whenever it is time to restart a child that died.
 *
 * @param cls closure, always NULL
 * @param tc context
 */
static void
delayed_restart_task (void *cls,
		      const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct ServiceList *sl;
  struct GNUNET_TIME_Relative lowestRestartDelay;
  struct ServiceListeningInfo *sli;

  child_restart_task = GNUNET_SCHEDULER_NO_TASK;
  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
    return;
  GNUNET_assert (GNUNET_NO == in_shutdown);
  lowestRestartDelay = GNUNET_TIME_UNIT_FOREVER_REL;

  /* check for services that need to be restarted due to
   * configuration changes or because the last restart failed */
  for (sl = running_head; NULL != sl; sl = sl->next)
  {
    if (NULL != sl->proc)
      continue;
    /* service is currently not running */
    if (GNUNET_TIME_absolute_get_remaining (sl->restart_at).rel_value ==
	0)
    {
      /* restart is now allowed */
      if (sl->is_default)
      {
	/* process should run by default, start immediately */
	GNUNET_log (GNUNET_ERROR_TYPE_INFO,
		    _("Restarting service `%s'.\n"), sl->name);
	start_process (sl);
      }
      else
      {
	/* process is run on-demand, ensure it is re-started if there is demand */
	for (sli = sl->listen_head; NULL != sli; sli = sli->next)
	  if (GNUNET_SCHEDULER_NO_TASK == sli->accept_task)
	  {
	    /* accept was actually paused, so start it again */
	    sli->accept_task =
	      GNUNET_SCHEDULER_add_read_net
	      (GNUNET_TIME_UNIT_FOREVER_REL, sli->listen_socket,
	       &accept_connection, sli);
	  }
      }
    }
    else
    {
      /* update calculation for earliest time to reactivate a service */
      lowestRestartDelay =
	GNUNET_TIME_relative_min (lowestRestartDelay,
				  GNUNET_TIME_absolute_get_remaining
				  (sl->restart_at));
    }
  }
  if (lowestRestartDelay.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Will restart process in %llums\n",
		(unsigned long long) lowestRestartDelay.rel_value);
    child_restart_task =
      GNUNET_SCHEDULER_add_delayed_with_priority (lowestRestartDelay,
						  GNUNET_SCHEDULER_PRIORITY_IDLE, 
						  &delayed_restart_task, NULL);
  }
}
コード例 #15
0
/**
 * Creating a listening socket for each of the service's addresses and
 * wait for the first incoming connection to it
 *
 * @param sa address associated with the service
 * @param addr_len length of sa
 * @param sl service entry for the service in question
 */
static void
create_listen_socket (struct sockaddr *sa, socklen_t addr_len,
		      struct ServiceList *sl)
{
  static int on = 1;
  struct GNUNET_NETWORK_Handle *sock;
  struct ServiceListeningInfo *sli;

  switch (sa->sa_family)
    {
    case AF_INET:
      sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0);
      break;
    case AF_INET6:
      sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
      break;
    case AF_UNIX:
      if (strcmp (GNUNET_a2s (sa, addr_len), "@") == 0)	/* Do not bind to blank UNIX path! */
	return;
      sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
      break;
    default:
      GNUNET_break (0);
      sock = NULL;
      errno = EAFNOSUPPORT;
      break;
    }
  if (NULL == sock)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
		  _("Unable to create socket for service `%s': %s\n"),
		  sl->name, STRERROR (errno));
      GNUNET_free (sa);
      return;
    }
  if (GNUNET_NETWORK_socket_setsockopt
      (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK)
    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
			 "setsockopt");
#ifdef IPV6_V6ONLY
  if ((sa->sa_family == AF_INET6) &&
      (GNUNET_NETWORK_socket_setsockopt
       (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)) != GNUNET_OK))
    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
			 "setsockopt");
#endif

  if (GNUNET_NETWORK_socket_bind
      (sock, (const struct sockaddr *) sa, addr_len) != GNUNET_OK)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
		  _
		  ("Unable to bind listening socket for service `%s' to address `%s': %s\n"),
		  sl->name, GNUNET_a2s (sa, addr_len), STRERROR (errno));
      GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
      GNUNET_free (sa);
      return;
    }
  if (GNUNET_NETWORK_socket_listen (sock, 5) != GNUNET_OK)
    {
      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen");
      GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
      GNUNET_free (sa);
      return;
    }
  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
	      _("ARM now monitors connections to service `%s' at `%s'\n"),
	      sl->name, GNUNET_a2s (sa, addr_len));
  sli = GNUNET_malloc (sizeof (struct ServiceListeningInfo));
  sli->service_addr = sa;
  sli->service_addr_len = addr_len;
  sli->listen_socket = sock;
  sli->sl = sl;
  sli->accept_task =
    GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, sock,
				   &accept_connection, sli);
  GNUNET_CONTAINER_DLL_insert (sl->listen_head, sl->listen_tail, sli);
}
コード例 #16
0
ファイル: nat_test.c プロジェクト: tg-x/gnunet
/**
 * Start testing if NAT traversal works using the
 * given configuration (IPv4-only).
 *
 * ALL failures are reported directly to the report callback
 *
 * @param cfg configuration for the NAT traversal
 * @param is_tcp #GNUNET_YES to test TCP, #GNUNET_NO to test UDP
 * @param bnd_port port to bind to, 0 for connection reversal
 * @param adv_port externally advertised port to use
 * @param timeout delay after which the test should be aborted
 * @param report function to call with the result of the test
 * @param report_cls closure for @a report
 * @return handle to cancel NAT test or NULL. The error is always indicated via the report callback
 */
struct GNUNET_NAT_Test *
GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
                       int is_tcp,
                       uint16_t bnd_port,
                       uint16_t adv_port,
                       struct GNUNET_TIME_Relative timeout,
                       GNUNET_NAT_TestCallback report,
                       void *report_cls)
{
  struct GNUNET_NAT_Test *nh;
  struct sockaddr_in sa;
  const struct sockaddr *addrs[] = { (const struct sockaddr *) &sa };
  const socklen_t addrlens[] = { sizeof (sa) };

  memset (&sa, 0, sizeof (sa));
  sa.sin_family = AF_INET;
  sa.sin_port = htons (bnd_port);
#if HAVE_SOCKADDR_IN_SIN_LEN
  sa.sin_len = sizeof (sa);
#endif

  nh = GNUNET_new (struct GNUNET_NAT_Test);
  nh->cfg = cfg;
  nh->is_tcp = is_tcp;
  nh->data = bnd_port;
  nh->adv_port = adv_port;
  nh->report = report;
  nh->report_cls = report_cls;
  nh->status = GNUNET_NAT_ERROR_SUCCESS;
  if (0 == bnd_port)
  {
    nh->nat 
      = GNUNET_NAT_register (cfg, is_tcp, 0, 0, 
			     NULL, NULL,
			     &addr_cb,
                             &reversal_cb, nh, NULL);
  }
  else
  {
    nh->lsock =
        GNUNET_NETWORK_socket_create (AF_INET,
                                      (is_tcp ==
                                       GNUNET_YES) ? SOCK_STREAM : SOCK_DGRAM,
                                      0);
    if ((nh->lsock == NULL) ||
        (GNUNET_OK !=
         GNUNET_NETWORK_socket_bind (nh->lsock, (const struct sockaddr *) &sa,
                                     sizeof (sa))))
    {
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                  _("Failed to create listen socket bound to `%s' for NAT test: %s\n"),
                  GNUNET_a2s ((const struct sockaddr *) &sa, sizeof (sa)),
                  STRERROR (errno));
      if (NULL != nh->lsock)
      {
        GNUNET_NETWORK_socket_close (nh->lsock);
        nh->lsock = NULL;
      }
      nh->status = GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR;
      nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout, nh);
      return nh;
    }
    if (GNUNET_YES == is_tcp)
    {
      GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_listen (nh->lsock, 5));
      nh->ltask =
          GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
                                         nh->lsock, &do_accept, nh);
    }
    else
    {
      nh->ltask =
          GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
                                         nh->lsock, &do_udp_read, nh);
    }
    LOG (GNUNET_ERROR_TYPE_INFO,
	 "NAT test listens on port %u (%s)\n",
	 bnd_port,
	 (GNUNET_YES == is_tcp) ? "tcp" : "udp");
    nh->nat = GNUNET_NAT_register (cfg, is_tcp, adv_port, 1,
                                   addrs, addrlens,
                                   &addr_cb, NULL, nh, NULL);
    if (NULL == nh->nat)
    {
      LOG (GNUNET_ERROR_TYPE_INFO,
          _("NAT test failed to start NAT library\n"));
      if (NULL != nh->ltask)
      {
        GNUNET_SCHEDULER_cancel (nh->ltask);
        nh->ltask = NULL;
      }
      if (NULL != nh->lsock)
      {
        GNUNET_NETWORK_socket_close (nh->lsock);
        nh->lsock = NULL;
      }
      nh->status = GNUNET_NAT_ERROR_NAT_REGISTER_FAILED;
      nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout, nh);
      return nh;
    }
  }
  nh->ttask = GNUNET_SCHEDULER_add_delayed (timeout, &do_timeout, nh);
  return nh;
}
コード例 #17
0
ファイル: gnunet-nat.c プロジェクト: GNUnet/gnunet
/**
 * Main function that will be run.
 *
 * @param cls closure
 * @param args remaining command-line arguments
 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
 * @param c configuration
 */
static void
run (void *cls,
     char *const *args,
     const char *cfgfile,
     const struct GNUNET_CONFIGURATION_Handle *c)
{
  uint8_t af;
  struct sockaddr *local_sa;
  struct sockaddr *remote_sa;
  socklen_t local_len;
  size_t remote_len;

  if (use_tcp && use_udp)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		"Cannot use TCP and UDP\n");
    global_ret = 1;
    return;
  }
  proto = 0;
  if (use_tcp)
    proto = IPPROTO_TCP;
  if (use_udp)
    proto = IPPROTO_UDP;

  GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
				 NULL);

  if (0 == proto)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		"Must specify either TCP or UDP\n");
    global_ret = 1;
    return;
  }
  if (NULL != local_addr)
  {
    local_len = (socklen_t) GNUNET_STRINGS_parse_socket_addr (local_addr,
							      &af,
							      &local_sa);
    if (0 == local_len)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		  "Invalid socket address `%s'\n",
		  local_addr);
      global_ret = 1;
      return;
    }
  }
  if (NULL != remote_addr)
  {
    remote_len = GNUNET_STRINGS_parse_socket_addr (remote_addr,
						   &af,
						   &remote_sa);
    if (0 == remote_len)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		  "Invalid socket address `%s'\n",
		  remote_addr);
      global_ret = 1;
      return;
    }
  }

  if (NULL != local_addr)
  {
    if (NULL == section_name)
      section_name = GNUNET_strdup ("undefined");
    nh = GNUNET_NAT_register (c,
			      section_name,
			      proto,
			      1,
			      (const struct sockaddr **) &local_sa,
			      &local_len,
			      &address_cb,
			      (listen_reversal) ? &reversal_cb : NULL,
			      NULL);
  }
  else if (listen_reversal)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		"Use of `-W` only effective in combination with `-i`\n");    
    global_ret = 1;
    GNUNET_SCHEDULER_shutdown ();
    return;
  }

  if (NULL != remote_addr)
  {
    int ret;
    
    if ( (NULL == nh) ||
	 (sizeof (struct sockaddr_in) != local_len) )
    {
      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		  "Require IPv4 local address to initiate connection reversal\n");
      global_ret = 1;
      GNUNET_SCHEDULER_shutdown ();
      return;
    }
    if (sizeof (struct sockaddr_in) != remote_len)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		  "Require IPv4 reversal target address\n");
      global_ret = 1;
      GNUNET_SCHEDULER_shutdown ();
      return;
    }
    GNUNET_assert (AF_INET == local_sa->sa_family);
    GNUNET_assert (AF_INET == remote_sa->sa_family);
    ret = GNUNET_NAT_request_reversal (nh,
				       (const struct sockaddr_in *) local_sa,
				       (const struct sockaddr_in *) remote_sa);
    switch (ret)
    {
    case GNUNET_SYSERR:
      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		  "Connection reversal internal error\n");
      break;
    case GNUNET_NO:
      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		  "Connection reversal unavailable\n");
      break;
    case GNUNET_OK:
      /* operation in progress */
      break;
    }
  }
  
  if (do_stun)
  {
    if (NULL == local_addr)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		  "Require local address to support STUN requests\n");
      global_ret = 1;
      GNUNET_SCHEDULER_shutdown ();
      return;
    }
    if (IPPROTO_UDP != proto)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
		  "STUN only supported over UDP\n");
      global_ret = 1;
      GNUNET_SCHEDULER_shutdown ();
      return;
    }
    ls = GNUNET_NETWORK_socket_create (af,
				       SOCK_DGRAM,
				       IPPROTO_UDP);
    if (GNUNET_OK !=
	GNUNET_NETWORK_socket_bind (ls,
				    local_sa,
				    local_len))
    {
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
		  "Failed to bind to %s: %s\n",
		  GNUNET_a2s (local_sa,
			      local_len),
		  STRERROR (errno));
      global_ret = 1;
      GNUNET_SCHEDULER_shutdown ();
      return;
    }
    rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
					   ls,
					   &stun_read_task,
					   NULL);
  }

  test_finished ();
}