📄 fs.c
字号:
/*
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 + -