GNUnet  0.19.2
fs_download.c File Reference

download methods More...

#include "platform.h"
#include "gnunet_constants.h"
#include "gnunet_fs_service.h"
#include "fs_api.h"
#include "fs_tree.h"
Include dependency graph for fs_download.c:

Go to the source code of this file.

Data Structures

struct  ProcessResultClosure
 Closure for iterator processing results. More...
 

Macros

#define GNUNET_FS_URI_CHK_PREFIX   GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX
 

Functions

static int is_recursive_download (struct GNUNET_FS_DownloadContext *dc)
 Determine if the given download (options and meta data) should cause use to try to do a recursive download. More...
 
static uint64_t compute_disk_offset (uint64_t fsize, uint64_t off, unsigned int depth)
 We're storing the IBLOCKS after the DBLOCKS on disk (so that we only have to truncate the file once we're done). More...
 
void GNUNET_FS_download_make_status_ (struct GNUNET_FS_ProgressInfo *pi, struct GNUNET_FS_DownloadContext *dc)
 Fill in all of the generic fields for a download event and call the callback. More...
 
static int process_result_with_request (void *cls, const struct GNUNET_HashCode *key, void *value)
 Iterator over entries in the pending requests in the 'active' map for the reply that we just got. More...
 
static int encrypt_existing_match (struct GNUNET_FS_DownloadContext *dc, const struct ContentHashKey *chk, struct DownloadRequest *dr, const char *block, size_t len, int do_store)
 We've found a matching block without downloading it. More...
 
static void try_reconnect (struct GNUNET_FS_DownloadContext *dc)
 We've lost our connection with the FS service. More...
 
static void trigger_recursive_download (void *cls, const char *filename, const struct GNUNET_FS_Uri *uri, const struct GNUNET_FS_MetaData *meta, size_t length, const void *data)
 We found an entry in a directory. More...
 
static void full_recursive_download (struct GNUNET_FS_DownloadContext *dc)
 We're done downloading a directory. More...
 
static void check_completed (struct GNUNET_FS_DownloadContext *dc)
 Check if all child-downloads have completed (or trigger them if necessary) and once we're completely done, signal completion (and possibly recurse to parent). More...
 
static void try_match_block (struct GNUNET_FS_DownloadContext *dc, struct DownloadRequest *dr, const char *data, size_t data_len)
 We got a block of plaintext data (from the meta data). More...
 
static int match_full_data (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_len)
 Type of a function that libextractor calls for each meta data item found. More...
 
static void propagate_up (struct DownloadRequest *dr)
 Set the state of the given download request to BRS_DOWNLOAD_UP and propagate it up the tree. More...
 
static void try_top_down_reconstruction (struct GNUNET_FS_DownloadContext *dc, struct DownloadRequest *dr)
 Try top-down reconstruction. More...
 
static int retry_entry (void *cls, const struct GNUNET_HashCode *key, void *entry)
 Add entries to the message queue. More...
 
static void schedule_block_download (struct GNUNET_FS_DownloadContext *dc, struct DownloadRequest *dr)
 Schedule the download of the specified block in the tree. More...
 
void GNUNET_FS_free_download_request_ (struct DownloadRequest *dr)
 (recursively) free download request structure More...
 
static int check_put (void *cls, const struct ClientPutMessage *cm)
 Type of a function to call when we check the PUT message from the service. More...
 
static void handle_put (void *cls, const struct ClientPutMessage *cm)
 Type of a function to call when we receive a message from the service. More...
 
static void download_mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
 Generic error handler, called with the appropriate error code and the same closure specified at the creation of the message queue. More...
 
static void do_reconnect (void *cls)
 Reconnect to the FS service and transmit our queries NOW. More...
 
static void activate_fs_download (void *cls)
 We're allowed to ask the FS service for our blocks. More...
 
static void deactivate_fs_download (void *cls)
 We must stop to ask the FS service for our blocks. More...
 
static struct DownloadRequestcreate_download_request (struct DownloadRequest *parent, unsigned int chk_idx, unsigned int depth, uint64_t dr_offset, uint64_t file_start_offset, uint64_t desired_length)
 (recursively) Create a download request structure. More...
 
static void reconstruct_cont (void *cls)
 Continuation after a possible attempt to reconstruct the current IBlock from the existing file. More...
 
static void get_next_block (void *cls)
 Task requesting the next block from the tree encoder. More...
 
static void reconstruct_cb (void *cls, const struct ContentHashKey *chk, uint64_t offset, unsigned int depth, enum GNUNET_BLOCK_Type type, const void *block, uint16_t block_size)
 Function called asking for the current (encoded) block to be processed. More...
 
static size_t fh_reader (void *cls, uint64_t offset, size_t max, void *buf, char **emsg)
 Function called by the tree encoder to obtain a block of plaintext data (for the lowest level of the tree). More...
 
void GNUNET_FS_download_start_task_ (void *cls)
 Task that creates the initial (top-level) download request for the file. More...
 
void GNUNET_FS_download_signal_suspend_ (void *cls)
 Create SUSPEND event for the given download operation and then clean up our state (without stop signal). More...
 
struct GNUNET_FS_DownloadContextcreate_download_context (struct GNUNET_FS_Handle *h, const struct GNUNET_FS_Uri *uri, const struct GNUNET_FS_MetaData *meta, const char *filename, const char *tempname, uint64_t offset, uint64_t length, uint32_t anonymity, enum GNUNET_FS_DownloadOptions options, void *cctx)
 Helper function to setup the download context. More...
 
struct GNUNET_FS_DownloadContextGNUNET_FS_download_start (struct GNUNET_FS_Handle *h, const struct GNUNET_FS_Uri *uri, const struct GNUNET_FS_MetaData *meta, const char *filename, const char *tempname, uint64_t offset, uint64_t length, uint32_t anonymity, enum GNUNET_FS_DownloadOptions options, void *cctx, struct GNUNET_FS_DownloadContext *parent)
 Download parts of a file. More...
 
struct GNUNET_FS_DownloadContextGNUNET_FS_download_start_from_search (struct GNUNET_FS_Handle *h, struct GNUNET_FS_SearchResult *sr, const char *filename, const char *tempname, uint64_t offset, uint64_t length, uint32_t anonymity, enum GNUNET_FS_DownloadOptions options, void *cctx)
 Download parts of a file based on a search result. More...
 
void GNUNET_FS_download_start_downloading_ (struct GNUNET_FS_DownloadContext *dc)
 Start the downloading process (by entering the queue). More...
 
void GNUNET_FS_download_suspend (struct GNUNET_FS_DownloadContext *dc)
 Suspend a download. More...
 
void GNUNET_FS_download_resume (struct GNUNET_FS_DownloadContext *dc)
 Resume a suspended download. More...
 
void GNUNET_FS_download_stop (struct GNUNET_FS_DownloadContext *dc, int do_delete)
 Stop a download (aborts if download is incomplete). More...
 

Detailed Description

download methods

Author
Christian Grothoff

Definition in file fs_download.c.

Macro Definition Documentation

◆ GNUNET_FS_URI_CHK_PREFIX

#define GNUNET_FS_URI_CHK_PREFIX   GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX

Definition at line 837 of file fs_download.c.

Function Documentation

◆ is_recursive_download()

static int is_recursive_download ( struct GNUNET_FS_DownloadContext dc)
static

Determine if the given download (options and meta data) should cause use to try to do a recursive download.

Definition at line 38 of file fs_download.c.

