⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 init.c

📁 GNUnet是一个安全的点对点网络框架
💻 C
字号:
/*
     This file is part of GNUnet
     (C) 2006 Christian Grothoff (and other contributing authors)

     GNUnet is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published
     by the Free Software Foundation; either version 2, or (at your
     option) any later version.

     GNUnet is distributed in the hope that it will be useful, but
     WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with GNUnet; see the file COPYING.  If not, write to the
     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
     Boston, MA 02111-1307, USA.
*/

/**
 * @file src/transports/upnp/init.c
 * @brief API for UPnP access
 * @author Christian Grothoff
 */

#include "platform.h"
#include "gnunet_util.h"
#include "upnp.h"
#include "gnunet_upnp_service.h"
#include "gnunet_core.h"

static struct GNUNET_GE_Context *ectx;

static struct GNUNET_GC_Configuration *cfg;

static struct GNUNET_CronManager *cron;

static struct GNUNET_Mutex *lock;

typedef struct
{
  unsigned short port;
  const char *proto;
} PMap;

static PMap *maps;

static unsigned int maps_size;

static struct GNUNET_ThreadHandle *discovery;

static int discovery_socket;

/**
 * Obtain the public/external IP address.
 *
 * @return GNUNET_SYSERR on error, GNUNET_OK on success
 */
static int
gnunet_upnp_get_public_ip (struct in_addr *address)
{
  const char *ip;
  socklen_t socklen;
  struct sockaddr *sa;
  struct sockaddr_in s4;
  int ret;

  ip = gaim_upnp_get_public_ip ();
  if (ip == NULL)
    return GNUNET_SYSERR;
  socklen = sizeof (struct sockaddr_in);
  sa = (struct sockaddr *) &s4;
  ret = GNUNET_get_ip_from_hostname (NULL, ip, AF_INET, &sa, &socklen);
  if (ret == GNUNET_OK)
    *address = s4.sin_addr;
  return ret;
}

static void
kill_discovery ()
{
  void *unused;

  if (discovery != NULL)
    {
      SHUTDOWN (discovery_socket, SHUT_RDWR);
      CLOSE (discovery_socket);
      GNUNET_thread_join (discovery, &unused);
      discovery = NULL;
    }
}

static void *
discover_thread ()
{
  gaim_upnp_discover (ectx, cfg, discovery_socket);
  return NULL;
}

/**
 * Periodically try to (re)discover UPnP access points.
 */
static void
discover (void *unused)
{
  kill_discovery ();
  discovery_socket = SOCKET (PF_INET, SOCK_DGRAM, 0);
  if (discovery_socket == -1)
    return;
  discovery = GNUNET_thread_create (&discover_thread, NULL, 1024 * 128);
}

/**
 * Periodically repeat our requests for port mappings.
 */
static void
portmap (void *unused)
{
  unsigned int i;

  GNUNET_mutex_lock (lock);
  for (i = 0; i < maps_size; i++)
    gaim_upnp_change_port_mapping (ectx,
                                   cfg, GNUNET_NO, maps[i].port,
                                   maps[i].proto);
  GNUNET_mutex_unlock (lock);
}


/**
 * Get the external IP address for the local machine.
 *
 * @return GNUNET_SYSERR on error, GNUNET_OK on success
 */
static int
gnunet_upnp_get_ip (unsigned short port,
                    const char *protocol, struct in_addr *address)
{
  unsigned int i;

  GNUNET_mutex_lock (lock);
  for (i = 0; i < maps_size; i++)
    if ((0 == strcmp (maps[i].proto, protocol)) && (maps[i].port == port))
      break;
  if (i == maps_size)
    {
      /* new entry! */
      GNUNET_array_grow (maps, maps_size, maps_size + 1);
      maps[i].proto = protocol;
      maps[i].port = port;
      gaim_upnp_change_port_mapping (ectx, cfg, GNUNET_YES, port, protocol);
    }
  GNUNET_mutex_unlock (lock);
  return gnunet_upnp_get_public_ip (address);
}


/**
 * Get the external IP address for the local machine.
 */
GNUNET_UPnP_ServiceAPI *
provide_module_upnp (GNUNET_CoreAPIForPlugins * capi)
{
  static GNUNET_UPnP_ServiceAPI api;

  ectx = capi->ectx;
  cfg = capi->cfg;
  cron = GNUNET_cron_create (ectx);
  lock = GNUNET_mutex_create (GNUNET_NO);
  GNUNET_cron_start (cron);
  GNUNET_cron_add_job (cron, &discover, 0, 5 * GNUNET_CRON_MINUTES, NULL);
  GNUNET_cron_add_job (cron, &portmap, 150 * GNUNET_CRON_SECONDS,
                       5 * GNUNET_CRON_MINUTES, NULL);
  api.get_ip = gnunet_upnp_get_ip;
  return &api;
}

/**
 * Shutdown UPNP.
 */
int
release_module_upnp ()
{
  unsigned int i;

  if (cron == NULL)
    return GNUNET_SYSERR;       /* not loaded! */
  for (i = 0; i < maps_size; i++)
    gaim_upnp_change_port_mapping (ectx,
                                   cfg, GNUNET_NO, maps[i].port,
                                   maps[i].proto);
  GNUNET_cron_stop (cron);
  GNUNET_cron_del_job (cron, &discover, 5 * GNUNET_CRON_MINUTES, NULL);
  GNUNET_cron_del_job (cron, &portmap, 5 * GNUNET_CRON_MINUTES, NULL);
  GNUNET_cron_destroy (cron);
  kill_discovery ();
  cron = NULL;
  GNUNET_mutex_destroy (lock);
  lock = NULL;
  GNUNET_array_grow (maps, maps_size, 0);
  ectx = NULL;
  cfg = NULL;
  return GNUNET_OK;
}


/* end of init.c */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -