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

📄 deserialize.c

📁 GNUnet是一个安全的点对点网络框架
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
     This file is part of GNUnet.
     (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008 Christian Grothoff (and other contributing authors)

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

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

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


/**
 * @file applications/fs/fsui/deserializer.c
 * @brief FSUI functions for reading state from disk
 * @author Christian Grothoff
 * @see serializer.c
 */

#include "platform.h"
#include "gnunet_fsui_lib.h"
#include "gnunet_directories.h"
#include "fsui.h"

typedef struct
{
  int fd;
  unsigned int have;
  unsigned int size;
  unsigned int pos;
  char *buffer;
} ReadBuffer;

static int
read_buffered (ReadBuffer * rb, void *d, unsigned int size)
{
  char *dst = d;
  unsigned int min;
  unsigned int pos;
  int ret;

  if (rb->fd == -1)
    return -1;
  pos = 0;
  do
    {
      /* first, use buffer */
      min = rb->have - rb->pos;
      if (min > 0)
        {
          if (min > size - pos)
            min = size - pos;
          memcpy (&dst[pos], &rb->buffer[rb->pos], min);
          rb->pos += min;
          pos += min;
        }
      if (pos == size)
        return pos;             /* done! */
      GNUNET_GE_ASSERT (NULL, rb->have == rb->pos);
      /* fill buffer */
      ret = READ (rb->fd, rb->buffer, rb->size);
      if (ret == -1)
        {
          CLOSE (rb->fd);
          rb->fd = -1;
          return -1;
        }
      if (ret == 0)
        return 0;
      rb->pos = 0;
      rb->have = ret;
    }
  while (pos < size);           /* should always be true */
  return pos;
}


static int
read_int (ReadBuffer * rb, int *val)
{
  int big;

  if (sizeof (int) != read_buffered (rb, &big, sizeof (int)))
    return GNUNET_SYSERR;
  *val = ntohl (big);
  return GNUNET_OK;
}

static unsigned int
read_uint (ReadBuffer * rb, unsigned int *val)
{
  unsigned int big;

  if (sizeof (unsigned int) !=
      read_buffered (rb, &big, sizeof (unsigned int)))
    return GNUNET_SYSERR;
  *val = ntohl (big);
  return GNUNET_OK;
}

#define READINT(a) if (GNUNET_OK != read_int(rb, (int*) &a)) return GNUNET_SYSERR;

static int
read_long (ReadBuffer * rb, long long *val)
{
  long long big;

  if (sizeof (long long) != read_buffered (rb, &big, sizeof (long long)))
    return GNUNET_SYSERR;
  *val = GNUNET_ntohll (big);
  return GNUNET_OK;
}

#define READLONG(a) if (GNUNET_OK != read_long(rb, (long long*) &a)) return GNUNET_SYSERR;

static struct GNUNET_ECRS_URI *
read_uri (struct GNUNET_GE_Context *ectx, ReadBuffer * rb)
{
  char *buf;
  struct GNUNET_ECRS_URI *ret;
  unsigned int size;

  if (GNUNET_OK != read_uint (rb, &size))
    return NULL;
  buf = GNUNET_malloc (size + 1);
  buf[size] = '\0';
  if (size != read_buffered (rb, buf, size))
    {
      GNUNET_free (buf);
      return NULL;
    }
  ret = GNUNET_ECRS_string_to_uri (ectx, buf);
  GNUNET_GE_BREAK (ectx, ret != NULL);
  GNUNET_free (buf);
  return ret;
}

#define READURI(u) if (NULL == (u = read_uri(ectx, rb))) return GNUNET_SYSERR;

static char *
read_string (ReadBuffer * rb, unsigned int maxLen)
{
  char *buf;
  unsigned int big;

  if (GNUNET_OK != read_uint (rb, &big))
    return NULL;
  if (big > maxLen)
    return NULL;
  buf = GNUNET_malloc (big + 1);
  buf[big] = '\0';
  if (big != read_buffered (rb, buf, big))
    {
      GNUNET_free (buf);
      return NULL;
    }
  return buf;
}

#define READSTRING(c, max) if (NULL == (c = read_string(rb, max))) return GNUNET_SYSERR;

static void
fixState (GNUNET_FSUI_State * state)
{
  switch (*state)
    {                           /* try to correct errors */
    case GNUNET_FSUI_ACTIVE:
      *state = GNUNET_FSUI_PENDING;
      break;
    case GNUNET_FSUI_PENDING:
    case GNUNET_FSUI_COMPLETED_JOINED:
    case GNUNET_FSUI_ABORTED_JOINED:
    case GNUNET_FSUI_ERROR_JOINED:
      break;
    case GNUNET_FSUI_ERROR:
      *state = GNUNET_FSUI_ERROR_JOINED;
      break;
    case GNUNET_FSUI_ABORTED:
      *state = GNUNET_FSUI_ABORTED_JOINED;
      break;
    case GNUNET_FSUI_COMPLETED:
      *state = GNUNET_FSUI_COMPLETED_JOINED;
      break;
    default:
      *state = GNUNET_FSUI_ERROR_JOINED;
      break;
    }
}


/**
 * Read file info from file.
 *
 * @return GNUNET_OK on success, GNUNET_SYSERR on error
 */
static struct GNUNET_MetaData *
read_meta (struct GNUNET_GE_Context *ectx, ReadBuffer * rb)
{
  unsigned int size;
  char *buf;
  struct GNUNET_MetaData *meta;

  if (read_uint (rb, &size) != GNUNET_OK)
    {
      GNUNET_GE_BREAK (ectx, 0);
      return NULL;
    }
  if (size > 1024 * 1024)
    {
      GNUNET_GE_BREAK (ectx, 0);
      return NULL;
    }
  buf = GNUNET_malloc (size);
  if (size != read_buffered (rb, buf, size))
    {
      GNUNET_free (buf);
      GNUNET_GE_BREAK (ectx, 0);
      return NULL;
    }
  meta = GNUNET_meta_data_deserialize (ectx, buf, size);
  if (meta == NULL)
    {
      GNUNET_free (buf);
      GNUNET_GE_BREAK (ectx, 0);
      return NULL;
    }
  GNUNET_free (buf);
  return meta;
}

/**
 * Read file info from file.
 *
 * @return GNUNET_OK on success, GNUNET_SYSERR on error
 */
static int
readFileInfo (struct GNUNET_GE_Context *ectx, ReadBuffer * rb,
              GNUNET_ECRS_FileInfo * fi)
{
  fi->meta = read_meta (ectx, rb);
  if (fi->meta == NULL)
    {
      GNUNET_GE_BREAK (ectx, 0);
      return GNUNET_SYSERR;
    }
  fi->uri = NULL;

  fi->uri = read_uri (ectx, rb);
  if (fi->uri == NULL)
    {
      GNUNET_meta_data_destroy (fi->meta);
      fi->meta = NULL;
      GNUNET_GE_BREAK (ectx, 0);
      return GNUNET_SYSERR;
    }
  return GNUNET_OK;
}

/**
 * (Recursively) read a download list from the given fd.  The returned
 * pointer is expected to be integrated into the tree either as a next
 * or child pointer such that the given parent becomes the parent of the
 * returned node.
 *
 * @return NULL on error AND on read of empty
 *  list (these two cannot be distinguished)
 */
static GNUNET_FSUI_DownloadList *
readDownloadList (struct GNUNET_GE_Context *ectx,
                  ReadBuffer * rb, GNUNET_FSUI_Context * ctx,
                  GNUNET_FSUI_DownloadList * parent)
{
  GNUNET_FSUI_DownloadList *ret;
  GNUNET_FSUI_SearchList *pos;
  unsigned int big;
  int i;
  int ok;
  int soff;

  GNUNET_GE_ASSERT (ectx, ctx != NULL);
  if ((GNUNET_OK != read_uint (rb, &big)) || (big == 0))
    return NULL;
  ret = GNUNET_malloc (sizeof (GNUNET_FSUI_DownloadList));
  memset (ret, 0, sizeof (GNUNET_FSUI_DownloadList));
  ret->ctx = ctx;
  if ((GNUNET_OK != read_int (rb, &soff)) ||
      (GNUNET_OK != read_int (rb, (int *) &ret->state)) ||
      (GNUNET_OK != read_int (rb, &ret->is_recursive)) ||
      (GNUNET_OK != read_int (rb, &ret->is_directory)) ||
      (GNUNET_OK != read_uint (rb, &ret->anonymityLevel)) ||
      (GNUNET_OK != read_uint (rb, &ret->completedDownloadsCount)) ||
      (GNUNET_OK != read_long (rb, (long long *) &ret->total)) ||
      (GNUNET_OK != read_long (rb, (long long *) &ret->completed)) ||
      (GNUNET_OK != read_long (rb, (long long *) &ret->runTime)) ||
      (GNUNET_OK != read_uint (rb, &big)) || (big > 1024 * 1024))
    {
      GNUNET_GE_BREAK (NULL, 0);
      GNUNET_free (ret);
      return NULL;
    }
  ret->lastProgressTime = GNUNET_get_time();
  ret->progressBits = 1;
  fixState (&ret->state);
  ret->filename = GNUNET_malloc (big + 1);
  ret->filename[big] = '\0';
  if (big != read_buffered (rb, ret->filename, big))
    {
      GNUNET_GE_BREAK (ectx, 0);
      GNUNET_free (ret->filename);
      GNUNET_free (ret);
      return NULL;
    }
  if (GNUNET_OK != readFileInfo (ectx, rb, &ret->fi))
    {
      GNUNET_GE_BREAK (NULL, 0);
      GNUNET_free (ret->filename);
      GNUNET_free (ret);
      return NULL;
    }
  if (ret->completedDownloadsCount > 0)
    ret->completedDownloads
      =
      GNUNET_malloc (sizeof (struct GNUNET_ECRS_URI *) *
                     ret->completedDownloadsCount);
  ok = GNUNET_YES;
  for (i = 0; i < ret->completedDownloadsCount; i++)
    {
      ret->completedDownloads[i] = read_uri (ectx, rb);
      if (ret->completedDownloads[i] == NULL)
        {
          GNUNET_GE_BREAK (NULL, 0);
          ok = GNUNET_NO;
        }
    }
  if (GNUNET_NO == ok)
    {
      GNUNET_free (ret->filename);
      GNUNET_ECRS_uri_destroy (ret->fi.uri);
      GNUNET_meta_data_destroy (ret->fi.meta);
      for (i = 0; i < ret->completedDownloadsCount; i++)
        {
          if (ret->completedDownloads[i] != NULL)
            GNUNET_ECRS_uri_destroy (ret->completedDownloads[i]);
        }
      GNUNET_free (ret->completedDownloads);
      GNUNET_free (ret);
      GNUNET_GE_BREAK (NULL, 0);
      return NULL;
    }
  ret->parent = parent;
  if (soff == 0)
    {
      ret->search = NULL;
    }
  else
    {
      pos = ctx->activeSearches;
      while (--soff > 0)
        {
          if (pos == NULL)
            {
              GNUNET_GE_BREAK (NULL, 0);
              break;
            }
          pos = pos->next;
        }
      ret->search = pos;
      if (pos != NULL)
        {
          GNUNET_array_grow (pos->my_downloads,
                             pos->my_downloads_size,
                             pos->my_downloads_size + 1);
          pos->my_downloads[pos->my_downloads_size - 1] = ret;
        }
    }
  ret->next = readDownloadList (ectx, rb, ctx, parent);
  ret->child = readDownloadList (ectx, rb, ctx, ret);
#if DEBUG_PERSISTENCE
  GNUNET_GE_LOG (ectx,
                 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
                 "FSUI persistence: restoring download `%s': (%llu, %llu)\n",
                 ret->filename, ret->completed, ret->total);
#endif
  return ret;
}

static int
checkMagic (ReadBuffer * rb)
{
  char magic[8];

  if (8 != read_buffered (rb, magic, 8))
    {
      GNUNET_GE_BREAK (NULL, 0);
      return GNUNET_SYSERR;
    }
  if (0 != memcmp (magic, "FSUI03\n\0", 8))
    {
      GNUNET_GE_BREAK (NULL, 0);
      return GNUNET_SYSERR;
    }
  return GNUNET_OK;
}

static int
readCollection (ReadBuffer * rb, struct GNUNET_FSUI_Context *ctx)
{
  int big;

  /* deserialize collection data */
  READINT (big);
  if (big == 0)
    {
      ctx->collectionData = NULL;
      return GNUNET_OK;
    }
  if ((big > 16 * 1024 * 1024) || (big < sizeof (unsigned int)))
    {
      GNUNET_GE_BREAK (NULL, 0);
      return GNUNET_SYSERR;
    }
  ctx->collectionDataSize = big;
  ctx->collectionData = GNUNET_malloc (big);
  if (big != read_buffered (rb, ctx->collectionData, big))
    {
      GNUNET_free (ctx->collectionData);
      ctx->collectionData = NULL;
      ctx->collectionDataSize = 0;
      GNUNET_GE_BREAK (NULL, 0);
      return GNUNET_SYSERR;
    }
  return GNUNET_OK;
}

/**
 * Read in information about the individual ECRS searches
 * that we are performing.
 */
struct SearchRecordList *
read_search_record_list (struct GNUNET_GE_Context *ectx, ReadBuffer * rb)
{
  unsigned int is_required;
  GNUNET_HashCode key;
  struct GNUNET_ECRS_URI *uri;
  struct SearchRecordList *ret;
  struct SearchRecordList *head;
  struct SearchRecordList *tail;

  ret = NULL;
  head = NULL;
  tail = NULL;
  while (1)
    {
      if (GNUNET_OK != read_uint (rb, &is_required))
        break;
      if (is_required == -1)
        break;                  /* end of list marker */
      if (sizeof (GNUNET_HashCode)
          != read_buffered (rb, &key, sizeof (GNUNET_HashCode)))
        break;

⌨️ 快捷键说明

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