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

📄 fs.c

📁 GNUnet是一个安全的点对点网络框架
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
     This file is part of GNUnet.
     (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 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., 51 Franklin Street, Fifth Floor,
     Boston, MA 02110-1301, USA.
*/

/**
 * @file applications/fs/gap/fs.c
 * @brief functions for handling CS and P2P file-sharing requests
 * @author Christian Grothoff
 *
 * This file contains all of the entry points to the file-sharing
 * module.
 *
 * TODO:
 * - integrate with migration submodule
 * - make sure we do an immediate PUSH for DHT stuff
 *   given to us with anonymity_level zero.
 */

#include "platform.h"
#include "gnunet_util.h"
#include "gnunet_directories.h"
#include "gnunet_protocols.h"
#include "gnunet_datastore_service.h"
#include "gnunet_dht_service.h"
#include "gnunet_identity_service.h"
#include "gnunet_stats_service.h"
#include "gnunet_traffic_service.h"
#include "ecrs_core.h"
#include "anonymity.h"
#include "fs.h"
#include "fs_dht.h"
#include "gap.h"
#include "migration.h"
#include "querymanager.h"
#include "ondemand.h"
#include "plan.h"
#include "pid_table.h"
#include "shared.h"


#define DEBUG_FS GNUNET_NO

/**
 * Lock shared between all C files in this
 * directory.
 */
struct GNUNET_Mutex *GNUNET_FS_lock;

static struct GNUNET_GE_Context *ectx;

static GNUNET_CoreAPIForPlugins *coreAPI;

static GNUNET_Identity_ServiceAPI *identity;

static GNUNET_Stats_ServiceAPI *stats;

static GNUNET_Datastore_ServiceAPI *datastore;

static int active_migration;

static int stat_gap_query_received;

static int stat_gap_query_drop_busy;

static int stat_gap_content_received;

static int stat_gap_trust_awarded;

/**
 * Hard CPU limit
 */
static unsigned long long hardCPULimit;

/**
 * Hard network upload limit.
 */
static unsigned long long hardUpLimit;



/* ********************* CS handlers ********************** */

/**
 * Process a request to insert content from the client.
 *
 * @return GNUNET_SYSERR if the TCP connection should be closed, otherwise GNUNET_OK
 */
static int
handle_cs_insert_request (struct GNUNET_ClientHandle *sock,
                          const GNUNET_MessageHeader * req)
{
  const CS_fs_request_insert_MESSAGE *ri;
  GNUNET_DatastoreValue *datum;
  struct GNUNET_GE_Context *cectx;
  GNUNET_HashCode query;
  int ret;
#if DEBUG_FS
  GNUNET_EncName enc;
#endif

  ri = (const CS_fs_request_insert_MESSAGE *) req;
  if ((ntohs (req->size) < sizeof (CS_fs_request_insert_MESSAGE)) ||
      (GNUNET_OK !=
       GNUNET_EC_file_block_check_and_get_query (ntohs (ri->header.size) -
                                                 sizeof
                                                 (CS_fs_request_insert_MESSAGE),
                                                 (const GNUNET_EC_DBlock *)
                                                 &ri[1], GNUNET_YES, &query)))
    {
      GNUNET_GE_BREAK (ectx, 0);
      return GNUNET_SYSERR;
    }
  datum = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) +
                         ntohs (req->size) -
                         sizeof (CS_fs_request_insert_MESSAGE));
  datum->size =
    htonl (sizeof (GNUNET_DatastoreValue) + ntohs (req->size) -
           sizeof (CS_fs_request_insert_MESSAGE));
  datum->expiration_time = ri->expiration;
  datum->priority = ri->priority;
  datum->anonymity_level = ri->anonymity_level;
  datum->type =
    htonl (GNUNET_EC_file_block_get_type
           (ntohs (ri->header.size) - sizeof (CS_fs_request_insert_MESSAGE),
            (const GNUNET_EC_DBlock *) &ri[1]));
#if DEBUG_FS
  IF_GELOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
            GNUNET_hash_to_enc (&query, &enc));
  GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
                 "FS received REQUEST INSERT (query: `%s', type: %u, priority %u)\n",
                 &enc, ntohl (datum->type), ntohl (ri->priority));
#endif
  memcpy (&datum[1],
          &ri[1], ntohs (req->size) - sizeof (CS_fs_request_insert_MESSAGE));
  ret = datastore->putUpdate (&query, datum);
  if (ret == GNUNET_NO)
    {
      cectx = coreAPI->cs_log_context_create (sock);
      GNUNET_GE_LOG (cectx,
                     GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
                     _("Datastore full.\n"));
      GNUNET_GE_free_context (cectx);
    }
  GNUNET_free (datum);
  return coreAPI->cs_send_value (sock, ret);
}

/**
 * Process a request to symlink a file
 */
static int
handle_cs_init_index_request (struct GNUNET_ClientHandle *sock,
                              const GNUNET_MessageHeader * req)
{
  const CS_fs_request_init_index_MESSAGE *ri;
  struct GNUNET_GE_Context *cectx;
  int fnLen;
  int ret;
  char *fn;

  fnLen = ntohs (req->size) - sizeof (CS_fs_request_init_index_MESSAGE);
  if ((ntohs (req->size) < sizeof (CS_fs_request_init_index_MESSAGE))
#if WINDOWS
      || (fnLen > _MAX_PATH)
#endif
    )
    {
      GNUNET_GE_BREAK (ectx, 0);
      return GNUNET_SYSERR;
    }
  ri = (const CS_fs_request_init_index_MESSAGE *) req;
  fn = GNUNET_malloc (fnLen + 1);
  strncpy (fn, (const char *) &ri[1], fnLen + 1);
  fn[fnLen] = 0;
  cectx = coreAPI->cs_log_context_create (sock);
  ret =
    GNUNET_FS_ONDEMAND_index_prepare_with_symlink (cectx, &ri->fileId, fn);
  GNUNET_GE_free_context (cectx);
  GNUNET_free (fn);
#if DEBUG_FS
  GNUNET_GE_LOG (ectx,
                 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
                 "Sending confirmation (%s) of index initialization request to client\n",
                 ret == GNUNET_OK ? "success" : "failure");
#endif
  return coreAPI->cs_send_value (sock, ret);
}