39 {
40  return (0 != (dc->options & GNUNET_FS_DOWNLOAD_OPTION_RECURSIVE)) &&
42  ((NULL == dc->meta) &&
43  ((NULL == dc->filename) ||
44  ((strlen (dc->filename) >= strlen (GNUNET_FS_DIRECTORY_EXT)) &&
45  (NULL != strstr (dc->filename + strlen (dc->filename)
46  - strlen (GNUNET_FS_DIRECTORY_EXT),
48 }
static struct GNUNET_FS_DownloadContext * dc
int GNUNET_FS_meta_data_test_for_directory(const struct GNUNET_FS_MetaData *md)
Does the meta-data claim that this is a directory? Checks if the mime-type is that of a GNUnet direct...
Definition: fs_directory.c:55
#define GNUNET_FS_DIRECTORY_EXT
@ GNUNET_FS_DOWNLOAD_OPTION_RECURSIVE
Do a recursive download (that is, automatically trigger the download of files in directories).
@ GNUNET_YES
char * filename
Where are we writing the data (name of the file, can be NULL!).
Definition: fs_api.h:1822
struct GNUNET_FS_MetaData * meta
Known meta-data for the file (can be NULL).
Definition: fs_api.h:1805
enum GNUNET_FS_DownloadOptions options
Options for the download.
Definition: fs_api.h:1923

References dc, GNUNET_FS_DownloadContext::filename, GNUNET_FS_DIRECTORY_EXT, GNUNET_FS_DOWNLOAD_OPTION_RECURSIVE, GNUNET_FS_meta_data_test_for_directory(), GNUNET_YES, GNUNET_FS_DownloadContext::meta, and GNUNET_FS_DownloadContext::options.

Referenced by check_completed(), create_download_context(), and process_result_with_request().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ compute_disk_offset()

static uint64_t compute_disk_offset ( uint64_t  fsize,
uint64_t  off,
unsigned int  depth 
)
static

We're storing the IBLOCKS after the DBLOCKS on disk (so that we only have to truncate the file once we're done).

Given the offset of a block (with respect to the DBLOCKS) and its depth, return the offset where we would store this block in the file.

Parameters
fsizeoverall file size
offoffset of the block in the file
depthdepth of the block in the tree, 0 for DBLOCK
Returns
off for DBLOCKS (depth == treedepth), otherwise an offset past the end of the file that does not overlap with the range for any other block

Definition at line 68 of file fs_download.c.

69 {
70  unsigned int i;
71  uint64_t lsize; /* what is the size of all IBlocks for depth "i"? */
72  uint64_t loff; /* where do IBlocks for depth "i" start? */
73  unsigned int ioff; /* which IBlock corresponds to "off" at depth "i"? */
74 
75  if (0 == depth)
76  return off;
77  /* first IBlocks start at the end of file, rounded up
78  * to full DBLOCK_SIZE */
79  loff = ((fsize + DBLOCK_SIZE - 1) / DBLOCK_SIZE) * DBLOCK_SIZE;
80  lsize =
81  ((fsize + DBLOCK_SIZE - 1) / DBLOCK_SIZE) * sizeof(struct ContentHashKey);
82  GNUNET_assert (0 == (off % DBLOCK_SIZE));
83  ioff = (off / DBLOCK_SIZE);
84  for (i = 1; i < depth; i++)
85  {
86  loff += lsize;
87  lsize = (lsize + CHK_PER_INODE - 1) / CHK_PER_INODE;
88  GNUNET_assert (lsize > 0);
89  GNUNET_assert (0 == (ioff % CHK_PER_INODE));
90  ioff /= CHK_PER_INODE;
91  }
92  return loff + ioff * sizeof(struct ContentHashKey);
93 }
#define DBLOCK_SIZE
Size of the individual blocks used for file-sharing.
Definition: fs.h:41
#define CHK_PER_INODE
Pick a multiple of 2 here to achieve 8-byte alignment! We also probably want DBlocks to have (roughly...
Definition: fs_api.h:44
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
content hash key
Definition: fs.h:55

References CHK_PER_INODE, DBLOCK_SIZE, and GNUNET_assert.

Referenced by process_result_with_request(), and try_top_down_reconstruction().

Here is the caller graph for this function:

◆ GNUNET_FS_download_make_status_()

void GNUNET_FS_download_make_status_ ( struct GNUNET_FS_ProgressInfo pi,
struct GNUNET_FS_DownloadContext dc 
)

Fill in all of the generic fields for a download event and call the callback.

Parameters
pistructure to fill in
dcoverall download context

Definition at line 104 of file fs_download.c.

106 {
107  pi->value.download.dc = dc;
108  pi->value.download.cctx = dc->client_info;
109  pi->value.download.pctx =
110  (NULL == dc->parent) ? NULL : dc->parent->client_info;
111  pi->value.download.sctx =
112  (NULL == dc->search) ? NULL : dc->search->client_info;
113  pi->value.download.uri = dc->uri;
114  pi->value.download.filename = dc->filename;
115  pi->value.download.size = dc->length;
116  /* FIXME: Fix duration calculation to account for pauses */
117  pi->value.download.duration =
119  pi->value.download.completed = dc->completed;
120  pi->value.download.anonymity = dc->anonymity;
121  pi->value.download.eta =
123  pi->value.download.is_active = (NULL == dc->mq) ? GNUNET_NO : GNUNET_YES;
124  pi->fsh = dc->h;
125  if (0 == (dc->options & GNUNET_FS_DOWNLOAD_IS_PROBE))
126  dc->client_info = dc->h->upcb (dc->h->upcb_cls, pi);
127  else
129 }
void * GNUNET_FS_search_probe_progress_(void *cls, const struct GNUNET_FS_ProgressInfo *info)
Notification of FS that a search probe has made progress.
Definition: fs_search.c:281
static struct GNUNET_PEERINFO_Handle * pi
Handle to peerinfo service.
@ GNUNET_FS_DOWNLOAD_IS_PROBE
Internal option used to flag this download as a 'probe' for a search result.
@ GNUNET_NO
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:436
struct GNUNET_TIME_Relative GNUNET_TIME_calculate_eta(struct GNUNET_TIME_Absolute start, uint64_t finished, uint64_t total)
Calculate the estimate time of arrival/completion for an operation.
Definition: time.c:564
struct GNUNET_FS_Uri * uri
URI that identifies the file that we are downloading.
Definition: fs_api.h:1800
void * client_info
Context kept for the client.
Definition: fs_api.h:1795
uint64_t completed
How many bytes have we already received within the specified range (DBlocks only).
Definition: fs_api.h:1890
struct GNUNET_FS_SearchResult * search
Associated search (used when downloading files based on search results), or NULL for none.
Definition: fs_api.h:1770
uint64_t length
How many bytes starting from offset are desired? This is NOT the overall length of the file!
Definition: fs_api.h:1884
struct GNUNET_MQ_Handle * mq
Connection to the FS service.
Definition: fs_api.h:1758
uint32_t anonymity
Desired level of anonymity.
Definition: fs_api.h:1913
struct GNUNET_FS_DownloadContext * parent
Parent download (used when downloading files in directories).
Definition: fs_api.h:1764
struct GNUNET_FS_Handle * h
Global FS context.
Definition: fs_api.h:1748
struct GNUNET_TIME_Absolute start_time
Time download was started.
Definition: fs_api.h:1903
void * upcb_cls
Closure for upcb.
Definition: fs_api.h:1089
GNUNET_FS_ProgressCallback upcb
Function to call with updates on our progress.
Definition: fs_api.h:1084
void * client_info
Client info for this search result.
Definition: fs_api.h:534

References GNUNET_FS_DownloadContext::anonymity, GNUNET_FS_SearchResult::client_info, GNUNET_FS_DownloadContext::client_info, GNUNET_FS_DownloadContext::completed, dc, GNUNET_FS_DownloadContext::filename, GNUNET_FS_DOWNLOAD_IS_PROBE, GNUNET_FS_search_probe_progress_(), GNUNET_NO, GNUNET_TIME_absolute_get_duration(), GNUNET_TIME_calculate_eta(), GNUNET_YES, GNUNET_FS_DownloadContext::h, GNUNET_FS_DownloadContext::length, GNUNET_FS_DownloadContext::mq, GNUNET_FS_DownloadContext::options, GNUNET_FS_DownloadContext::parent, pi, GNUNET_FS_DownloadContext::search, GNUNET_FS_DownloadContext::start_time, GNUNET_FS_Handle::upcb, GNUNET_FS_Handle::upcb_cls, and GNUNET_FS_DownloadContext::uri.

Referenced by activate_fs_download(), check_completed(), deactivate_fs_download(), GNUNET_FS_download_resume(), GNUNET_FS_download_signal_suspend_(), GNUNET_FS_download_start_task_(), process_result_with_request(), reconstruct_cb(), search_result_stop(), signal_download_resume(), and try_match_block().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_result_with_request()

static int process_result_with_request ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Iterator over entries in the pending requests in the 'active' map for the reply that we just got.

Parameters
clsclosure (our struct ProcessResultClosure)
keyquery for the given value / request
valuevalue in the hash map (a struct DownloadRequest)
Returns
GNUNET_YES (we should continue to iterate); unless serious error

Definition at line 1009 of file fs_download.c.

1012 {
1013  struct ProcessResultClosure *prc = cls;
1014  struct DownloadRequest *dr = value;
1015  struct GNUNET_FS_DownloadContext *dc = prc->dc;
1016  struct DownloadRequest *drc;
1017  struct GNUNET_DISK_FileHandle *fh = NULL;
1020  char pt[prc->size];
1021  struct GNUNET_FS_ProgressInfo pi;
1022  uint64_t off;
1023  size_t bs;
1024  size_t app;
1025  int i;
1026  struct ContentHashKey *chkarr;
1027 
1028  GNUNET_log (
1030  "Received %u byte block `%s' matching pending request at depth %u and offset %llu/%llu\n",
1031  (unsigned int) prc->size,
1032  GNUNET_h2s (key),
1033  dr->depth,
1034  (unsigned long long) dr->offset,
1035  (unsigned long long) GNUNET_ntohll (dc->uri->data.chk.file_length));
1037  dc->uri->data.chk.file_length),
1038  dr->offset,
1039  dr->depth);
1040  if (prc->size != bs)
1041  {
1042  GNUNET_asprintf (
1043  &dc->emsg,
1044  _ (
1045  "Internal error or bogus download URI (expected %lu bytes at depth %u and offset %llu/%llu, got %lu bytes)"),
1046  bs,
1047  dr->depth,
1048  (unsigned long long) dr->offset,
1049  (unsigned long long) GNUNET_ntohll (dc->uri->data.chk.file_length),
1050  prc->size);
1052  while (NULL != dr->parent)
1053  {
1054  dr->state = BRS_ERROR;
1055  dr = dr->parent;
1056  }
1057  dr->state = BRS_ERROR;
1058  goto signal_error;
1059  }
1060 
1061  (void) GNUNET_CONTAINER_multihashmap_remove (dc->active, &prc->query, dr);
1062  GNUNET_CRYPTO_hash_to_aes_key (&dr->chk.key, &skey, &iv);
1063  if (-1 ==
1064  GNUNET_CRYPTO_symmetric_decrypt (prc->data, prc->size, &skey, &iv, pt))
1065  {
1066  GNUNET_break (0);
1067  dc->emsg = GNUNET_strdup (_ ("internal error decrypting content"));
1068  goto signal_error;
1069  }
1071  dr->offset,
1072  dr->depth);
1073  /* save to disk */
1074  if ((GNUNET_YES == prc->do_store) &&
1075  ((NULL != dc->filename) || (is_recursive_download (dc))) &&
1076  ((dr->depth == dc->treedepth) ||
1078  {
1080  : dc->temp_filename,
1087  if (NULL == fh)
1088  {
1089  GNUNET_asprintf (&dc->emsg,
1090  _ ("Download failed: could not open file `%s': %s"),
1091  dc->filename,
1092  strerror (errno));
1093  goto signal_error;
1094  }
1096  "Saving decrypted block to disk at offset %llu\n",
1097  (unsigned long long) off);
1098  if ((off != GNUNET_DISK_file_seek (fh, off, GNUNET_DISK_SEEK_SET)))
1099  {
1100  GNUNET_asprintf (&dc->emsg,
1101  _ ("Failed to seek to offset %llu in file `%s': %s"),
1102  (unsigned long long) off,
1103  dc->filename,
1104  strerror (errno));
1105  goto signal_error;
1106  }
1107  if (prc->size != GNUNET_DISK_file_write (fh, pt, prc->size))
1108  {
1109  GNUNET_asprintf (
1110  &dc->emsg,
1111  _ ("Failed to write block of %u bytes at offset %llu in file `%s': %s"),
1112  (unsigned int) prc->size,
1113  (unsigned long long) off,
1114  dc->filename,
1115  strerror (errno));
1116  goto signal_error;
1117  }
1119  fh = NULL;
1120  }
1121 
1122  if (0 == dr->depth)
1123  {
1124  /* DBLOCK, update progress and try recursion if applicable */
1125  app = prc->size;
1126  if (dr->offset < dc->offset)
1127  {
1128  /* starting offset begins in the middle of pt,
1129  * do not count first bytes as progress */
1130  GNUNET_assert (app > (dc->offset - dr->offset));
1131  app -= (dc->offset - dr->offset);
1132  }
1133  if (dr->offset + prc->size > dc->offset + dc->length)
1134  {
1135  /* end of block is after relevant range,
1136  * do not count last bytes as progress */
1137  GNUNET_assert (app >
1138  (dr->offset + prc->size) - (dc->offset + dc->length));
1139  app -= (dr->offset + prc->size) - (dc->offset + dc->length);
1140  }
1141  dc->completed += app;
1142 
1143  /* do recursive download if option is set and either meta data
1144  * says it is a directory or if no meta data is given AND filename
1145  * ends in '.gnd' (top-level case) */
1146  if (is_recursive_download (dc))
1148  pt,
1149  off,
1151  dc);
1152  }
1154  dr->state = BRS_DOWNLOAD_DOWN;
1156  pi.value.download.specifics.progress.data = pt;
1157  pi.value.download.specifics.progress.offset = dr->offset;
1158  pi.value.download.specifics.progress.data_len = prc->size;
1159  pi.value.download.specifics.progress.depth = dr->depth;
1160  pi.value.download.specifics.progress.respect_offered = prc->respect_offered;
1161  pi.value.download.specifics.progress.num_transmissions =
1162  prc->num_transmissions;
1163  if (prc->last_transmission.abs_value_us !=
1164  GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
1165  pi.value.download.specifics.progress.block_download_duration =
1167  else
1168  pi.value.download.specifics.progress.block_download_duration =
1169  GNUNET_TIME_UNIT_ZERO; /* found locally */
1171  if (0 == dr->depth)
1172  propagate_up (dr);
1173 
1174  if (dc->completed == dc->length)
1175  {
1176  /* download completed, signal */
1178  "Download completed, truncating file to desired length %llu\n",
1179  (unsigned long long) GNUNET_ntohll (
1180  dc->uri->data.chk.file_length));
1181  /* truncate file to size (since we store IBlocks at the end) */
1182  if (NULL != dc->filename)
1183  {
1184  if (0 != truncate (dc->filename,
1187  "truncate",
1188  dc->filename);
1189  }
1190  GNUNET_assert (0 == dr->depth);
1191  check_completed (dc);
1192  }
1193  if (0 == dr->depth)
1194  {
1195  /* bottom of the tree, no child downloads possible, just sync */
1197  return GNUNET_YES;
1198  }
1199 
1200  GNUNET_log (
1202  "Triggering downloads of children (this block was at depth %u and offset %llu)\n",
1203  dr->depth,
1204  (unsigned long long) dr->offset);
1205  GNUNET_assert (0 == (prc->size % sizeof(struct ContentHashKey)));
1206  chkarr = (struct ContentHashKey *) pt;
1207  for (i = dr->num_children - 1; i >= 0; i--)
1208  {
1209  drc = dr->children[i];
1210  switch (drc->state)
1211  {
1212  case BRS_INIT:
1213  if ((drc->chk_idx + 1) * sizeof(struct ContentHashKey) > prc->size)
1214  {
1215  /* 'chkarr' does not have enough space for this chk_idx;
1216  internal error! */
1217  GNUNET_break (0);
1218  GNUNET_assert (0);
1219  dc->emsg = GNUNET_strdup (_ ("internal error decoding tree"));
1220  goto signal_error;
1221  }
1222  drc->chk = chkarr[drc->chk_idx];
1223  drc->state = BRS_CHK_SET;
1224  if (GNUNET_YES == dc->issue_requests)
1225  schedule_block_download (dc, drc);
1226  break;
1227 
1228  case BRS_RECONSTRUCT_DOWN:
1229  GNUNET_assert (0);
1230  break;
1231 
1233  GNUNET_assert (0);
1234  break;
1235 
1236  case BRS_RECONSTRUCT_UP:
1237  GNUNET_assert (0);
1238  break;
1239 
1240  case BRS_CHK_SET:
1241  GNUNET_assert (0);
1242  break;
1243 
1244  case BRS_DOWNLOAD_DOWN:
1245  GNUNET_assert (0);
1246  break;
1247 
1248  case BRS_DOWNLOAD_UP:
1249  GNUNET_assert (0);
1250  break;
1251 
1252  case BRS_ERROR:
1253  GNUNET_assert (0);
1254  break;
1255 
1256  default:
1257  GNUNET_assert (0);
1258  break;
1259  }
1260  }
1262  return GNUNET_YES;
1263 
1264 signal_error:
1265  if (NULL != fh)
1268  pi.value.download.specifics.error.message = dc->emsg;
1270  GNUNET_MQ_destroy (dc->mq);
1271  dc->mq = NULL;
1273  dc->top_request = NULL;
1274  if (NULL != dc->job_queue)
1275  {
1277  dc->job_queue = NULL;
1278  }
1280  return GNUNET_NO;
1281 }
void GNUNET_FS_download_sync_(struct GNUNET_FS_DownloadContext *dc)
Synchronize this download struct with its mirror on disk.
Definition: fs_api.c:2036
void GNUNET_FS_dequeue_(struct GNUNET_FS_QueueEntry *qe)
Dequeue a job from the queue.
Definition: fs_api.c:356
@ BRS_DOWNLOAD_UP
This block and all of its children have been downloaded successfully (full completion propagates up).
Definition: fs_api.h:1661
@ BRS_RECONSTRUCT_META_UP
We've calculated the CHK bottom-up based on the meta data.
Definition: fs_api.h:1629
@ BRS_CHK_SET
We've determined the real, desired CHK for this block (full tree reconstruction failed),...
Definition: fs_api.h:1646
@ BRS_ERROR
We got a block back that matched the query but did not hash to the key (malicious publisher or hash c...
Definition: fs_api.h:1668
@ BRS_RECONSTRUCT_DOWN
We've checked the block on the path down the tree, and the content on disk did match the desired CHK,...
Definition: fs_api.h:1621
@ BRS_INIT
Initial state, block has only been allocated (since it is relevant to the overall download request).
Definition: fs_api.h:1613
@ BRS_DOWNLOAD_DOWN
We've successfully downloaded this block, but the children still need to be either downloaded or veri...
Definition: fs_api.h:1655
@ BRS_RECONSTRUCT_UP
We've calculated the CHK bottom-up based on what we have on disk, which may not be what the desired C...
Definition: fs_api.h:1637
static void propagate_up(struct DownloadRequest *dr)
Set the state of the given download request to BRS_DOWNLOAD_UP and propagate it up the tree.
Definition: fs_download.c:634
static void check_completed(struct GNUNET_FS_DownloadContext *dc)
Check if all child-downloads have completed (or trigger them if necessary) and once we're completely ...
Definition: fs_download.c:376
void GNUNET_FS_free_download_request_(struct DownloadRequest *dr)
(recursively) free download request structure
Definition: fs_download.c:997
void GNUNET_FS_download_make_status_(struct GNUNET_FS_ProgressInfo *pi, struct GNUNET_FS_DownloadContext *dc)
Fill in all of the generic fields for a download event and call the callback.
Definition: fs_download.c:104
static int is_recursive_download(struct GNUNET_FS_DownloadContext *dc)
Determine if the given download (options and meta data) should cause use to try to do a recursive dow...
Definition: fs_download.c:38
static void trigger_recursive_download(void *cls, const char *filename, const struct GNUNET_FS_Uri *uri, const struct GNUNET_FS_MetaData *meta, size_t length, const void *data)
We found an entry in a directory.
Definition: fs_download.c:851
static uint64_t compute_disk_offset(uint64_t fsize, uint64_t off, unsigned int depth)
We're storing the IBLOCKS after the DBLOCKS on disk (so that we only have to truncate the file once w...
Definition: fs_download.c:68
static void schedule_block_download(struct GNUNET_FS_DownloadContext *dc, struct DownloadRequest *dr)
Schedule the download of the specified block in the tree.
Definition: fs_download.c:778
size_t GNUNET_FS_tree_calculate_block_size(uint64_t fsize, uint64_t offset, unsigned int depth)
Compute how many bytes of data should be stored in the specified block.
Definition: fs_tree.c:211
struct GNUNET_HashCode key
The key used in the DHT.
static char * value
Value of the record to add/remove.
static struct GNUNET_DISK_FileHandle * fh
File handle to STDIN, for reading restart/quit commands.
ssize_t GNUNET_CRYPTO_symmetric_decrypt(const void *block, size_t size, const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, void *result)
Decrypt a given block using a symmetric sessionkey.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition: disk.c:1234
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: disk.c:685
off_t GNUNET_DISK_file_seek(const struct GNUNET_DISK_FileHandle *h, off_t offset, enum GNUNET_DISK_Seek whence)
Move the read/write pointer in a file.
Definition: disk.c:205
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1305
@ GNUNET_DISK_OPEN_CREATE
Create file if it doesn't exist.
@ GNUNET_DISK_OPEN_READWRITE
Open the file for both reading and writing.
@ GNUNET_DISK_PERM_USER_READ
Owner can read.
@ GNUNET_DISK_PERM_GROUP_READ
Group can read.
@ GNUNET_DISK_PERM_USER_WRITE
Owner can write.
@ GNUNET_DISK_PERM_OTHER_READ
Everybody can read.
@ GNUNET_DISK_SEEK_SET
Seek an absolute position (from the start of the file).
int GNUNET_FS_directory_list_contents(size_t size, const void *data, uint64_t offset, GNUNET_FS_DirectoryEntryProcessor dep, void *dep_cls)
Iterate over all entries in a directory.
Definition: fs_directory.c:182
@ GNUNET_FS_DOWNLOAD_NO_TEMPORARIES
Do not append temporary data to the target file (for the IBlocks).
@ GNUNET_FS_STATUS_DOWNLOAD_ERROR
Notification that this download encountered an error.
@ GNUNET_FS_STATUS_DOWNLOAD_PROGRESS
Notification about progress with this download.
void GNUNET_CRYPTO_hash_to_aes_key(const struct GNUNET_HashCode *hc, struct GNUNET_CRYPTO_SymmetricSessionKey *skey, struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
Convert a hashcode into a key.
Definition: crypto_hash.c:151
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
#define GNUNET_log(kind,...)
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:54
@ GNUNET_OK
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_DEBUG
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:683
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
struct GNUNET_HashCode key
Hash of the original content, used for encryption.
Definition: fs.h:59
Information about an active download request.
Definition: fs_api.h:1676
struct DownloadRequest ** children
Array (!) of child-requests, or NULL for the bottom of the tree.
Definition: fs_api.h:1685
unsigned int chk_idx
Offset of the CHK for this block in the parent block.
Definition: fs_api.h:1713
unsigned int num_children
Number of entries in children array.
Definition: fs_api.h:1703
uint64_t offset
Offset of the corresponding block.
Definition: fs_api.h:1698
enum BlockRequestState state
State in the FSM.
Definition: fs_api.h:1718
unsigned int depth
Depth of the corresponding block in the tree.
Definition: fs_api.h:1708
struct DownloadRequest * parent
Parent in the CHK-tree.
Definition: fs_api.h:1680
struct ContentHashKey chk
CHK for the request for this block (set during reconstruction to what we have on disk,...
Definition: fs_api.h:1691
uint64_t file_length
Total size of the file in bytes.
Definition: fs_api.h:99
Handle used to access files (and pipes).
Context for controlling a download.
Definition: fs_api.h:1744
unsigned int treedepth
The depth of the file-tree.
Definition: fs_api.h:1918
int issue_requests
Are we ready to issue requests (reconstructions are finished)?
Definition: fs_api.h:1935
uint64_t offset
What is the first offset that we're interested in?
Definition: fs_api.h:1878
struct GNUNET_FS_QueueEntry * job_queue
Our entry in the job queue.
Definition: fs_api.h:1834
char * emsg
Error message, NULL if we're doing OK.
Definition: fs_api.h:1810
struct GNUNET_CONTAINER_MultiHashMap * active
Map of active requests (those waiting for a response).
Definition: fs_api.h:1851
char * temp_filename
Where are we writing the data temporarily (name of the file, can be NULL!); used if we do not have a ...
Definition: fs_api.h:1829
struct DownloadRequest * top_request
Top-level download request.
Definition: fs_api.h:1856
Argument given to the progress callback with information about what is going on.
union GNUNET_FS_Uri::@13 data
struct FileIdentifier chk
Information needed to retrieve a file (content-hash-key plus file size).
Definition: fs_api.h:212
uint64_t abs_value_us
The actual value.
Closure for iterator processing results.
Definition: fs_download.c:136
uint32_t respect_offered
how much respect did we offer to get this reply?
Definition: fs_download.c:175
size_t size
Number of bytes in data.
Definition: fs_download.c:160
int do_store
Flag to indicate if this block should be stored on disk.
Definition: fs_download.c:170
struct GNUNET_FS_DownloadContext * dc
Our download context.
Definition: fs_download.c:150
struct GNUNET_TIME_Absolute last_transmission
When did we last transmit the request?
Definition: fs_download.c:155
const void * data
Data found in P2P network.
Definition: fs_download.c:145
uint32_t num_transmissions
how often did we transmit the query?
Definition: fs_download.c:180
struct GNUNET_HashCode query
Hash of data.
Definition: fs_download.c:140

References _, GNUNET_TIME_Absolute::abs_value_us, GNUNET_FS_DownloadContext::active, BRS_CHK_SET, BRS_DOWNLOAD_DOWN, BRS_DOWNLOAD_UP, BRS_ERROR, BRS_INIT, BRS_RECONSTRUCT_DOWN, BRS_RECONSTRUCT_META_UP, BRS_RECONSTRUCT_UP, check_completed(), DownloadRequest::children, GNUNET_FS_Uri::chk, DownloadRequest::chk, DownloadRequest::chk_idx, GNUNET_FS_DownloadContext::completed, compute_disk_offset(), GNUNET_FS_Uri::data, ProcessResultClosure::data, ProcessResultClosure::dc, dc, DownloadRequest::depth, ProcessResultClosure::do_store, GNUNET_FS_DownloadContext::emsg, fh, FileIdentifier::file_length, GNUNET_FS_DownloadContext::filename, GNUNET_asprintf(), GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_multihashmap_remove(), GNUNET_CRYPTO_hash_to_aes_key(), GNUNET_CRYPTO_symmetric_decrypt(), GNUNET_DISK_file_close(), GNUNET_DISK_file_open(), GNUNET_DISK_file_seek(), GNUNET_DISK_file_write(), GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_OPEN_READWRITE, GNUNET_DISK_PERM_GROUP_READ, GNUNET_DISK_PERM_OTHER_READ, GNUNET_DISK_PERM_USER_READ, GNUNET_DISK_PERM_USER_WRITE, GNUNET_DISK_SEEK_SET, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_FS_dequeue_(), GNUNET_FS_directory_list_contents(), GNUNET_FS_download_make_status_(), GNUNET_FS_DOWNLOAD_NO_TEMPORARIES, GNUNET_FS_download_sync_(), GNUNET_FS_free_download_request_(), GNUNET_FS_STATUS_DOWNLOAD_ERROR, GNUNET_FS_STATUS_DOWNLOAD_PROGRESS, GNUNET_FS_tree_calculate_block_size(), GNUNET_h2s(), GNUNET_log, GNUNET_log_strerror_file, GNUNET_MQ_destroy(), GNUNET_NO, GNUNET_ntohll(), GNUNET_OK, GNUNET_strdup, GNUNET_TIME_absolute_get_duration(), GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_TIME_UNIT_ZERO, GNUNET_YES, is_recursive_download(), GNUNET_FS_DownloadContext::issue_requests, GNUNET_FS_DownloadContext::job_queue, key, ContentHashKey::key, ProcessResultClosure::last_transmission, GNUNET_FS_DownloadContext::length, GNUNET_FS_DownloadContext::mq, DownloadRequest::num_children, ProcessResultClosure::num_transmissions, DownloadRequest::offset, GNUNET_FS_DownloadContext::offset, GNUNET_FS_DownloadContext::options, DownloadRequest::parent, pi, propagate_up(), ProcessResultClosure::query, ProcessResultClosure::respect_offered, schedule_block_download(), ProcessResultClosure::size, size, DownloadRequest::state, GNUNET_FS_DownloadContext::temp_filename, GNUNET_FS_DownloadContext::top_request, GNUNET_FS_DownloadContext::treedepth, trigger_recursive_download(), GNUNET_FS_DownloadContext::uri, and value.

Referenced by encrypt_existing_match(), and handle_put().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ encrypt_existing_match()

static int encrypt_existing_match ( struct GNUNET_FS_DownloadContext dc,
const struct ContentHashKey chk,
struct DownloadRequest dr,
const char *  block,
size_t  len,
int  do_store 
)
static

We've found a matching block without downloading it.

Encrypt it and pass it to our "receive" function as if we had received it from the network.

Parameters
dcdownload in question
chkrequest this relates to
drrequest details
blockplaintext data matching request
lennumber of bytes in block
do_storeshould we still store the block on disk?
Returns
GNUNET_OK on success

Definition at line 213 of file fs_download.c.

219 {
220  struct ProcessResultClosure prc;
221  char enc[len];
224  struct GNUNET_HashCode query;
225 
226  GNUNET_CRYPTO_hash_to_aes_key (&chk->key, &sk, &iv);
227  if (-1 == GNUNET_CRYPTO_symmetric_encrypt (block, len, &sk, &iv, enc))
228  {
229  GNUNET_break (0);
230  return GNUNET_SYSERR;
231  }
232  GNUNET_CRYPTO_hash (enc, len, &query);
233  if (0 != memcmp (&query, &chk->query, sizeof(struct GNUNET_HashCode)))
234  {
235  GNUNET_break_op (0);
236  return GNUNET_SYSERR;
237  }
238  GNUNET_log (
240  "Matching %u byte block for `%s' at offset %llu already present, no need for download!\n",
241  (unsigned int) len,
242  dc->filename,
243  (unsigned long long) dr->offset);
244  /* already got it! */
245  prc.dc = dc;
246  prc.data = enc;
247  prc.size = len;
248  prc.type = (0 == dr->depth) ? GNUNET_BLOCK_TYPE_FS_DBLOCK
250  prc.query = chk->query;
251  prc.do_store = do_store;
252  prc.last_transmission = GNUNET_TIME_UNIT_FOREVER_ABS;
253  process_result_with_request (&prc, &chk->key, dr);
254  return GNUNET_OK;
255 }
@ GNUNET_BLOCK_TYPE_FS_IBLOCK
Inner block in the CHK tree.
@ GNUNET_BLOCK_TYPE_FS_DBLOCK
Data block (leaf) in the CHK tree.
static int process_result_with_request(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator over entries in the pending requests in the 'active' map for the reply that we just got.
Definition: fs_download.c:1009
static OpusEncoder * enc
OPUS encoder.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
ssize_t GNUNET_CRYPTO_symmetric_encrypt(const void *block, size_t size, const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, void *result)
Encrypt a block using a symmetric sessionkey.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
struct GNUNET_HashCode query
Hash of the encrypted content, used for querying.
Definition: fs.h:64
A 512-bit hashcode.

References ProcessResultClosure::data, ProcessResultClosure::dc, dc, DownloadRequest::depth, ProcessResultClosure::do_store, enc, GNUNET_FS_DownloadContext::filename, GNUNET_BLOCK_TYPE_FS_DBLOCK, GNUNET_BLOCK_TYPE_FS_IBLOCK, GNUNET_break, GNUNET_break_op, GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_hash_to_aes_key(), GNUNET_CRYPTO_symmetric_encrypt(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_OK, GNUNET_SYSERR, GNUNET_TIME_UNIT_FOREVER_ABS, ContentHashKey::key, ProcessResultClosure::last_transmission, len, DownloadRequest::offset, process_result_with_request(), ContentHashKey::query, ProcessResultClosure::query, ProcessResultClosure::size, and ProcessResultClosure::type.

Referenced by try_top_down_reconstruction().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_reconnect()

static void try_reconnect ( struct GNUNET_FS_DownloadContext dc)
static

We've lost our connection with the FS service.

Re-establish it and re-transmit all of our pending requests.

Parameters
dcdownload context that is having trouble

Definition at line 1398 of file fs_download.c.

1399 {
1400  if (NULL != dc->mq)
1401  {
1403  "Moving all requests back to pending list\n");
1404  GNUNET_MQ_destroy (dc->mq);
1405  dc->mq = NULL;
1406  }
1407  if (0 == dc->reconnect_backoff.rel_value_us)
1409  else
1411 
1413  "Will try to reconnect in %s\n",
1415  GNUNET_YES));
1416  GNUNET_break (NULL != dc->job_queue);
1417  dc->task =
1419 }
static void do_reconnect(void *cls)
Reconnect to the FS service and transmit our queries NOW.
Definition: fs_download.c:1362
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1241
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:569
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
struct GNUNET_SCHEDULER_Task * task
ID of a task that is using this struct and that must be cancelled when the download is being stopped ...
Definition: fs_api.h:1872
struct GNUNET_TIME_Relative reconnect_backoff
How long to wait before we try to reconnect to FS service?
Definition: fs_api.h:1908
uint64_t rel_value_us
The actual value.

References dc, do_reconnect(), GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MQ_destroy(), GNUNET_SCHEDULER_add_delayed(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_STD_BACKOFF, GNUNET_TIME_UNIT_MILLISECONDS, GNUNET_YES, GNUNET_FS_DownloadContext::job_queue, GNUNET_FS_DownloadContext::mq, GNUNET_FS_DownloadContext::reconnect_backoff, GNUNET_TIME_Relative::rel_value_us, and GNUNET_FS_DownloadContext::task.

Referenced by do_reconnect(), and download_mq_error_handler().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ trigger_recursive_download()

static void trigger_recursive_download ( void *  cls,
const char *  filename,
const struct GNUNET_FS_Uri uri,
const struct GNUNET_FS_MetaData meta,
size_t  length,
const void *  data 
)
static

We found an entry in a directory.

Check if the respective child already exists and if not create the respective child download.

Parameters
clsthe parent download
filenamename of the file in the directory
uriURI of the file (CHK or LOC)
metameta data of the file
lengthnumber of bytes in data
datacontents of the file (or NULL if they were not inlined)

Definition at line 851 of file fs_download.c.

857 {
858  struct GNUNET_FS_DownloadContext *dc = cls;
859  struct GNUNET_FS_DownloadContext *cpos;
860  char *temp_name;
861  char *fn;
862  char *us;
863  char *ext;
864  char *dn;
865  char *pos;
866  char *full_name;
867  char *sfn;
868 
869  if (NULL == uri)
870  return; /* entry for the directory itself */
871  cpos = dc->child_head;
872  while (NULL != cpos)
873  {
874  if ((GNUNET_FS_uri_test_equal (uri, cpos->uri)) ||
875  ((NULL != filename) && (0 == strcmp (cpos->filename, filename))))
876  break;
877  cpos = cpos->next;
878  }
879  if (NULL != cpos)
880  return; /* already exists */
881  fn = NULL;
882  if (NULL == filename)
883  {
885  if (NULL == fn)
886  {
888  fn = GNUNET_strdup (&us[strlen (GNUNET_FS_URI_CHK_PREFIX)]);
889  GNUNET_free (us);
890  }
891  else if ('.' == fn[0])
892  {
893  ext = fn;
895  GNUNET_asprintf (&fn,
896  "%s%s",
897  &us[strlen (GNUNET_FS_URI_CHK_PREFIX)],
898  ext);
899  GNUNET_free (ext);
900  GNUNET_free (us);
901  }
902  /* change '\' to '/' (this should have happened
903  * during insertion, but malicious peers may
904  * not have done this) */
905  while (NULL != (pos = strstr (fn, "\\")))
906  *pos = '/';
907  /* remove '../' everywhere (again, well-behaved
908  * peers don't do this, but don't trust that
909  * we did not get something nasty) */
910  while (NULL != (pos = strstr (fn, "../")))
911  {
912  pos[0] = '_';
913  pos[1] = '_';
914  pos[2] = '_';
915  }
916  filename = fn;
917  }
918  if (NULL == dc->filename)
919  {
920  full_name = NULL;
921  }
922  else
923  {
924  dn = GNUNET_strdup (dc->filename);
925  GNUNET_break (
926  (strlen (dn) >= strlen (GNUNET_FS_DIRECTORY_EXT)) &&
927  (NULL != strstr (dn + strlen (dn) - strlen (GNUNET_FS_DIRECTORY_EXT),
929  sfn = GNUNET_strdup (filename);
930  while ((strlen (sfn) > 0) && ('/' == filename[strlen (sfn) - 1]))
931  sfn[strlen (sfn) - 1] = '\0';
932  if ((strlen (dn) >= strlen (GNUNET_FS_DIRECTORY_EXT)) &&
933  (NULL != strstr (dn + strlen (dn) - strlen (GNUNET_FS_DIRECTORY_EXT),
935  dn[strlen (dn) - strlen (GNUNET_FS_DIRECTORY_EXT)] = '\0';
937  ((strlen (filename) < strlen (GNUNET_FS_DIRECTORY_EXT)) ||
938  (NULL == strstr (filename + strlen (filename)
939  - strlen (GNUNET_FS_DIRECTORY_EXT),
941  {
942  GNUNET_asprintf (&full_name,
943  "%s%s%s%s",
944  dn,
946  sfn,
948  }
949  else
950  {
951  GNUNET_asprintf (&full_name, "%s%s%s", dn, DIR_SEPARATOR_STR, sfn);
952  }
953  GNUNET_free (sfn);
954  GNUNET_free (dn);
955  }
956  if ((NULL != full_name) &&
958  {
960  _ (
961  "Failed to create directory for recursive download of `%s'\n"),
962  full_name);
963  GNUNET_free (full_name);
964  GNUNET_free (fn);
965  return;
966  }
967 
968  temp_name = NULL;
970  "Triggering recursive download of size %llu with %u bytes MD\n",
971  (unsigned long long) GNUNET_FS_uri_chk_get_file_size (uri),
973  meta));
975  uri,
976  meta,
977  full_name,
978  temp_name,
979  0,
981  dc->anonymity,
982  dc->options,
983  NULL,
984  dc);
985  GNUNET_free (full_name);
986  GNUNET_free (temp_name);
987  GNUNET_free (fn);
988 }
#define GNUNET_FS_URI_CHK_PREFIX
Definition: fs_download.c:837
static char * filename
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
static struct GNUNET_FS_MetaData * meta
Meta-data provided via command-line option.
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:581
char * GNUNET_FS_meta_data_suggest_filename(const struct GNUNET_FS_MetaData *md)
Suggest a filename based on given metadata.
Definition: fs_misc.c:39
uint64_t GNUNET_FS_uri_chk_get_file_size(const struct GNUNET_FS_Uri *uri)
What is the size of the file that this URI refers to?
Definition: fs_uri.c:1360
int GNUNET_FS_uri_test_equal(const struct GNUNET_FS_Uri *u1, const struct GNUNET_FS_Uri *u2)
Test if two URIs are equal.
Definition: fs_uri.c:1201
char * GNUNET_FS_uri_to_string(const struct GNUNET_FS_Uri *uri)
Convert a URI to a UTF-8 String.
Definition: fs_uri.c:2017
struct GNUNET_FS_DownloadContext * GNUNET_FS_download_start(struct GNUNET_FS_Handle *h, const struct GNUNET_FS_Uri *uri, const struct GNUNET_FS_MetaData *meta, const char *filename, const char *tempname, uint64_t offset, uint64_t length, uint32_t anonymity, enum GNUNET_FS_DownloadOptions options, void *cctx, struct GNUNET_FS_DownloadContext *parent)
Download parts of a file.
Definition: fs_download.c:2100
@ GNUNET_ERROR_TYPE_ERROR
#define GNUNET_free(ptr)
Wrapper around free.
ssize_t GNUNET_FS_meta_data_get_serialized_size(const struct GNUNET_FS_MetaData *md)
Get the size of the full meta-data in serialized form.
Definition: meta_data.c:862
#define DIR_SEPARATOR_STR
Definition: platform.h:165
struct GNUNET_FS_DownloadContext * child_head
Head of list of child downloads.
Definition: fs_api.h:1775
struct GNUNET_FS_DownloadContext * next
Next download belonging to the same parent.
Definition: fs_api.h:1790

References _, GNUNET_FS_DownloadContext::anonymity, GNUNET_FS_DownloadContext::child_head, dc, DIR_SEPARATOR_STR, GNUNET_FS_DownloadContext::filename, filename, GNUNET_asprintf(), GNUNET_break, GNUNET_DISK_directory_create_for_file(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_FS_DIRECTORY_EXT, GNUNET_FS_download_start(), GNUNET_FS_meta_data_get_serialized_size(), GNUNET_FS_meta_data_suggest_filename(), GNUNET_FS_meta_data_test_for_directory(), GNUNET_FS_uri_chk_get_file_size(), GNUNET_FS_URI_CHK_PREFIX, GNUNET_FS_uri_test_equal(), GNUNET_FS_uri_to_string(), GNUNET_log, GNUNET_OK, GNUNET_strdup, GNUNET_YES, GNUNET_FS_DownloadContext::h, meta, GNUNET_FS_DownloadContext::next, GNUNET_FS_DownloadContext::options, GNUNET_FS_DownloadContext::uri, and uri.

Referenced by full_recursive_download(), and process_result_with_request().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ full_recursive_download()

static void full_recursive_download ( struct GNUNET_FS_DownloadContext dc)
static

We're done downloading a directory.

Open the file and trigger all of the (remaining) child downloads.

Parameters
dccontext of download that just completed

Definition at line 296 of file fs_download.c.

297 {
298  size_t size;
299  uint64_t size64;
300  void *data;
301  struct GNUNET_DISK_FileHandle *h;
302  struct GNUNET_DISK_MapHandle *m;
303 
305  size = (size_t) size64;
306  if (size64 != (uint64_t) size)
307  {
308  GNUNET_log (
310  _ (
311  "Recursive downloads of directories larger than 4 GB are not supported on 32-bit systems\n"));
312  return;
313  }
314  if (NULL != dc->filename)
315  {
319  }
320  else
321  {
322  GNUNET_assert (NULL != dc->temp_filename);
326  }
327  if (NULL == h)
328  return; /* oops */
330  if (NULL == data)
331  {
333  _ ("Directory too large for system address space\n"));
334  }
335  else
336  {
337  if (GNUNET_OK !=
339  data,
340  0,
342  dc))
343  {
344  GNUNET_log (
346  _ (
347  "Failed to access full directory contents of `%s' for recursive download\n"),
348  dc->filename);
349  }
351  }
353  if (NULL == dc->filename)
354  {
355  if (0 != unlink (dc->temp_filename))
357  "unlink",
358  dc->temp_filename);
360  dc->temp_filename = NULL;
361  }
362 }
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
uint32_t data
The data value.
void * GNUNET_DISK_file_map(const struct GNUNET_DISK_FileHandle *h, struct GNUNET_DISK_MapHandle **m, enum GNUNET_DISK_MapType access, size_t len)
Map a file into memory.
Definition: disk.c:1377
enum GNUNET_GenericReturnValue GNUNET_DISK_file_unmap(struct GNUNET_DISK_MapHandle *h)
Unmap a file.
Definition: disk.c:1408
@ GNUNET_DISK_OPEN_READ
Open the file for reading.
@ GNUNET_DISK_PERM_NONE
Nobody is allowed to do anything to the file.
@ GNUNET_DISK_MAP_TYPE_READ
Read-only memory map.
Handle for a memory-mapping operation.
Definition: disk.c:1358

References _, data, dc, GNUNET_FS_DownloadContext::filename, GNUNET_assert, GNUNET_DISK_file_close(), GNUNET_DISK_file_map(), GNUNET_DISK_file_open(), GNUNET_DISK_file_unmap(), GNUNET_DISK_MAP_TYPE_READ, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_FS_directory_list_contents(), GNUNET_FS_uri_chk_get_file_size(), GNUNET_log, GNUNET_log_strerror_file, GNUNET_OK, h, m, size, GNUNET_FS_DownloadContext::temp_filename, trigger_recursive_download(), and GNUNET_FS_DownloadContext::uri.

Referenced by check_completed().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_completed()

static void check_completed ( struct GNUNET_FS_DownloadContext dc)
static

Check if all child-downloads have completed (or trigger them if necessary) and once we're completely done, signal completion (and possibly recurse to parent).

This function MUST be called when the download of a file itself is done or when the download of a file is done and then later a direct child download has completed (and hence this download may complete itself).

Parameters
dcdownload to check for completion of children

Definition at line 376 of file fs_download.c.

377 {
378  struct GNUNET_FS_ProgressInfo pi;
379  struct GNUNET_FS_DownloadContext *pos;
380 
381  /* first, check if we need to download children */
384  /* then, check if children are done already */
385  for (pos = dc->child_head; NULL != pos; pos = pos->next)
386  {
387  if ((NULL == pos->emsg) && (pos->completed < pos->length))
388  return; /* not done yet */
389  if ((NULL != pos->child_head) && (pos->has_finished != GNUNET_YES))
390  return; /* not transitively done yet */
391  }
392  /* All of our children are done, so mark this download done */
394  if (NULL != dc->job_queue)
395  {
397  dc->job_queue = NULL;
398  }
399  if (NULL != dc->task)
400  {
402  dc->task = NULL;
403  }
404  if (NULL != dc->rfh)
405  {
407  dc->rfh = NULL;
408  }
410 
411  /* signal completion */
414 
415  /* let parent know */
416  if (NULL != dc->parent)
418 }
static void full_recursive_download(struct GNUNET_FS_DownloadContext *dc)
We're done downloading a directory.
Definition: fs_download.c:296
@ GNUNET_FS_STATUS_DOWNLOAD_COMPLETED
Notification that this download completed.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:944
int has_finished
Flag set upon transitive completion (includes child downloads).
Definition: fs_api.h:1930
struct GNUNET_DISK_FileHandle * rfh
File handle for reading data from an existing file (to pass to tree encoder).
Definition: fs_api.h:1845

References GNUNET_FS_DownloadContext::child_head, GNUNET_FS_DownloadContext::completed, dc, GNUNET_FS_DownloadContext::emsg, full_recursive_download(), GNUNET_break, GNUNET_DISK_file_close(), GNUNET_FS_dequeue_(), GNUNET_FS_download_make_status_(), GNUNET_FS_download_sync_(), GNUNET_FS_STATUS_DOWNLOAD_COMPLETED, GNUNET_OK, GNUNET_SCHEDULER_cancel(), GNUNET_YES, GNUNET_FS_DownloadContext::has_finished, is_recursive_download(), GNUNET_FS_DownloadContext::job_queue, GNUNET_FS_DownloadContext::length, GNUNET_FS_DownloadContext::next, GNUNET_FS_DownloadContext::parent, pi, GNUNET_FS_DownloadContext::rfh, and GNUNET_FS_DownloadContext::task.

Referenced by GNUNET_FS_download_start_task_(), process_result_with_request(), reconstruct_cb(), and try_match_block().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_match_block()

static void try_match_block ( struct GNUNET_FS_DownloadContext dc,
struct DownloadRequest dr,
const char *  data,
size_t  data_len 
)
static

We got a block of plaintext data (from the meta data).

Try it for upward reconstruction of the data. On success, the top-level block will move to state BRS_DOWNLOAD_UP.

Parameters
dccontext for the download
drdownload request to match against
dataplaintext data, starting from the beginning of the file
data_lennumber of bytes in data

Definition at line 432 of file fs_download.c.

436 {
437  struct GNUNET_FS_ProgressInfo pi;
438  unsigned int i;
439  char enc[DBLOCK_SIZE];
440  struct ContentHashKey chks[CHK_PER_INODE];
441  struct ContentHashKey in_chk;
444  size_t dlen;
445  struct DownloadRequest *drc;
446  struct GNUNET_DISK_FileHandle *fh;
447  int complete;
448  const char *fn;
449  const char *odata;
450  size_t odata_len;
451 
452  odata = data;
453  odata_len = data_len;
454  if (BRS_DOWNLOAD_UP == dr->state)
455  return;
456  if (dr->depth > 0)
457  {
458  if ((dc->offset > 0) ||
460  {
461  /* NOTE: this test is not tight, but should suffice; the issue
462  here is that 'dr->num_children' may inherently only specify a
463  smaller range than what is in the original file;
464  thus, reconstruction of (some) inner blocks will fail.
465  FIXME: we might eventually want to write a tighter test to
466  maximize the circumstances under which we do succeed with
467  IBlock reconstruction. (need good tests though). */return;
468  }
469  complete = GNUNET_YES;
470  for (i = 0; i < dr->num_children; i++)
471  {
472  drc = dr->children[i];
473  try_match_block (dc, drc, data, data_len);
474  if (drc->state != BRS_RECONSTRUCT_META_UP)
475  complete = GNUNET_NO;
476  else
477  chks[i] = drc->chk;
478  }
479  if (GNUNET_YES != complete)
480  return;
481  data = (const char *) chks;
482  dlen = dr->num_children * sizeof(struct ContentHashKey);
483  }
484  else
485  {
486  if (dr->offset > data_len)
487  return; /* oops */
488  dlen = GNUNET_MIN (data_len - dr->offset, DBLOCK_SIZE);
489  }
490  GNUNET_CRYPTO_hash (&data[dr->offset], dlen, &in_chk.key);
491  GNUNET_CRYPTO_hash_to_aes_key (&in_chk.key, &sk, &iv);
492  if (-1 ==
493  GNUNET_CRYPTO_symmetric_encrypt (&data[dr->offset], dlen, &sk, &iv, enc))
494  {
495  GNUNET_break (0);
496  return;
497  }
498  GNUNET_CRYPTO_hash (enc, dlen, &in_chk.query);
499  switch (dr->state)
500  {
501  case BRS_INIT:
502  dr->chk = in_chk;
504  break;
505 
506  case BRS_CHK_SET:
507  if (0 != memcmp (&in_chk, &dr->chk, sizeof(struct ContentHashKey)))
508  {
509  /* other peer provided bogus meta data */
510  GNUNET_break_op (0);
511  break;
512  }
513  /* write block to disk */
514  fn = (NULL != dc->filename) ? dc->filename : dc->temp_filename;
515  if (NULL != fn)
516  {
525  if (NULL == fh)
526  {
529  _ ("Failed to open file `%s' for writing"),
530  fn);
532  dr->state = BRS_ERROR;
534  pi.value.download.specifics.error.message = dc->emsg;
536  return;
537  }
538  if (data_len != GNUNET_DISK_file_write (fh, odata, odata_len))
539  {
542  _ ("Failed to open file `%s' for writing"),
543  fn);
545  dr->state = BRS_ERROR;
547  pi.value.download.specifics.error.message = dc->emsg;
549  return;
550  }
552  }
553  /* signal success */
554  dr->state = BRS_DOWNLOAD_UP;
555  dc->completed = dc->length;
558  pi.value.download.specifics.progress.data = data;
559  pi.value.download.specifics.progress.offset = 0;
560  pi.value.download.specifics.progress.data_len = dlen;
561  pi.value.download.specifics.progress.depth = 0;
562  pi.value.download.specifics.progress.respect_offered = 0;
563  pi.value.download.specifics.progress.block_download_duration =
566  if ((NULL != dc->filename) &&
567  (0 != truncate (dc->filename,
570  "truncate",
571  dc->filename);
573  break;
574 
575  default:
576  /* how did we get here? */
577  GNUNET_break (0);
578  break;
579  }
580 }
static void try_match_block(struct GNUNET_FS_DownloadContext *dc, struct DownloadRequest *dr, const char *data, size_t data_len)
We got a block of plaintext data (from the meta data).
Definition: fs_download.c:432
@ GNUNET_DISK_OPEN_TRUNCATE
Truncate file if it exists.
#define GNUNET_MIN(a, b)

References _, BRS_CHK_SET, BRS_DOWNLOAD_UP, BRS_ERROR, BRS_INIT, BRS_RECONSTRUCT_META_UP, check_completed(), DownloadRequest::children, GNUNET_FS_Uri::chk, DownloadRequest::chk, CHK_PER_INODE, GNUNET_FS_DownloadContext::completed, GNUNET_FS_Uri::data, data, DBLOCK_SIZE, dc, DownloadRequest::depth, GNUNET_FS_DownloadContext::emsg, enc, fh, FileIdentifier::file_length, GNUNET_FS_DownloadContext::filename, GNUNET_asprintf(), GNUNET_break, GNUNET_break_op, GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_hash_to_aes_key(), GNUNET_CRYPTO_symmetric_encrypt(), GNUNET_DISK_file_close(), GNUNET_DISK_file_open(), GNUNET_DISK_file_write(), GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_OPEN_READWRITE, GNUNET_DISK_OPEN_TRUNCATE, GNUNET_DISK_PERM_GROUP_READ, GNUNET_DISK_PERM_OTHER_READ, GNUNET_DISK_PERM_USER_READ, GNUNET_DISK_PERM_USER_WRITE, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_FS_download_make_status_(), GNUNET_FS_download_sync_(), GNUNET_FS_STATUS_DOWNLOAD_ERROR, GNUNET_FS_STATUS_DOWNLOAD_PROGRESS, GNUNET_log_strerror_file, GNUNET_MIN, GNUNET_NO, GNUNET_ntohll(), GNUNET_TIME_UNIT_ZERO, GNUNET_YES, ContentHashKey::key, GNUNET_FS_DownloadContext::length, DownloadRequest::num_children, DownloadRequest::offset, GNUNET_FS_DownloadContext::offset, pi, ContentHashKey::query, DownloadRequest::state, GNUNET_FS_DownloadContext::temp_filename, and GNUNET_FS_DownloadContext::uri.

Referenced by match_full_data().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ match_full_data()

static int match_full_data ( void *  cls,
const char *  plugin_name,
enum EXTRACTOR_MetaType  type,
enum EXTRACTOR_MetaFormat  format,
const char *  data_mime_type,
const char *  data,
size_t  data_len 
)
static

Type of a function that libextractor calls for each meta data item found.

If we find full data meta data, call 'try_match_block' on it.

Parameters
clsour 'struct GNUNET_FS_DownloadContext*'
plugin_namename of the plugin that produced this value; special values can be used (e.g. '<zlib>' for zlib being used in the main libextractor library and yielding meta data).
typelibextractor-type describing the meta data
formatbasic format information about data
data_mime_typemime-type of data (not of the original file); can be NULL (if mime-type is not known)
dataactual meta-data found
data_lennumber of bytes in data
Returns
0 to continue extracting, 1 to abort

Definition at line 602 of file fs_download.c.

609 {
610  struct GNUNET_FS_DownloadContext *dc = cls;
611 
612  if (EXTRACTOR_METATYPE_GNUNET_FULL_DATA != type)
613  return 0;
615  "Found %u bytes of FD!\n",
616  (unsigned int) data_len);
617  if (GNUNET_FS_uri_chk_get_file_size (dc->uri) != data_len)
618  {
619  GNUNET_break_op (0);
620  return 1; /* bogus meta data */
621  }
622  try_match_block (dc, dc->top_request, data, data_len);
623  return 1;
624 }
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model

References data, dc, GNUNET_break_op, GNUNET_ERROR_TYPE_DEBUG, GNUNET_FS_uri_chk_get_file_size(), GNUNET_log, GNUNET_FS_DownloadContext::top_request, try_match_block(), type, and GNUNET_FS_DownloadContext::uri.

Referenced by GNUNET_FS_download_start_task_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ propagate_up()

static void propagate_up ( struct DownloadRequest dr)
static

Set the state of the given download request to BRS_DOWNLOAD_UP and propagate it up the tree.

Parameters
drdownload request that is done

Definition at line 634 of file fs_download.c.

635 {
636  unsigned int i;
637 
638  do
639  {
640  dr->state = BRS_DOWNLOAD_UP;
641  dr = dr->parent;
642  if (NULL == dr)
643  break;
644  for (i = 0; i < dr->num_children; i++)
645  if (dr->children[i]->state != BRS_DOWNLOAD_UP)
646  break;
647  }
648  while (i == dr->num_children);
649 }

References BRS_DOWNLOAD_UP, DownloadRequest::children, DownloadRequest::num_children, DownloadRequest::parent, and DownloadRequest::state.

Referenced by process_result_with_request(), and try_top_down_reconstruction().

Here is the caller graph for this function:

◆ try_top_down_reconstruction()

static void try_top_down_reconstruction ( struct GNUNET_FS_DownloadContext dc,
struct DownloadRequest dr 
)
static

Try top-down reconstruction.

Before, the given request node must have the state BRS_CHK_SET. Afterwards, more nodes may have that state or advanced to BRS_DOWNLOAD_DOWN or even BRS_DOWNLOAD_UP. It is also possible to get BRS_ERROR on the top level.

Parameters
dcoverall download this block belongs to
drblock to reconstruct

Definition at line 663 of file fs_download.c.

665 {
666  uint64_t off;
667  char block[DBLOCK_SIZE];
668  struct GNUNET_HashCode key;
669  uint64_t total;
670  size_t len;
671  unsigned int i;
672  struct DownloadRequest *drc;
673  uint64_t child_block_size;
674  const struct ContentHashKey *chks;
675  int up_done;
676 
677  GNUNET_assert (NULL != dc->rfh);
680  GNUNET_assert (dr->depth < dc->treedepth);
683  off = compute_disk_offset (total, dr->offset, dr->depth);
684  if (dc->old_file_size < off + len)
685  return; /* failure */
686  if (off != GNUNET_DISK_file_seek (dc->rfh, off, GNUNET_DISK_SEEK_SET))
687  {
689  return; /* failure */
690  }
691  if (len != GNUNET_DISK_file_read (dc->rfh, block, len))
692  {
694  return; /* failure */
695  }
696  GNUNET_CRYPTO_hash (block, len, &key);
697  if (0 != memcmp (&key, &dr->chk.key, sizeof(struct GNUNET_HashCode)))
698  return; /* mismatch */
699  if (GNUNET_OK !=
700  encrypt_existing_match (dc, &dr->chk, dr, block, len, GNUNET_NO))
701  {
702  /* hash matches but encrypted block does not, really bad */
703  dr->state = BRS_ERROR;
704  /* propagate up */
705  while (NULL != dr->parent)
706  {
707  dr = dr->parent;
708  dr->state = BRS_ERROR;
709  }
710  return;
711  }
712  /* block matches */
713  dr->state = BRS_DOWNLOAD_DOWN;
714 
715  /* set CHKs for children */
716  up_done = GNUNET_YES;
717  chks = (const struct ContentHashKey *) block;
718  for (i = 0; i < dr->num_children; i++)
719  {
720  drc = dr->children[i];
721  GNUNET_assert (drc->offset >= dr->offset);
722  child_block_size = GNUNET_FS_tree_compute_tree_size (drc->depth);
723  GNUNET_assert (0 == (drc->offset - dr->offset) % child_block_size);
724  if (BRS_INIT == drc->state)
725  {
726  drc->state = BRS_CHK_SET;
727  drc->chk = chks[drc->chk_idx];
729  }
730  if (BRS_DOWNLOAD_UP != drc->state)
731  up_done = GNUNET_NO; /* children not all done */
732  }
733  if (GNUNET_YES == up_done)
734  propagate_up (dr); /* children all done (or no children...) */
735 }
static void try_top_down_reconstruction(struct GNUNET_FS_DownloadContext *dc, struct DownloadRequest *dr)
Try top-down reconstruction.
Definition: fs_download.c:663
static int encrypt_existing_match(struct GNUNET_FS_DownloadContext *dc, const struct ContentHashKey *chk, struct DownloadRequest *dr, const char *block, size_t len, int do_store)
We've found a matching block without downloading it.
Definition: fs_download.c:213
uint64_t GNUNET_FS_tree_compute_tree_size(unsigned int depth)
Calculate how many bytes of payload a block tree of the given depth MAY correspond to at most (this f...
Definition: fs_tree.c:156
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:621
uint64_t old_file_size
What was the size of the file on disk that we're downloading before we started? Used to detect if the...
Definition: fs_api.h:1898

References BRS_CHK_SET, BRS_DOWNLOAD_DOWN, BRS_DOWNLOAD_UP, BRS_ERROR, BRS_INIT, DownloadRequest::children, DownloadRequest::chk, DownloadRequest::chk_idx, compute_disk_offset(), DBLOCK_SIZE, dc, DownloadRequest::depth, encrypt_existing_match(), GNUNET_FS_DownloadContext::filename, GNUNET_assert, GNUNET_CRYPTO_hash(), GNUNET_DISK_file_read(), GNUNET_DISK_file_seek(), GNUNET_DISK_SEEK_SET, GNUNET_ERROR_TYPE_WARNING, GNUNET_FS_tree_calculate_block_size(), GNUNET_FS_tree_compute_tree_size(), GNUNET_FS_uri_chk_get_file_size(), GNUNET_log_strerror_file, GNUNET_NO, GNUNET_OK, GNUNET_YES, key, ContentHashKey::key, len, DownloadRequest::num_children, DownloadRequest::offset, GNUNET_FS_DownloadContext::old_file_size, DownloadRequest::parent, propagate_up(), GNUNET_FS_DownloadContext::rfh, DownloadRequest::state, GNUNET_FS_DownloadContext::treedepth, and GNUNET_FS_DownloadContext::uri.

Referenced by GNUNET_FS_download_start_task_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ retry_entry()

static int retry_entry ( void *  cls,
const struct GNUNET_HashCode key,
void *  entry 
)
static

Add entries to the message queue.

Parameters
clsour download context
keyunused
entryentry of type struct DownloadRequest
Returns
GNUNET_OK

Definition at line 747 of file fs_download.c.

748 {
749  struct GNUNET_FS_DownloadContext *dc = cls;
750  struct DownloadRequest *dr = entry;
751  struct SearchMessage *sm;
752  struct GNUNET_MQ_Envelope *env;
753 
757  else
759  if (0 == dr->depth)
760  sm->type = htonl (GNUNET_BLOCK_TYPE_FS_DBLOCK);
761  else
762  sm->type = htonl (GNUNET_BLOCK_TYPE_FS_IBLOCK);
763  sm->anonymity_level = htonl (dc->anonymity);
764  sm->target = dc->target;
765  sm->query = dr->chk.query;
766  GNUNET_MQ_send (dc->mq, env);
767  return GNUNET_OK;
768 }
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
@ GNUNET_FS_SEARCH_OPTION_LOOPBACK_ONLY
Only search the local host, do not search remote systems (no P2P)
@ GNUNET_FS_SEARCH_OPTION_NONE
No options (use defaults for everything).
@ GNUNET_FS_DOWNLOAD_OPTION_LOOPBACK_ONLY
Only download from the local host, do not access remote systems (no P2P)
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:304
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:77
#define GNUNET_MESSAGE_TYPE_FS_START_SEARCH
Client asks FS service to start a (keyword) search.
struct GNUNET_PeerIdentity target
Identity of the peer having the content, or all-zeros if we don't know of such a peer.
Definition: fs_api.h:1862
Message sent from a GNUnet (fs) search activity to the gnunet-service-fs to start a search.
Definition: fs.h:270
struct GNUNET_PeerIdentity target
If the request is for a DBLOCK or IBLOCK, this is the identity of the peer that is known to have a re...
Definition: fs.h:307
uint32_t type
Type of the content that we're looking for.
Definition: fs.h:290
struct GNUNET_HashCode query
Hash of the public key for UBLOCKs; Hash of the CHK-encoded block for DBLOCKS and IBLOCKS.
Definition: fs.h:313
uint32_t anonymity_level
Desired anonymity level, big-endian.
Definition: fs.h:295
uint32_t options
Bitmask with options.
Definition: fs.h:285

References GNUNET_FS_DownloadContext::anonymity, SearchMessage::anonymity_level, DownloadRequest::chk, dc, DownloadRequest::depth, env, GNUNET_BLOCK_TYPE_FS_DBLOCK, GNUNET_BLOCK_TYPE_FS_IBLOCK, GNUNET_FS_DOWNLOAD_OPTION_LOOPBACK_ONLY, GNUNET_FS_SEARCH_OPTION_LOOPBACK_ONLY, GNUNET_FS_SEARCH_OPTION_NONE, GNUNET_MESSAGE_TYPE_FS_START_SEARCH, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_OK, GNUNET_FS_DownloadContext::mq, SearchMessage::options, GNUNET_FS_DownloadContext::options, SearchMessage::query, ContentHashKey::query, SearchMessage::target, GNUNET_FS_DownloadContext::target, and SearchMessage::type.

Referenced by do_reconnect(), oprelease_overlay_configure_topology(), overlay_link_completed(), and schedule_block_download().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ schedule_block_download()

static void schedule_block_download ( struct GNUNET_FS_DownloadContext dc,
struct DownloadRequest dr 
)
static

Schedule the download of the specified block in the tree.

Parameters
dcoverall download this block belongs to
drrequest to schedule

Definition at line 778 of file fs_download.c.

780 {
781  unsigned int i;
782 
783  switch (dr->state)
784  {
785  case BRS_INIT:
786  GNUNET_assert (0);
787  break;
788 
790  GNUNET_assert (0);
791  break;
792 
794  GNUNET_assert (0);
795  break;
796 
797  case BRS_RECONSTRUCT_UP:
798  GNUNET_assert (0);
799  break;
800 
801  case BRS_CHK_SET:
802  /* normal case, start download */
803  break;
804 
805  case BRS_DOWNLOAD_DOWN:
806  for (i = 0; i < dr->num_children; i++)
808  return;
809 
810  case BRS_DOWNLOAD_UP:
811  /* We're done! */
812  return;
813 
814  case BRS_ERROR:
815  GNUNET_break (0);
816  return;
817  }
819  "Scheduling download at offset %llu and depth %u for `%s'\n",
820  (unsigned long long) dr->offset,
821  dr->depth,
822  GNUNET_h2s (&dr->chk.query));
824  &dr->chk.query,
825  dr))
826  return; /* already active */
828  &dr->chk.query,
829  dr,
831  if (NULL == dc->mq)
832  return; /* download not active */
833  retry_entry (dc, &dr->chk.query, dr);
834 }
static int retry_entry(void *cls, const struct GNUNET_HashCode *key, void *entry)
Add entries to the message queue.
Definition: fs_download.c:747
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_contains_value(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Check if the map contains the given value under the given key.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.

References GNUNET_FS_DownloadContext::active, BRS_CHK_SET, BRS_DOWNLOAD_DOWN, BRS_DOWNLOAD_UP, BRS_ERROR, BRS_INIT, BRS_RECONSTRUCT_DOWN, BRS_RECONSTRUCT_META_UP, BRS_RECONSTRUCT_UP, DownloadRequest::children, DownloadRequest::chk, dc, DownloadRequest::depth, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_multihashmap_contains_value(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE, GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_NO, GNUNET_FS_DownloadContext::mq, DownloadRequest::num_children, DownloadRequest::offset, ContentHashKey::query, retry_entry(), and DownloadRequest::state.

Referenced by GNUNET_FS_download_start_task_(), process_result_with_request(), and reconstruct_cont().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_FS_free_download_request_()

void GNUNET_FS_free_download_request_ ( struct DownloadRequest dr)

(recursively) free download request structure

Parameters
drrequest to free

Definition at line 997 of file fs_download.c.

998 {
999  if (NULL == dr)
1000  return;
1001  for (unsigned int i = 0; i < dr->num_children; i++)
1003  GNUNET_free (dr->children);
1004  GNUNET_free (dr);
1005 }

References DownloadRequest::children, GNUNET_free, GNUNET_FS_free_download_request_(), and DownloadRequest::num_children.

Referenced by free_download_context(), GNUNET_FS_download_signal_suspend_(), GNUNET_FS_free_download_request_(), process_result_with_request(), and read_download_request().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_put()

static int check_put ( void *  cls,
const struct ClientPutMessage cm 
)
static

Type of a function to call when we check the PUT message from the service.

Parameters
clsclosure
msgmessage received

Definition at line 1292 of file fs_download.c.

1293 {
1294  /* any varsize length is OK */
1295  return GNUNET_OK;
1296 }

References GNUNET_OK.

◆ handle_put()

static void handle_put ( void *  cls,
const struct ClientPutMessage cm 
)
static

Type of a function to call when we receive a message from the service.

Parameters
clsclosure
msgmessage received

Definition at line 1307 of file fs_download.c.

1308 {
1309  struct GNUNET_FS_DownloadContext *dc = cls;
1310  uint16_t msize = ntohs (cm->header.size) - sizeof(*cm);
1311  struct ProcessResultClosure prc;
1312 
1313  prc.dc = dc;
1314  prc.data = &cm[1];
1316  prc.size = msize;
1317  prc.type = ntohl (cm->type);
1318  prc.do_store = GNUNET_YES;
1319  prc.respect_offered = ntohl (cm->respect_offered);
1320  prc.num_transmissions = ntohl (cm->num_transmissions);
1321  GNUNET_CRYPTO_hash (prc.data, msize, &prc.query);
1323  "Received result for query `%s' from FS service\n",
1324  GNUNET_h2s (&prc.query));
1326  &prc.query,
1328  &prc);
1329 }
int GNUNET_CONTAINER_multihashmap_get_multiple(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map that match a particular key.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:737
uint32_t respect_offered
How much respect did we offer (in total) before getting an answer (estimate).
Definition: fs.h:388
uint32_t type
Type of the block (in big endian).
Definition: fs.h:365
struct GNUNET_MessageHeader header
Message type will be GNUNET_MESSAGE_TYPE_FS_PUT.
Definition: fs.h:360
struct GNUNET_TIME_AbsoluteNBO last_transmission
When was the last time we've tried to download this block? (FOREVER if unknown/not relevant)
Definition: fs.h:376
uint32_t num_transmissions
How often did we transmit this query before getting an answer (estimate).
Definition: fs.h:382
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.

References GNUNET_FS_DownloadContext::active, ProcessResultClosure::data, ProcessResultClosure::dc, dc, ProcessResultClosure::do_store, GNUNET_CONTAINER_multihashmap_get_multiple(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_TIME_absolute_ntoh(), GNUNET_YES, ClientPutMessage::header, ClientPutMessage::last_transmission, ProcessResultClosure::last_transmission, ClientPutMessage::num_transmissions, ProcessResultClosure::num_transmissions, process_result_with_request(), ProcessResultClosure::query, ClientPutMessage::respect_offered, ProcessResultClosure::respect_offered, ProcessResultClosure::size, GNUNET_MessageHeader::size, ClientPutMessage::type, and ProcessResultClosure::type.

Here is the call graph for this function:

◆ download_mq_error_handler()

static void download_mq_error_handler ( void *  cls,
enum GNUNET_MQ_Error  error 
)
static

Generic error handler, called with the appropriate error code and the same closure specified at the creation of the message queue.

Not every message queue implementation supports an error handler.

Parameters
clsclosure with the struct GNUNET_FS_DownloadContext *
errorerror code

Definition at line 1341 of file fs_download.c.

1342 {
1343  struct GNUNET_FS_DownloadContext *dc = cls;
1344 
1345  if (NULL != dc->mq)
1346  {
1347  GNUNET_MQ_destroy (dc->mq);
1348  dc->mq = NULL;
1349  }
1351  "Transmitting download request failed, trying to reconnect\n");
1352  try_reconnect (dc);
1353 }
static void try_reconnect(struct GNUNET_FS_DownloadContext *dc)
We've lost our connection with the FS service.
Definition: fs_download.c:1398

References dc, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MQ_destroy(), GNUNET_FS_DownloadContext::mq, and try_reconnect().

Referenced by do_reconnect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_reconnect()

static void do_reconnect ( void *  cls)
static

Reconnect to the FS service and transmit our queries NOW.

Parameters
clsour download context

Definition at line 1362 of file fs_download.c.

1363 {
1364  struct GNUNET_FS_DownloadContext *dc = cls;
1366  { GNUNET_MQ_hd_var_size (put,
1368  struct ClientPutMessage,
1369  dc),
1370  GNUNET_MQ_handler_end () };
1371 
1372  dc->task = NULL;
1374  "fs",
1375  handlers,
1377  dc);
1378  if (NULL == dc->mq)
1379  {
1381  "Connecting to `%s'-service failed, will try again.\n",
1382  "FS");
1383  try_reconnect (dc);
1384  return;
1385  }
1387 }
static void download_mq_error_handler(void *cls, enum GNUNET_MQ_Error error)
Generic error handler, called with the appropriate error code and the same closure specified at the c...
Definition: fs_download.c:1341
static struct GNUNET_CADET_MessageHandler handlers[]
Handlers, for diverse services.
struct GNUNET_MQ_Handle * GNUNET_CLIENT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *service_name, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *error_handler_cls)
Create a message queue to connect to a GNUnet service.
Definition: client.c:1057
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_MESSAGE_TYPE_FS_PUT
P2P response with content or active migration of content.
Response from FS service with a result for a previous FS search.
Definition: fs.h:356
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
Definition: fs_api.h:1074
Message handler for a specific message type.

References GNUNET_FS_DownloadContext::active, GNUNET_FS_Handle::cfg, dc, download_mq_error_handler(), GNUNET_CLIENT_connect(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_MESSAGE_TYPE_FS_PUT, GNUNET_MQ_handler_end, GNUNET_MQ_hd_var_size, GNUNET_FS_DownloadContext::h, handlers, GNUNET_FS_DownloadContext::mq, retry_entry(), GNUNET_FS_DownloadContext::task, and try_reconnect().

Referenced by activate_fs_download(), and try_reconnect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ activate_fs_download()

static void activate_fs_download ( void *  cls)
static

We're allowed to ask the FS service for our blocks.

Start the download.

Parameters
clsthe 'struct GNUNET_FS_DownloadContext'

Definition at line 1428 of file fs_download.c.

1429 {
1430  struct GNUNET_FS_DownloadContext *dc = cls;
1431  struct GNUNET_FS_ProgressInfo pi;
1432 
1433  GNUNET_assert (NULL == dc->mq);
1434  GNUNET_assert (NULL != dc->active);
1435  do_reconnect (dc);
1436  if (NULL != dc->mq)
1437  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download activated\n");
1440 }
@ GNUNET_FS_STATUS_DOWNLOAD_ACTIVE
Notification that this download is now actively being pursued (as opposed to waiting in the queue).

References GNUNET_FS_DownloadContext::active, dc, do_reconnect(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_FS_download_make_status_(), GNUNET_FS_STATUS_DOWNLOAD_ACTIVE, GNUNET_log, GNUNET_FS_DownloadContext::mq, and pi.

Referenced by GNUNET_FS_download_resume(), and GNUNET_FS_download_start_downloading_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ deactivate_fs_download()

static void deactivate_fs_download ( void *  cls)
static

We must stop to ask the FS service for our blocks.

Pause the download.

Parameters
clsthe struct GNUNET_FS_DownloadContext

Definition at line 1449 of file fs_download.c.

1450 {
1451  struct GNUNET_FS_DownloadContext *dc = cls;
1452  struct GNUNET_FS_ProgressInfo pi;
1453 
1454  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download deactivated\n");
1455  if (NULL != dc->mq)
1456  {
1457  GNUNET_MQ_destroy (dc->mq);
1458  dc->mq = NULL;
1459  }
1462 }
@ GNUNET_FS_STATUS_DOWNLOAD_INACTIVE
Notification that this download is no longer actively being pursued (back in the queue).

References dc, GNUNET_ERROR_TYPE_DEBUG, GNUNET_FS_download_make_status_(), GNUNET_FS_STATUS_DOWNLOAD_INACTIVE, GNUNET_log, GNUNET_MQ_destroy(), GNUNET_FS_DownloadContext::mq, and pi.

Referenced by GNUNET_FS_download_resume(), GNUNET_FS_download_start_downloading_(), and GNUNET_FS_download_suspend().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_download_request()

static struct DownloadRequest* create_download_request ( struct DownloadRequest parent,
unsigned int  chk_idx,
unsigned int  depth,
uint64_t  dr_offset,
uint64_t  file_start_offset,
uint64_t  desired_length 
)
static

(recursively) Create a download request structure.

Parameters
parentparent of the current entry
chk_idxindex of the chk for this block in the parent block
depthdepth of the current entry, 0 are the DBLOCKs, top level block is 'dc->treedepth - 1'
dr_offsetoffset in the original file this block maps to (as in, offset of the first byte of the first DBLOCK in the subtree rooted in the returned download request tree)
file_start_offsetdesired starting offset for the download in the original file; requesting tree should not contain DBLOCKs prior to the file_start_offset
desired_lengthdesired number of bytes the user wanted to access (from file_start_offset). Resulting tree should not contain DBLOCKs after file_start_offset + file_length.
Returns
download request tree for the given range of DBLOCKs at the specified depth

Definition at line 1485 of file fs_download.c.

1491 {
1492  struct DownloadRequest *dr;
1493  unsigned int i;
1494  unsigned int head_skip;
1495  uint64_t child_block_size;
1496 
1497  dr = GNUNET_new (struct DownloadRequest);
1498  dr->parent = parent;
1499  dr->depth = depth;
1500  dr->offset = dr_offset;
1501  dr->chk_idx = chk_idx;
1502  if (0 == depth)
1503  return dr;
1504  child_block_size = GNUNET_FS_tree_compute_tree_size (depth - 1);
1505 
1506  /* calculate how many blocks at this level are not interesting
1507  * from the start (rounded down), either because of the requested
1508  * file offset or because this IBlock is further along */
1509  if (dr_offset < file_start_offset)
1510  {
1511  head_skip = (file_start_offset - dr_offset) / child_block_size;
1512  }
1513  else
1514  {
1515  head_skip = 0;
1516  }
1517 
1518  /* calculate index of last block at this level that is interesting (rounded up) */
1519  dr->num_children =
1520  (file_start_offset + desired_length - dr_offset) / child_block_size;
1521  if (dr->num_children * child_block_size <
1522  file_start_offset + desired_length - dr_offset)
1523  dr->num_children++; /* round up */
1524  GNUNET_assert (dr->num_children > head_skip);
1525  dr->num_children -= head_skip;
1526  if (dr->num_children > CHK_PER_INODE)
1527  dr->num_children = CHK_PER_INODE; /* cap at max */
1529  "Block at offset %llu and depth %u has %u children\n",
1530  (unsigned long long) dr_offset,
1531  depth,
1532  dr->num_children);
1533 
1534  /* now we can get the total number of *interesting* children for this block */
1535 
1536  /* why else would we have gotten here to begin with? (that'd be a bad logic error) */
1537  GNUNET_assert (dr->num_children > 0);
1538 
1539  dr->children = GNUNET_new_array (dr->num_children, struct DownloadRequest *);
1540  for (i = 0; i < dr->num_children; i++)
1541  {
1542  dr->children[i] =
1544  i + head_skip,
1545  depth - 1,
1546  dr_offset + (i + head_skip) * child_block_size,
1547  file_start_offset,
1548  desired_length);
1549  }
1550  return dr;
1551 }
static struct DownloadRequest * create_download_request(struct DownloadRequest *parent, unsigned int chk_idx, unsigned int depth, uint64_t dr_offset, uint64_t file_start_offset, uint64_t desired_length)
(recursively) Create a download request structure.
Definition: fs_download.c:1485
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.

References DownloadRequest::children, DownloadRequest::chk_idx, CHK_PER_INODE, DownloadRequest::depth, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_FS_tree_compute_tree_size(), GNUNET_log, GNUNET_new, GNUNET_new_array, DownloadRequest::num_children, DownloadRequest::offset, and DownloadRequest::parent.

Referenced by GNUNET_FS_download_start_task_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ reconstruct_cont()

static void reconstruct_cont ( void *  cls)
static

Continuation after a possible attempt to reconstruct the current IBlock from the existing file.

Parameters
clsthe 'struct ReconstructContext'

Definition at line 1561 of file fs_download.c.

1562 {
1563  struct GNUNET_FS_DownloadContext *dc = cls;
1564 
1565  /* clean up state from tree encoder */
1566  if (NULL != dc->task)
1567  {
1569  dc->task = NULL;
1570  }
1571  if (NULL != dc->rfh)
1572  {
1574  dc->rfh = NULL;
1575  }
1576  /* start "normal" download */
1578  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting normal download\n");
1580 }

References dc, GNUNET_break, GNUNET_DISK_file_close(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_OK, GNUNET_SCHEDULER_cancel(), GNUNET_YES, GNUNET_FS_DownloadContext::issue_requests, GNUNET_FS_DownloadContext::rfh, schedule_block_download(), GNUNET_FS_DownloadContext::task, and GNUNET_FS_DownloadContext::top_request.

Referenced by GNUNET_FS_download_start_task_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_next_block()

static void get_next_block ( void *  cls)
static

Task requesting the next block from the tree encoder.

Parameters
clsthe 'struct GNUJNET_FS_DownloadContext' we're processing

Definition at line 1589 of file fs_download.c.

1590 {
1591  struct GNUNET_FS_DownloadContext *dc = cls;
1592 
1593  dc->task = NULL;
1595 }
void GNUNET_FS_tree_encoder_next(struct GNUNET_FS_TreeEncoder *te)
Encrypt the next block of the file (and call proc and progress accordingly; or of course "cont" if we...
Definition: fs_tree.c:320
struct GNUNET_FS_TreeEncoder * te
Tree encoder used for the reconstruction.
Definition: fs_api.h:1839

References dc, GNUNET_FS_tree_encoder_next(), GNUNET_FS_DownloadContext::task, and GNUNET_FS_DownloadContext::te.

Referenced by GNUNET_FS_download_start_task_(), and reconstruct_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ reconstruct_cb()

static void reconstruct_cb ( void *  cls,
const struct ContentHashKey chk,
uint64_t  offset,
unsigned int  depth,
enum GNUNET_BLOCK_Type  type,
const void *  block,
uint16_t  block_size 
)
static

Function called asking for the current (encoded) block to be processed.

After processing the client should either call "GNUNET_FS_tree_encode_next" or (on error) "GNUNET_FS_tree_encode_finish".

This function checks if the content on disk matches the expected content based on the URI.

Parameters
clsclosure
chkcontent hash key for the block
offsetoffset of the block
depthdepth of the block, 0 for DBLOCK
typetype of the block (IBLOCK or DBLOCK)
blockthe (encrypted) block
block_sizesize of block (in bytes)

Definition at line 1616 of file fs_download.c.

1623 {
1624  struct GNUNET_FS_DownloadContext *dc = cls;
1625  struct GNUNET_FS_ProgressInfo pi;
1626  struct DownloadRequest *dr;
1627  uint64_t blen;
1628  unsigned int chld;
1629 
1630  /* find corresponding request entry */
1631  dr = dc->top_request;
1632  while (dr->depth > depth)
1633  {
1634  GNUNET_assert (dr->num_children > 0);
1635  blen = GNUNET_FS_tree_compute_tree_size (dr->depth - 1);
1636  chld = (offset - dr->offset) / blen;
1637  if (chld < dr->children[0]->chk_idx)
1638  {
1640  "Block %u < %u irrelevant for our range\n",
1641  chld,
1642  dr->children[0]->chk_idx);
1644  return; /* irrelevant block */
1645  }
1646  if (chld > dr->children[dr->num_children - 1]->chk_idx)
1647  {
1649  "Block %u > %u irrelevant for our range\n",
1650  chld,
1651  dr->children[dr->num_children - 1]->chk_idx);
1653  return; /* irrelevant block */
1654  }
1655  dr = dr->children[chld - dr->children[0]->chk_idx];
1656  }
1657  GNUNET_log (
1659  "Matched TE block with request at offset %llu and depth %u in state %d\n",
1660  (unsigned long long) dr->offset,
1661  dr->depth,
1662  dr->state);
1663  /* FIXME: this code needs more testing and might
1664  need to handle more states... */
1665  switch (dr->state)
1666  {
1667  case BRS_INIT:
1668  break;
1669 
1670  case BRS_RECONSTRUCT_DOWN:
1671  break;
1672 
1674  break;
1675 
1676  case BRS_RECONSTRUCT_UP:
1677  break;
1678 
1679  case BRS_CHK_SET:
1680  if (0 == memcmp (chk, &dr->chk, sizeof(struct ContentHashKey)))
1681  {
1682  GNUNET_log (
1684  "Reconstruction succeeded, can use block at offset %llu, depth %u\n",
1685  (unsigned long long) offset,
1686  depth);
1687  /* block matches, hence tree below matches;
1688  * this request is done! */
1689  dr->state = BRS_DOWNLOAD_UP;
1691  &dr->chk.query,
1692  dr);
1693  /* calculate how many bytes of payload this block
1694  * corresponds to */
1696  /* how many of those bytes are in the requested range? */
1697  blen = GNUNET_MIN (blen, dc->length + dc->offset - dr->offset);
1698  /* signal progress */
1699  dc->completed += blen;
1701  pi.value.download.specifics.progress.data = NULL;
1702  pi.value.download.specifics.progress.offset = offset;
1703  pi.value.download.specifics.progress.data_len = 0;
1704  pi.value.download.specifics.progress.depth = 0;
1705  pi.value.download.specifics.progress.respect_offered = 0;
1706  pi.value.download.specifics.progress.block_download_duration =
1709  /* FIXME: duplicated code from 'process_result_with_request - refactor */
1710  if (dc->completed == dc->length)
1711  {
1712  /* download completed, signal */
1714  "Download completed, truncating file to desired length %llu\n",
1715  (unsigned long long) GNUNET_ntohll (
1716  dc->uri->data.chk.file_length));
1717  /* truncate file to size (since we store IBlocks at the end) */
1718  if (NULL != dc->filename)
1719  {
1720  if (0 != truncate (dc->filename,
1723  "truncate",
1724  dc->filename);
1725  }
1726  }
1727  }
1728  else
1729  GNUNET_log (
1731  "Reconstruction failed, need to download block at offset %llu, depth %u\n",
1732  (unsigned long long) offset,
1733  depth);
1734  break;
1735 
1736  case BRS_DOWNLOAD_DOWN:
1737  break;
1738 
1739  case BRS_DOWNLOAD_UP:
1740  break;
1741 
1742  case BRS_ERROR:
1743  break;
1744 
1745  default:
1746  GNUNET_assert (0);
1747  break;
1748  }
1750  if ((dr == dc->top_request) && (dr->state == BRS_DOWNLOAD_UP))
1751  check_completed (dc);
1752 }
static void get_next_block(void *cls)
Task requesting the next block from the tree encoder.
Definition: fs_download.c:1589
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1268

References GNUNET_FS_DownloadContext::active, BRS_CHK_SET, BRS_DOWNLOAD_DOWN, BRS_DOWNLOAD_UP, BRS_ERROR, BRS_INIT, BRS_RECONSTRUCT_DOWN, BRS_RECONSTRUCT_META_UP, BRS_RECONSTRUCT_UP, check_completed(), DownloadRequest::children, GNUNET_FS_Uri::chk, DownloadRequest::chk, DownloadRequest::chk_idx, GNUNET_FS_DownloadContext::completed, GNUNET_FS_Uri::data, dc, DownloadRequest::depth, FileIdentifier::file_length, GNUNET_FS_DownloadContext::filename, get_next_block(), GNUNET_assert, GNUNET_CONTAINER_multihashmap_remove(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_FS_download_make_status_(), GNUNET_FS_STATUS_DOWNLOAD_PROGRESS, GNUNET_FS_tree_compute_tree_size(), GNUNET_log, GNUNET_log_strerror_file, GNUNET_MIN, GNUNET_ntohll(), GNUNET_SCHEDULER_add_now(), GNUNET_TIME_UNIT_ZERO, GNUNET_FS_DownloadContext::length, DownloadRequest::num_children, DownloadRequest::offset, GNUNET_FS_DownloadContext::offset, pi, ContentHashKey::query, DownloadRequest::state, GNUNET_FS_DownloadContext::task, GNUNET_FS_DownloadContext::top_request, and GNUNET_FS_DownloadContext::uri.

Referenced by GNUNET_FS_download_start_task_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fh_reader()

static size_t fh_reader ( void *  cls,
uint64_t  offset,
size_t  max,
void *  buf,
char **  emsg 
)
static

Function called by the tree encoder to obtain a block of plaintext data (for the lowest level of the tree).

Parameters
clsour 'struct ReconstructContext'
offsetidentifies which block to get
max(maximum) number of bytes to get; returning fewer will also cause errors
bufwhere to copy the plaintext buffer
emsglocation to store an error message (on error)
Returns
number of bytes copied to buf, 0 on error

Definition at line 1768 of file fs_download.c.

1769 {
1770  struct GNUNET_FS_DownloadContext *dc = cls;
1771  struct GNUNET_DISK_FileHandle *fh = dc->rfh;
1772  ssize_t ret;
1773 
1774  if (NULL != emsg)
1775  *emsg = NULL;
1776  if (offset != GNUNET_DISK_file_seek (fh, offset, GNUNET_DISK_SEEK_SET))
1777  {
1778  if (NULL != emsg)
1779  *emsg = GNUNET_strdup (strerror (errno));
1780  return 0;
1781  }
1783  if (ret < 0)
1784  {
1785  if (NULL != emsg)
1786  *emsg = GNUNET_strdup (strerror (errno));
1787  return 0;
1788  }
1789  return ret;
1790 }
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static char buf[2048]
#define max(x, y)

References buf, dc, fh, GNUNET_DISK_file_read(), GNUNET_DISK_file_seek(), GNUNET_DISK_SEEK_SET, GNUNET_strdup, max, ret, and GNUNET_FS_DownloadContext::rfh.

Referenced by GNUNET_FS_download_start_task_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_FS_download_start_task_()

void GNUNET_FS_download_start_task_ ( void *  cls)

Task that creates the initial (top-level) download request for the file.

Parameters
clsthe 'struct GNUNET_FS_DownloadContext'

Definition at line 1800 of file fs_download.c.

1801 {
1802  struct GNUNET_FS_DownloadContext *dc = cls;
1803  struct GNUNET_FS_ProgressInfo pi;
1804  struct GNUNET_DISK_FileHandle *fh;
1805 
1806  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start task running...\n");
1807  dc->task = NULL;
1808  if (0 == dc->length)
1809  {
1810  /* no bytes required! */
1811  if (NULL != dc->filename)
1812  {
1816  | ((0 ==
1819  : 0),
1825  }
1828  pi.value.download.specifics.start.meta = dc->meta;
1830  check_completed (dc);
1831  return;
1832  }
1833  if (NULL != dc->emsg)
1834  return;
1835  if (NULL == dc->top_request)
1836  {
1838  0,
1839  dc->treedepth - 1,
1840  0,
1841  dc->offset,
1842  dc->length);
1845  ? dc->uri->data.chk.chk
1846  : dc->uri->data.loc.fi.chk;
1847  /* signal start */
1849  if (NULL != dc->search)
1852  pi.value.download.specifics.start.meta = dc->meta;
1854  }
1856  /* attempt reconstruction from disk */
1861  if (dc->top_request->state == BRS_CHK_SET)
1862  {
1863  if (NULL != dc->rfh)
1864  {
1865  /* first, try top-down */
1867  "Trying top-down reconstruction for `%s'\n",
1868  dc->filename);
1870  switch (dc->top_request->state)
1871  {
1872  case BRS_CHK_SET:
1873  break; /* normal */
1874 
1875  case BRS_DOWNLOAD_DOWN:
1876  break; /* normal, some blocks already down */
1877 
1878  case BRS_DOWNLOAD_UP:
1879  /* already done entirely, party! */
1880  if (NULL != dc->rfh)
1881  {
1882  /* avoid hanging on to file handle longer than
1883  * necessary */
1885  dc->rfh = NULL;
1886  }
1887  return;
1888 
1889  case BRS_ERROR:
1890  GNUNET_asprintf (&dc->emsg, _ ("Invalid URI"));
1893  pi.value.download.specifics.error.message = dc->emsg;
1895  return;
1896 
1897  default:
1898  GNUNET_assert (0);
1899  break;
1900  }
1901  }
1902  }
1903  /* attempt reconstruction from meta data */
1905  (NULL != dc->meta))
1906  {
1907  GNUNET_log (
1909  "Trying to find embedded meta data for download of size %llu with %u bytes MD\n",
1910  (unsigned long long) GNUNET_FS_uri_chk_get_file_size (dc->uri),
1911  (unsigned int) GNUNET_FS_meta_data_get_serialized_size (dc->meta));
1914  {
1915  if (NULL != dc->rfh)
1916  {
1917  /* avoid hanging on to file handle longer than
1918  * necessary */
1920  dc->rfh = NULL;
1921  }
1922  return; /* finished, status update was already done for us */
1923  }
1924  }
1925  if (NULL != dc->rfh)
1926  {
1927  /* finally, actually run bottom-up */
1929  "Trying bottom-up reconstruction of file `%s'\n",
1930  dc->filename);
1931  dc->te =
1934  dc,
1935  &fh_reader,
1936  &reconstruct_cb,
1937  NULL,
1938  &reconstruct_cont);
1940  }
1941  else
1942  {
1943  /* simple, top-level download */
1946  }
1948  check_completed (dc);
1949 }
void GNUNET_FS_search_result_sync_(struct GNUNET_FS_SearchResult *sr)
Synchronize this search result with its mirror on disk.
Definition: fs_api.c:2149
#define MAX_INLINE_SIZE
Maximum size for a file to be considered for inlining in a directory.
Definition: fs_api.h:50
@ GNUNET_FS_URI_CHK
Content-hash-key (simple file).
Definition: fs_api.h:144
static void reconstruct_cb(void *cls, const struct ContentHashKey *chk, uint64_t offset, unsigned int depth, enum GNUNET_BLOCK_Type type, const void *block, uint16_t block_size)
Function called asking for the current (encoded) block to be processed.
Definition: fs_download.c:1616
static size_t fh_reader(void *cls, uint64_t offset, size_t max, void *buf, char **emsg)
Function called by the tree encoder to obtain a block of plaintext data (for the lowest level of the ...
Definition: fs_download.c:1768
static int match_full_data(void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_len)
Type of a function that libextractor calls for each meta data item found.
Definition: fs_download.c:602
static void reconstruct_cont(void *cls)
Continuation after a possible attempt to reconstruct the current IBlock from the existing file.
Definition: fs_download.c:1561
void GNUNET_FS_download_start_downloading_(struct GNUNET_FS_DownloadContext *dc)
Start the downloading process (by entering the queue).
Definition: fs_download.c:2184
struct GNUNET_FS_TreeEncoder * GNUNET_FS_tree_encoder_create(struct GNUNET_FS_Handle *h, uint64_t size, void *cls, GNUNET_FS_DataReader reader, GNUNET_FS_TreeBlockProcessor proc, GNUNET_FS_TreeProgressCallback progress, GNUNET_SCHEDULER_TaskCallback cont)
Initialize a tree encoder.
Definition: fs_tree.c:258
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory).
Definition: disk.c:481
@ GNUNET_FS_STATUS_DOWNLOAD_START
Notification that we have started this download.
int GNUNET_FS_meta_data_iterate(const struct GNUNET_FS_MetaData *md, EXTRACTOR_MetaDataProcessor iter, void *iter_cls)
Iterate over MD entries.
Definition: meta_data.c:422
struct ContentHashKey chk
Query and key of the top GNUNET_EC_IBlock.
Definition: fs_api.h:104
enum GNUNET_FS_UriType type
Type of the URI.
Definition: fs_api.h:171
struct Location loc
Information needed to retrieve a file including signed location (identity of a peer) of the content.
Definition: fs_api.h:218
struct FileIdentifier fi
Information about the shared file.
Definition: fs_api.h:117

References _, BRS_CHK_SET, BRS_DOWNLOAD_DOWN, BRS_DOWNLOAD_UP, BRS_ERROR, check_completed(), GNUNET_FS_Uri::chk, FileIdentifier::chk, DownloadRequest::chk, create_download_request(), GNUNET_FS_Uri::data, dc, GNUNET_FS_DownloadContext::emsg, fh, fh_reader(), Location::fi, GNUNET_FS_DownloadContext::filename, get_next_block(), GNUNET_asprintf(), GNUNET_assert, GNUNET_DISK_file_close(), GNUNET_DISK_file_open(), GNUNET_DISK_file_test(), GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_OPEN_READ, GNUNET_DISK_OPEN_READWRITE, GNUNET_DISK_OPEN_TRUNCATE, GNUNET_DISK_PERM_GROUP_READ, GNUNET_DISK_PERM_NONE, GNUNET_DISK_PERM_OTHER_READ, GNUNET_DISK_PERM_USER_READ, GNUNET_DISK_PERM_USER_WRITE, GNUNET_ERROR_TYPE_DEBUG, GNUNET_FS_download_make_status_(), GNUNET_FS_download_start_downloading_(), GNUNET_FS_download_sync_(), GNUNET_FS_meta_data_get_serialized_size(), GNUNET_FS_meta_data_iterate(), GNUNET_FS_search_result_sync_(), GNUNET_FS_STATUS_DOWNLOAD_ERROR, GNUNET_FS_STATUS_DOWNLOAD_START, GNUNET_FS_tree_encoder_create(), GNUNET_FS_URI_CHK, GNUNET_FS_uri_chk_get_file_size(), GNUNET_log, GNUNET_SCHEDULER_add_now(), GNUNET_YES, GNUNET_FS_DownloadContext::h, GNUNET_FS_DownloadContext::issue_requests, GNUNET_FS_DownloadContext::length, GNUNET_FS_Uri::loc, match_full_data(), MAX_INLINE_SIZE, GNUNET_FS_DownloadContext::meta, GNUNET_FS_DownloadContext::offset, pi, reconstruct_cb(), reconstruct_cont(), GNUNET_FS_DownloadContext::rfh, schedule_block_download(), GNUNET_FS_DownloadContext::search, DownloadRequest::state, GNUNET_FS_DownloadContext::task, GNUNET_FS_DownloadContext::te, GNUNET_FS_DownloadContext::top_request, GNUNET_FS_DownloadContext::treedepth, try_top_down_reconstruction(), GNUNET_FS_Uri::type, and GNUNET_FS_DownloadContext::uri.

Referenced by create_download_context(), and deserialize_download().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_FS_download_signal_suspend_()

void GNUNET_FS_download_signal_suspend_ ( void *  cls)

Create SUSPEND event for the given download operation and then clean up our state (without stop signal).

Parameters
clsthe struct GNUNET_FS_DownloadContext to signal for

Definition at line 1953 of file fs_download.c.

1954 {
1955  struct GNUNET_FS_DownloadContext *dc = cls;
1956  struct GNUNET_FS_ProgressInfo pi;
1957 
1958  if (NULL != dc->top)
1959  GNUNET_FS_end_top (dc->h, dc->top);
1960  while (NULL != dc->child_head)
1962  if (NULL != dc->search)
1963  {
1964  dc->search->download = NULL;
1965  dc->search = NULL;
1966  }
1967  if (NULL != dc->job_queue)
1968  {
1970  dc->job_queue = NULL;
1971  }
1972  if (NULL != dc->parent)
1974  dc->parent->child_tail,
1975  dc);
1976  if (NULL != dc->task)
1977  {
1979  dc->task = NULL;
1980  }
1983  if (NULL != dc->te)
1984  {
1986  dc->te = NULL;
1987  }
1988  if (NULL != dc->rfh)
1989  {
1991  dc->rfh = NULL;
1992  }
1994  if (NULL != dc->active)
1995  {
1997  dc->active = NULL;
1998  }
1999  GNUNET_free (dc->filename);
2004  GNUNET_assert (NULL == dc->job_queue);
2005  GNUNET_free (dc);
2006 }
void GNUNET_FS_end_top(struct GNUNET_FS_Handle *h, struct TopLevelActivity *top)
Destroy a top-level activity entry.
Definition: fs_api.c:402
void GNUNET_FS_download_signal_suspend_(void *cls)
Create SUSPEND event for the given download operation and then clean up our state (without stop signa...
Definition: fs_download.c:1953
void GNUNET_FS_tree_encoder_finish(struct GNUNET_FS_TreeEncoder *te, char **emsg)
Clean up a tree encoder and return information about possible errors.
Definition: fs_tree.c:432
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
void GNUNET_FS_uri_destroy(struct GNUNET_FS_Uri *uri)
Free URI.
Definition: fs_uri.c:677
@ GNUNET_FS_STATUS_DOWNLOAD_SUSPEND
Notification that this download was suspended.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
void GNUNET_FS_meta_data_destroy(struct GNUNET_FS_MetaData *md)
Free meta data.
Definition: meta_data.c:170
struct GNUNET_FS_DownloadContext * child_tail
Tail of list of child downloads.
Definition: fs_api.h:1780
char * serialization
Random portion of filename we use for syncing state of this download.
Definition: fs_api.h:1816
struct TopLevelActivity * top
Our top-level activity entry (if we are top-level, otherwise NULL).
Definition: fs_api.h:1753
struct GNUNET_FS_DownloadContext * download
ID of an associated download based on this search result (or NULL for none).
Definition: fs_api.h:546

References GNUNET_FS_DownloadContext::active, GNUNET_FS_DownloadContext::child_head, GNUNET_FS_DownloadContext::child_tail, dc, GNUNET_FS_SearchResult::download, GNUNET_FS_DownloadContext::filename, GNUNET_assert, GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_multihashmap_destroy(), GNUNET_DISK_file_close(), GNUNET_free, GNUNET_FS_dequeue_(), GNUNET_FS_download_make_status_(), GNUNET_FS_download_signal_suspend_(), GNUNET_FS_end_top(), GNUNET_FS_free_download_request_(), GNUNET_FS_meta_data_destroy(), GNUNET_FS_STATUS_DOWNLOAD_SUSPEND, GNUNET_FS_tree_encoder_finish(), GNUNET_FS_uri_destroy(), GNUNET_SCHEDULER_cancel(), GNUNET_FS_DownloadContext::h, GNUNET_FS_DownloadContext::job_queue, GNUNET_FS_DownloadContext::meta, GNUNET_FS_DownloadContext::parent, pi, GNUNET_FS_DownloadContext::rfh, GNUNET_FS_DownloadContext::search, GNUNET_FS_DownloadContext::serialization, GNUNET_FS_DownloadContext::task, GNUNET_FS_DownloadContext::te, GNUNET_FS_DownloadContext::temp_filename, GNUNET_FS_DownloadContext::top, GNUNET_FS_DownloadContext::top_request, and GNUNET_FS_DownloadContext::uri.

Referenced by deserialize_download(), GNUNET_FS_download_signal_suspend_(), GNUNET_FS_download_start(), search_result_stop(), and search_result_suspend().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_download_context()

struct GNUNET_FS_DownloadContext* create_download_context ( struct GNUNET_FS_Handle h,
const struct GNUNET_FS_Uri uri,
const struct GNUNET_FS_MetaData meta,
const char *  filename,
const char *  tempname,
uint64_t  offset,
uint64_t  length,
uint32_t  anonymity,
enum GNUNET_FS_DownloadOptions  options,
void *  cctx 
)

Helper function to setup the download context.

Parameters
hhandle to the file sharing subsystem
urithe URI of the file (determines what to download); CHK or LOC URI
metaknown metadata for the file (can be NULL)
filenamewhere to store the file, maybe NULL (then no file is created on disk and data must be grabbed from the callbacks)
tempnamewhere to store temporary file data, not used if filename is non-NULL; can be NULL (in which case we will pick a name if needed); the temporary file may already exist, in which case we will try to use the data that is there and if it is not what is desired, will overwrite it
offsetat what offset should we start the download (typically 0)
lengthhow many bytes should be downloaded starting at offset
anonymityanonymity level to use for the download
optionsvarious options
cctxinitial value for the client context for this download
Returns
context that can be used to control this download

Definition at line 2029 of file fs_download.c.

2039 {
2040  struct GNUNET_FS_DownloadContext *dc;
2041 
2043  if ((offset + length < offset) ||
2045  {
2046  GNUNET_break (0);
2047  return NULL;
2048  }
2051  "Starting download %p, %u bytes at offset %llu\n",
2052  dc,
2053  (unsigned int) length,
2054  (unsigned long long) offset);
2055  dc->h = h;
2056  dc->uri = GNUNET_FS_uri_dup (uri);
2058  dc->client_info = cctx;
2060  if (NULL != filename)
2061  {
2065  &dc->old_file_size,
2066  GNUNET_YES,
2067  GNUNET_YES));
2068  }
2069  if (GNUNET_FS_uri_test_loc (dc->uri))
2072  dc->offset = offset;
2073  dc->length = length;
2074  dc->anonymity = anonymity;
2075  dc->options = options;
2076  dc->active =
2078  GNUNET_NO);
2079  dc->treedepth =
2081  if ((NULL == filename) && (is_recursive_download (dc)))
2082  {
2083  if (NULL != tempname)
2084  dc->temp_filename = GNUNET_strdup (tempname);
2085  else
2086  dc->temp_filename = GNUNET_DISK_mktemp ("gnunet-directory-download-tmp");
2087  }
2089  "Starting download `%s' of %llu bytes with tree depth %u\n",
2090  filename,
2091  (unsigned long long) length,
2092  dc->treedepth);
2093  GNUNET_assert (NULL == dc->job_queue);
2095  return dc;
2096 }
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
void GNUNET_FS_download_start_task_(void *cls)
Task that creates the initial (top-level) download request for the file.
Definition: fs_download.c:1800
unsigned int GNUNET_FS_compute_depth(uint64_t flen)
Compute the depth of the CHK tree.
Definition: fs_tree.c:125
static unsigned int anonymity
char * GNUNET_DISK_mktemp(const char *t)
Create an (empty) temporary file on disk.
Definition: disk.c:380
enum GNUNET_GenericReturnValue GNUNET_DISK_file_size(const char *filename, uint64_t *size, int include_symbolic_links, int single_file_mode)
Get the size of the file (or directory) of the given file (in bytes).
Definition: disk.c:221
int GNUNET_FS_uri_test_loc(const struct GNUNET_FS_Uri *uri)
Is this a location URI?
Definition: fs_uri.c:1384
struct GNUNET_FS_Uri * GNUNET_FS_uri_dup(const struct GNUNET_FS_Uri *uri)
Duplicate URI.
Definition: fs_uri.c:987
int GNUNET_FS_uri_test_chk(const struct GNUNET_FS_Uri *uri)
Is this a file (or directory) URI?
Definition: fs_uri.c:1346
int GNUNET_FS_uri_loc_get_peer_identity(const struct GNUNET_FS_Uri *uri, struct GNUNET_PeerIdentity *peer)
Obtain the identity of the peer offering the data.
Definition: fs_uri.c:812
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
struct GNUNET_FS_MetaData * GNUNET_FS_meta_data_duplicate(const struct GNUNET_FS_MetaData *md)
Duplicate a struct GNUNET_FS_MetaData.
Definition: meta_data.c:531
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111

