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

📄 download.c

📁 GNUnet是一个安全的点对点网络框架
💻 C
📖 第 1 页 / 共 2 页
字号:
    {      GNUNET_hash (data, size, &hc);      if (0 == memcmp (&hc, &node->chk.key, sizeof (GNUNET_HashCode)))        {          notify_client_about_progress (node, data, size);          if (node->level > 0)            iblock_download_children (node, data, size);          ret = GNUNET_YES;        }    }  GNUNET_free (data);  return ret;}/** * DOWNLOAD children of this GNUNET_EC_IBlock. * * @param node the node that should be downloaded */static voidiblock_download_children (const struct Node *node,                          const char *data, unsigned int size){  struct GNUNET_GE_Context *ectx = node->ctx->ectx;  int i;  struct Node *child;  unsigned int childcount;  const GNUNET_EC_ContentHashKey *chks;  unsigned int levelSize;  unsigned long long baseOffset;  GNUNET_GE_ASSERT (ectx, node->level > 0);  childcount = size / sizeof (GNUNET_EC_ContentHashKey);  if (size != childcount * sizeof (GNUNET_EC_ContentHashKey))    {      GNUNET_GE_BREAK (ectx, 0);      return;    }  if (node->level == 1)    {      levelSize = GNUNET_ECRS_DBLOCK_SIZE;      baseOffset =        node->offset / sizeof (GNUNET_EC_ContentHashKey) *        GNUNET_ECRS_DBLOCK_SIZE;    }  else    {      levelSize =        sizeof (GNUNET_EC_ContentHashKey) * GNUNET_ECRS_CHK_PER_INODE;      baseOffset = node->offset * GNUNET_ECRS_CHK_PER_INODE;    }  chks = (const GNUNET_EC_ContentHashKey *) data;  for (i = 0; i < childcount; i++)    {      child = GNUNET_malloc (sizeof (struct Node));      child->ctx = node->ctx;      child->chk = chks[i];      child->offset = baseOffset + i * levelSize;      GNUNET_GE_ASSERT (ectx, child->offset < node->ctx->total);      child->level = node->level - 1;      GNUNET_GE_ASSERT (ectx, (child->level != 0) ||                        ((child->offset % GNUNET_ECRS_DBLOCK_SIZE) == 0));      if (GNUNET_NO == check_node_present (child))        add_request (child);      else        GNUNET_free (child);    /* done already! */    }}/** * Decrypts a given data block * * @param data represents the data block * @param hashcode represents the key concatenated with the initial *        value used in the alg * @param result where to store the result (encrypted block) * @returns GNUNET_OK on success, GNUNET_SYSERR on error */static intdecrypt_content (const char *data,                 unsigned int size, const GNUNET_HashCode * hashcode,                 char *result){  GNUNET_AES_InitializationVector iv;  GNUNET_AES_SessionKey skey;  /* get key and init value from the GNUNET_HashCode */  GNUNET_hash_to_AES_key (hashcode, &skey, &iv);  return GNUNET_AES_decrypt (&skey, data, size, &iv, result);}/** * We received a GNUNET_EC_ContentHashKey reply for a block. Decrypt.  Note * that the caller (fslib) has already aquired the * RM lock (we sometimes aquire it again in callees, * mostly because our callees could be also be theoretically * called from elsewhere). * * @param cls the node for which the reply is given, freed in *        the function! * @param query the query for which reply is the answer * @param reply the reply * @return GNUNET_OK if the reply was valid, GNUNET_SYSERR on error */static intcontent_receive_callback (const GNUNET_HashCode * query,                          const GNUNET_DatastoreValue * reply, void *cls,                          unsigned long long uid){  struct Node *node = cls;  struct GNUNET_ECRS_DownloadContext *rm = node->ctx;  struct GNUNET_GE_Context *ectx = rm->ectx;  GNUNET_HashCode hc;  unsigned int size;  char *data;  if (rm->abortFlag != GNUNET_NO)    return GNUNET_SYSERR;  GNUNET_GE_ASSERT (ectx,                    0 == memcmp (query, &node->chk.query,                                 sizeof (GNUNET_HashCode)));  size = ntohl (reply->size) - sizeof (GNUNET_DatastoreValue);  if ((size <= sizeof (GNUNET_EC_DBlock)) ||      (size - sizeof (GNUNET_EC_DBlock) != get_node_size (node)))    {      GNUNET_GE_BREAK (ectx, 0);      return GNUNET_SYSERR;     /* invalid size! */    }  size -= sizeof (GNUNET_EC_DBlock);  data = GNUNET_malloc (size);  if (GNUNET_SYSERR ==      decrypt_content ((const char *)                       &((const GNUNET_EC_DBlock *) &reply[1])[1], size,                       &node->chk.key, data))    GNUNET_GE_ASSERT (ectx, 0);  GNUNET_hash (data, size, &hc);  if (0 != memcmp (&hc, &node->chk.key, sizeof (GNUNET_HashCode)))    {      GNUNET_free (data);      GNUNET_GE_BREAK (ectx, 0);      signal_abort (rm,                    _("Decrypted content does not match key. "                      "This is either a bug or a maliciously inserted "                      "file. Download aborted.\n"));      return GNUNET_SYSERR;    }  if (size != write_to_files (rm, node->level, node->offset, data, size))    {      GNUNET_GE_LOG_STRERROR (ectx,                              GNUNET_GE_ERROR | GNUNET_GE_ADMIN |                              GNUNET_GE_USER | GNUNET_GE_BULK, "WRITE");      signal_abort (rm, _("IO error."));      return GNUNET_SYSERR;    }  notify_client_about_progress (node, data, size);  if (node->level > 0)    iblock_download_children (node, data, size);  GNUNET_free (data);  /* request satisfied, stop requesting! */  delete_node (node);  return GNUNET_OK;}/** * Helper function to sanitize filename * and create necessary directories. */static char *get_real_download_filename (struct GNUNET_GE_Context *ectx,                            const char *filename){  struct stat buf;  char *realFN;  char *path;  char *pos;  if ((filename[strlen (filename) - 1] == '/') ||      (filename[strlen (filename) - 1] == '\\'))    {      realFN =        GNUNET_malloc (strlen (filename) + strlen (GNUNET_DIRECTORY_EXT));      strcpy (realFN, filename);      realFN[strlen (filename) - 1] = '\0';      strcat (realFN, GNUNET_DIRECTORY_EXT);    }  else    {      realFN = GNUNET_strdup (filename);    }  path = GNUNET_malloc (strlen (realFN) * strlen (GNUNET_DIRECTORY_EXT) + 1);  strcpy (path, realFN);  pos = path;  while (*pos != '\0')    {      if (*pos == DIR_SEPARATOR)        {          *pos = '\0';          if ((0 == STAT (path, &buf)) && (!S_ISDIR (buf.st_mode)))            {              *pos = DIR_SEPARATOR;              memmove (pos + strlen (GNUNET_DIRECTORY_EXT),                       pos, strlen (pos));              memcpy (pos,                      GNUNET_DIRECTORY_EXT, strlen (GNUNET_DIRECTORY_EXT));              pos += strlen (GNUNET_DIRECTORY_EXT);            }          else            {              *pos = DIR_SEPARATOR;            }        }      pos++;    }  GNUNET_free (realFN);  return path;}/* ***************** main method **************** *//** * Download parts of a file.  Note that this will store * the blocks at the respective offset in the given file. * Also, the download is still using the blocking of the * underlying ECRS encoding.  As a result, the download * may *write* outside of the given boundaries (if offset * and length do not match the 32k ECRS block boundaries). * <p> * * This function should be used to focus a download towards a * particular portion of the file (optimization), not to strictly * limit the download to exactly those bytes. * * @param uri the URI of the file (determines what to download) * @param filename where to store the file * @param no_temporaries set to GNUNET_YES to disallow generation of temporary files * @param start starting offset * @param length length of the download (starting at offset) */struct GNUNET_ECRS_DownloadContext *GNUNET_ECRS_file_download_partial_start (struct GNUNET_GE_Context *ectx,                                         struct GNUNET_GC_Configuration *cfg,                                         struct GNUNET_FS_SearchContext *sc,                                         const struct GNUNET_ECRS_URI *uri,                                         const char *filename,                                         unsigned long long offset,                                         unsigned long long length,                                         unsigned int anonymityLevel,                                         int no_temporaries,                                         GNUNET_ECRS_DownloadProgressCallback                                         dpcb, void *dpcbClosure){  struct GNUNET_ECRS_DownloadContext *rm;  struct stat buf;  struct Node *top;  int ret;  if ((!GNUNET_ECRS_uri_test_chk (uri)) && (!GNUNET_ECRS_uri_test_loc (uri)))    {      GNUNET_GE_BREAK (ectx, 0);      return NULL;    }  rm = GNUNET_malloc (sizeof (struct GNUNET_ECRS_DownloadContext));  memset (rm, 0, sizeof (struct GNUNET_ECRS_DownloadContext));  if (sc == NULL)    {      rm->sctx = GNUNET_FS_create_search_context (ectx, cfg);      if (rm->sctx == NULL)        {          GNUNET_free (rm);          return NULL;        }      rm->my_sctx = GNUNET_YES;    }  else    {      rm->sctx = sc;      rm->my_sctx = GNUNET_NO;    }  rm->ectx = ectx;  rm->cfg = cfg;  rm->startTime = GNUNET_get_time ();  rm->anonymityLevel = anonymityLevel;  rm->offset = offset;  rm->length = length;  rm->dpcb = dpcb;  rm->dpcbClosure = dpcbClosure;  rm->main = GNUNET_thread_get_self ();  rm->total = GNUNET_ntohll (uri->data.fi.file_length);  rm->filename =    filename != NULL ? get_real_download_filename (ectx, filename) : NULL;  if ((rm->filename != NULL) &&      (GNUNET_SYSERR ==       GNUNET_disk_directory_create_for_file (ectx, rm->filename)))    {      free_request_manager (rm);      return NULL;    }  if (0 == rm->total)    {      if (rm->filename != NULL)        {          ret = GNUNET_disk_file_open (ectx,                                       rm->filename,                                       O_CREAT | O_WRONLY | O_TRUNC,                                       S_IRUSR | S_IWUSR);          if (ret == -1)            {              free_request_manager (rm);              return NULL;            }          CLOSE (ret);        }      dpcb (0, 0, rm->startTime, 0, NULL, 0, dpcbClosure);      free_request_manager (rm);      return NULL;    }  rm->treedepth = GNUNET_ECRS_compute_depth (rm->total);  if ((NULL != rm->filename) &&      ((0 == STAT (rm->filename, &buf))       && ((size_t) buf.st_size > rm->total)))    {      /* if exists and oversized, truncate */      if (truncate (rm->filename, rm->total) != 0)        {          GNUNET_GE_LOG_STRERROR_FILE (ectx,                                       GNUNET_GE_ERROR | GNUNET_GE_ADMIN |                                       GNUNET_GE_BULK, "truncate",                                       rm->filename);          free_request_manager (rm);          return NULL;        }    }  if (rm->filename != NULL)    {      rm->handle = GNUNET_disk_file_open (ectx,                                          rm->filename,                                          O_CREAT | O_RDWR,                                          S_IRUSR | S_IWUSR);      if (rm->handle < 0)        {          free_request_manager (rm);          return NULL;        }    }  else    rm->handle = -1;  if (GNUNET_ECRS_uri_test_loc (uri))    {      GNUNET_hash (&uri->data.loc.peer, sizeof (GNUNET_RSA_PublicKey),                   &rm->target.hashPubKey);      rm->have_target = GNUNET_YES;    }  top = GNUNET_malloc (sizeof (struct Node));  memset (top, 0, sizeof (struct Node));  top->ctx = rm;  top->chk = uri->data.fi.chk;  top->offset = 0;  top->level = rm->treedepth;  if (GNUNET_NO == check_node_present (top))    add_request (top);  else    GNUNET_free (top);  return rm;}intGNUNET_ECRS_file_download_partial_stop (struct GNUNET_ECRS_DownloadContext                                        *rm){  int ret;  ret = rm->abortFlag;  free_request_manager (rm);  if (ret == GNUNET_NO)    ret = GNUNET_OK;            /* normal termination */  return ret;}/** * Download parts of a file.  Note that this will store * the blocks at the respective offset in the given file. * Also, the download is still using the blocking of the * underlying ECRS encoding.  As a result, the download * may *write* outside of the given boundaries (if offset * and length do not match the 32k ECRS block boundaries). * <p> * * This function should be used to focus a download towards a * particular portion of the file (optimization), not to strictly * limit the download to exactly those bytes. * * @param uri the URI of the file (determines what to download) * @param filename where to store the file * @param no_temporaries set to GNUNET_YES to disallow generation of temporary files * @param start starting offset * @param length length of the download (starting at offset) */intGNUNET_ECRS_file_download_partial (struct GNUNET_GE_Context *ectx,                                   struct GNUNET_GC_Configuration *cfg,                                   const struct GNUNET_ECRS_URI *uri,                                   const char *filename,                                   unsigned long long offset,                                   unsigned long long length,                                   unsigned int anonymityLevel,                                   int no_temporaries,                                   GNUNET_ECRS_DownloadProgressCallback dpcb,                                   void *dpcbClosure,                                   GNUNET_ECRS_TestTerminate tt,                                   void *ttClosure){  struct GNUNET_ECRS_DownloadContext *rm;  int ret;  if (length == 0)    return GNUNET_OK;  rm = GNUNET_ECRS_file_download_partial_start (ectx,                                                cfg,                                                NULL,                                                uri,                                                filename,                                                offset,                                                length,                                                anonymityLevel,                                                no_temporaries,                                                dpcb, dpcbClosure);  if (rm == NULL)    return GNUNET_SYSERR;  while ((GNUNET_OK == tt (ttClosure)) &&         (GNUNET_YES != GNUNET_shutdown_test ()) &&         (rm->abortFlag == GNUNET_NO) && (rm->head != NULL))    GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS);  ret = GNUNET_ECRS_file_download_partial_stop (rm);  return ret;}/** * Download a file (simplified API). * * @param uri the URI of the file (determines what to download) * @param filename where to store the file */intGNUNET_ECRS_file_download (struct GNUNET_GE_Context *ectx,                           struct GNUNET_GC_Configuration *cfg,                           const struct GNUNET_ECRS_URI *uri,                           const char *filename,                           unsigned int anonymityLevel,                           GNUNET_ECRS_DownloadProgressCallback dpcb,                           void *dpcbClosure, GNUNET_ECRS_TestTerminate tt,                           void *ttClosure){  return GNUNET_ECRS_file_download_partial (ectx,                                            cfg,                                            uri,                                            filename,                                            0,                                            GNUNET_ECRS_uri_get_file_size                                            (uri), anonymityLevel, GNUNET_NO,                                            dpcb, dpcbClosure, tt, ttClosure);}/* end of download.c */

⌨️ 快捷键说明

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