/**
 * Process a request to index content from the client.
 *
 * @return GNUNET_SYSERR if the TCP connection should be closed, otherwise GNUNET_OK
 */
static int
handle_cs_index_request (struct GNUNET_ClientHandle *sock,
                         const GNUNET_MessageHeader * req)
{
  int ret;
  const CS_fs_request_index_MESSAGE *ri;
  struct GNUNET_GE_Context *cectx;
#if DEBUG_FS
  GNUNET_HashCode hc;
  GNUNET_EncName enc;
#endif

  if (ntohs (req->size) < sizeof (CS_fs_request_index_MESSAGE))
    {
      GNUNET_GE_BREAK (ectx, 0);
      return GNUNET_SYSERR;
    }
  cectx = coreAPI->cs_log_context_create (sock);
  ri = (const CS_fs_request_index_MESSAGE *) req;
#if DEBUG_FS
  GNUNET_EC_file_block_get_query ((const GNUNET_EC_DBlock *) &ri[1],
                                  ntohs (ri->header.size) -
                                  sizeof (CS_fs_request_index_MESSAGE), &hc);
  IF_GELOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
            GNUNET_hash_to_enc (&hc, &enc));
  GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
                 "FS received REQUEST INDEX (query: `%s', priority %u)\n",
                 &enc, ntohl (ri->priority));
#endif
  ret = GNUNET_FS_ONDEMAND_add_indexed_content (cectx,
                                                datastore,
                                                ntohl (ri->priority),
                                                GNUNET_ntohll
                                                (ri->expiration),
                                                GNUNET_ntohll
                                                (ri->fileOffset),
                                                ntohl (ri->anonymity_level),
                                                &ri->fileId,
                                                ntohs (ri->header.size) -
                                                sizeof
                                                (CS_fs_request_index_MESSAGE),
                                                (const GNUNET_EC_DBlock *)
                                                &ri[1]);
  GNUNET_GE_free_context (cectx);
#if DEBUG_FS
  GNUNET_GE_LOG (ectx,
                 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
                 "Sending confirmation (%s) of index request to client\n",
                 ret == GNUNET_OK ? "success" : "failure");
#endif
  return coreAPI->cs_send_value (sock, ret);
}

/**
 * Process a query to delete content.
 *
 * @return GNUNET_SYSERR if the TCP connection should be closed, otherwise GNUNET_OK
 */
static int
handle_cs_delete_request (struct GNUNET_ClientHandle *sock,
                          const GNUNET_MessageHeader * req)
{
  int ret;
  const CS_fs_request_delete_MESSAGE *rd;
  GNUNET_DatastoreValue *value;
  GNUNET_HashCode query;
  unsigned int type;
#if DEBUG_FS
  GNUNET_EncName enc;
#endif

  if (ntohs (req->size) < sizeof (CS_fs_request_delete_MESSAGE))
    {
      GNUNET_GE_BREAK (ectx, 0);
      return GNUNET_SYSERR;
    }
  rd = (const CS_fs_request_delete_MESSAGE *) req;
  value = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) +
                         ntohs (req->size) -
                         sizeof (CS_fs_request_delete_MESSAGE));
  value->size =
    ntohl (sizeof (GNUNET_DatastoreValue) + ntohs (req->size) -
           sizeof (CS_fs_request_delete_MESSAGE));
  type =
    GNUNET_EC_file_block_get_type (ntohs (rd->header.size) -
                                   sizeof (CS_fs_request_delete_MESSAGE),
                                   (const GNUNET_EC_DBlock *) &rd[1]);
  value->type = htonl (type);
  memcpy (&value[1],
          &rd[1], ntohs (req->size) - sizeof (CS_fs_request_delete_MESSAGE));
  if (GNUNET_OK !=
      GNUNET_EC_file_block_check_and_get_query (ntohs (rd->header.size) -
                                                sizeof
                                                (CS_fs_request_delete_MESSAGE),
                                                (const GNUNET_EC_DBlock *)
                                                &rd[1], GNUNET_NO, &query))
    {
      GNUNET_free (value);
      GNUNET_GE_BREAK (ectx, 0);
      return GNUNET_SYSERR;
    }
#if DEBUG_FS
  IF_GELOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
            GNUNET_hash_to_enc (&query, &enc));
  GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
                 "FS received REQUEST DELETE (query: `%s', type: %u)\n", &enc,
                 type);
#endif
  GNUNET_mutex_lock (GNUNET_FS_lock);
  value->type = htonl (GNUNET_ECRS_BLOCKTYPE_ANY);
  ret = datastore->get (&query, type,
                        &GNUNET_FS_HELPER_complete_value_from_database_callback,
                        value);
  if ((0 < ret) && (value->type != htonl (GNUNET_ECRS_BLOCKTYPE_ANY)))
    {
      ret = datastore->del (&query, value);
    }
  else
    {                           /* not found */
      ret = GNUNET_SYSERR;
    }
  GNUNET_mutex_unlock (GNUNET_FS_lock);
  GNUNET_free (value);
#if DEBUG_FS
  GNUNET_GE_LOG (ectx,
                 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
                 "Sending confirmation (%s) of delete request to client\n",
                 ret != GNUNET_SYSERR ? "success" : "failure");

⌨️ 快捷键说明

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