References GNUNET_FS_DownloadContext::active, GNUNET_FS_DownloadContext::anonymity, anonymity, GNUNET_FS_DownloadContext::client_info, DBLOCK_SIZE, dc, GNUNET_FS_DownloadContext::filename, filename, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_multihashmap_create(), GNUNET_DISK_file_size(), GNUNET_DISK_file_test(), GNUNET_DISK_mktemp(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_FS_compute_depth(), GNUNET_FS_download_start_task_(), GNUNET_FS_meta_data_duplicate(), GNUNET_FS_uri_chk_get_file_size(), GNUNET_FS_uri_dup(), GNUNET_FS_uri_loc_get_peer_identity(), GNUNET_FS_uri_test_chk(), GNUNET_FS_uri_test_loc(), GNUNET_log, GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_now(), GNUNET_strdup, GNUNET_TIME_absolute_get(), GNUNET_YES, h, GNUNET_FS_DownloadContext::h, is_recursive_download(), GNUNET_FS_DownloadContext::job_queue, GNUNET_FS_DownloadContext::length, GNUNET_FS_DownloadContext::meta, meta, GNUNET_FS_DownloadContext::offset, GNUNET_FS_DownloadContext::old_file_size, options, GNUNET_FS_DownloadContext::options, GNUNET_FS_DownloadContext::start_time, GNUNET_FS_DownloadContext::target, GNUNET_FS_DownloadContext::task, GNUNET_FS_DownloadContext::temp_filename, GNUNET_FS_DownloadContext::treedepth, GNUNET_FS_DownloadContext::uri, and uri.

Referenced by GNUNET_FS_download_start(), and GNUNET_FS_download_start_from_search().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_FS_download_start_downloading_()

void GNUNET_FS_download_start_downloading_ ( struct GNUNET_FS_DownloadContext dc)

Start the downloading process (by entering the queue).

Parameters
dcour download context

Definition at line 2184 of file fs_download.c.

2185 {
2186  if (dc->completed == dc->length)
2187  return;
2188  if (NULL != dc->mq)
2189  return; /* already running */
2190  GNUNET_assert (NULL == dc->job_queue);
2191  GNUNET_assert (NULL == dc->task);
2192  GNUNET_assert (NULL != dc->active);
2193  dc->job_queue =
2194  GNUNET_FS_queue_ (dc->h,
2197  dc,
2198  (dc->length + DBLOCK_SIZE - 1) / DBLOCK_SIZE,
2203  "Download %p put into queue as job %p\n",
2204  dc,
2205  dc->job_queue);
2206 }
struct GNUNET_FS_QueueEntry * GNUNET_FS_queue_(struct GNUNET_FS_Handle *h, GNUNET_SCHEDULER_TaskCallback start, GNUNET_SCHEDULER_TaskCallback stop, void *cls, unsigned int blocks, enum GNUNET_FS_QueuePriority priority)
Add a job to the queue.
Definition: fs_api.c:321
@ GNUNET_FS_QUEUE_PRIORITY_NORMAL
Default priority.
Definition: fs_api.h:413
@ GNUNET_FS_QUEUE_PRIORITY_PROBE
This is a probe (low priority).
Definition: fs_api.h:408
static void activate_fs_download(void *cls)
We're allowed to ask the FS service for our blocks.
Definition: fs_download.c:1428
static void deactivate_fs_download(void *cls)
We must stop to ask the FS service for our blocks.
Definition: fs_download.c:1449

References activate_fs_download(), GNUNET_FS_DownloadContext::active, GNUNET_FS_DownloadContext::completed, DBLOCK_SIZE, dc, deactivate_fs_download(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_FS_DOWNLOAD_IS_PROBE, GNUNET_FS_queue_(), GNUNET_FS_QUEUE_PRIORITY_NORMAL, GNUNET_FS_QUEUE_PRIORITY_PROBE, GNUNET_log, GNUNET_FS_DownloadContext::h, GNUNET_FS_DownloadContext::job_queue, GNUNET_FS_DownloadContext::length, GNUNET_FS_DownloadContext::mq, GNUNET_FS_DownloadContext::options, and GNUNET_FS_DownloadContext::task.

Referenced by GNUNET_FS_download_start_task_().

Here is the call graph for this function:
Here is the caller graph for this function: