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

📄 meta.c

📁 GNUnet是一个安全的点对点网络框架
💻 C
📖 第 1 页 / 共 2 页
字号:
/** * Decompress input, return the decompressed data * as output, set outputSize to the number of bytes * that were found. * * @return NULL on error */static char *decompress (const char *input,            unsigned int inputSize, unsigned int outputSize){  char *output;  uLongf olen;  olen = outputSize;  output = GNUNET_malloc (olen);  if (Z_OK == uncompress ((Bytef *) output,                          &olen, (const Bytef *) input, inputSize))    {      return output;    }  else    {      GNUNET_free (output);      return NULL;    }}/** * Flag in 'version' that indicates compressed meta-data. */#define HEADER_COMPRESSED 0x80000000/** * Bits in 'version' that give the version number. */#define HEADER_VERSION_MASK 0x7FFFFFFFtypedef struct{  /**   * The version of the MD serialization.   * The highest bit is used to indicate   * compression.   *   * Version 0 is the current version;   * Version is 1 for a NULL pointer.   * Other version numbers are not yet defined.   */  unsigned int version;  /**   * How many MD entries are there?   */  unsigned int entries;  /**   * Size of the MD (decompressed)   */  unsigned int size;  /**   * This is followed by 'entries' values of type 'unsigned int' that   * correspond to EXTRACTOR_KeywordTypes.  After that, the meta-data   * keywords follow (0-terminated).  The MD block always ends with   * 0-termination, padding with 0 until a multiple of 8 bytes.   */} MetaDataHeader;/** * Serialize meta-data to target. * * @param size maximum number of bytes available * @param part is it ok to just write SOME of the *        meta-data to match the size constraint, *        possibly discarding some data? GNUNET_YES/GNUNET_NO. * @return number of bytes written on success, *         GNUNET_SYSERR on error (typically: not enough *         space) */intGNUNET_meta_data_serialize (struct GNUNET_GE_Context *ectx,                            const MetaData * md,                            char *target, unsigned int max, int part){  MetaDataHeader *hdr;  size_t size;  size_t pos;  int i;  int len;  unsigned int ic;  if (max < sizeof (MetaDataHeader))    return GNUNET_SYSERR;       /* far too small */  ic = md ? md->itemCount : 0;  hdr = NULL;  while (1)    {      size = sizeof (MetaDataHeader);      size += sizeof (unsigned int) * ic;      for (i = 0; i < ic; i++)        size += 1 + strlen (md->items[i].data);      while (size % 8 != 0)        size++;      hdr = GNUNET_malloc (size);      hdr->version = htonl (md == NULL ? 1 : 0);      hdr->entries = htonl (ic);      for (i = 0; i < ic; i++)        ((unsigned int *) &hdr[1])[i] =          htonl ((unsigned int) md->items[i].type);      pos = sizeof (MetaDataHeader);      pos += sizeof (unsigned int) * ic;      for (i = 0; i < ic; i++)        {          len = strlen (md->items[i].data) + 1;          memcpy (&((char *) hdr)[pos], md->items[i].data, len);          pos += len;        }      hdr->size = htonl (size);      if ((part & GNUNET_SERIALIZE_NO_COMPRESS) == 0)        {          pos = tryCompression ((char *) &hdr[1],                                size - sizeof (MetaDataHeader));        }      else        {          pos = size - sizeof (MetaDataHeader);        }      if (pos < size - sizeof (MetaDataHeader))        {          hdr->version = htonl (HEADER_COMPRESSED);          size = pos + sizeof (MetaDataHeader);        }      if (size <= max)        break;      GNUNET_free (hdr);      hdr = NULL;      if ((part & GNUNET_SERIALIZE_PART) == 0)        {          return GNUNET_SYSERR; /* does not fit! */        }      /* partial serialization ok, try again with less meta-data */      if (size > 2 * max)        ic = ic * 2 / 3;        /* still far too big, make big reductions */      else        ic--;                   /* small steps, we're close */    }  GNUNET_GE_ASSERT (ectx, size <= max);  memcpy (target, hdr, size);  GNUNET_free (hdr);  /* extra check: deserialize! */#if EXTRA_CHECKS  {    MetaData *mdx;    mdx = GNUNET_meta_data_deserialize (ectx, target, size);    GNUNET_GE_ASSERT (ectx, NULL != mdx);    GNUNET_meta_data_destroy (mdx);  }#endif  return size;}/** * Estimate (!) the size of the meta-data in * serialized form.  The estimate MAY be higher * than what is strictly needed. */unsigned intGNUNET_meta_data_get_serialized_size (const MetaData * md, int part){  MetaDataHeader *hdr;  size_t size;  size_t pos;  int i;  int len;  unsigned int ic;  ic = md ? md->itemCount : 0;  size = sizeof (MetaDataHeader);  size += sizeof (unsigned int) * ic;  for (i = 0; i < ic; i++)    size += 1 + strlen (md->items[i].data);  while (size % 8 != 0)    size++;  hdr = GNUNET_malloc (size);  hdr->version = htonl (md == NULL ? 1 : 0);  hdr->entries = htonl (ic);  for (i = 0; i < ic; i++)    ((unsigned int *) &hdr[1])[i] = htonl ((unsigned int) md->items[i].type);  pos = sizeof (MetaDataHeader);  pos += sizeof (unsigned int) * ic;  for (i = 0; i < ic; i++)    {      len = strlen (md->items[i].data) + 1;      memcpy (&((char *) hdr)[pos], md->items[i].data, len);      pos += len;    }  if ((part & GNUNET_SERIALIZE_NO_COMPRESS) == 0)    {      pos = tryCompression ((char *) &hdr[1], size - sizeof (MetaDataHeader));    }  else    {      pos = size - sizeof (MetaDataHeader);    }  if (pos < size - sizeof (MetaDataHeader))    size = pos + sizeof (MetaDataHeader);  GNUNET_free (hdr);  return size;}/** * Deserialize meta-data.  Initializes md. * @param size number of bytes available * @return MD on success, NULL on error (i.e. *         bad format) */struct GNUNET_MetaData *GNUNET_meta_data_deserialize (struct GNUNET_GE_Context *ectx,                              const char *input, unsigned int size){  MetaData *md;  const MetaDataHeader *hdr;  unsigned int ic;  char *data;  unsigned int dataSize;  int compressed;  int i;  unsigned int pos;  int len;  unsigned int version;  if (size < sizeof (MetaDataHeader))    return NULL;  hdr = (const MetaDataHeader *) input;  version = ntohl (MAKE_UNALIGNED (hdr->version)) & HEADER_VERSION_MASK;  if (version == 1)    return NULL; /* null pointer */  if (version != 0)    {      GNUNET_GE_BREAK_OP(NULL, 0); /* unsupported version */      return NULL;     }  ic = ntohl (MAKE_UNALIGNED (hdr->entries));  compressed =    (ntohl (MAKE_UNALIGNED (hdr->version)) & HEADER_COMPRESSED) != 0;  if (compressed)    {      dataSize = ntohl (MAKE_UNALIGNED (hdr->size)) - sizeof (MetaDataHeader);      if (dataSize > 2 * 1042 * 1024)        {          GNUNET_GE_BREAK (ectx, 0);          return NULL;          /* only 2 MB allowed [to make sure we don't blow                                   our memory limit because of a mal-formed                                   message... ] */        }      data = decompress ((char *) &input[sizeof (MetaDataHeader)],                         size - sizeof (MetaDataHeader), dataSize);      if (data == NULL)        {          GNUNET_GE_BREAK (ectx, 0);          return NULL;        }    }  else    {      data = (char *) &hdr[1];      dataSize = size - sizeof (MetaDataHeader);      if (size != ntohl (MAKE_UNALIGNED (hdr->size)))        {          GNUNET_GE_BREAK (ectx, 0);          return NULL;        }    }  if ((sizeof (unsigned int) * ic + ic) > dataSize)    {      GNUNET_GE_BREAK (ectx, 0);      goto FAILURE;    }  if ((ic > 0) && (data[dataSize - 1] != '\0'))    {      GNUNET_GE_BREAK (ectx, 0);      goto FAILURE;    }  md = GNUNET_meta_data_create ();  GNUNET_array_grow (md->items, md->itemCount, ic);  i = 0;  pos = sizeof (unsigned int) * ic;  while ((pos < dataSize) && (i < ic))    {      len = strlen (&data[pos]) + 1;      md->items[i].type = (EXTRACTOR_KeywordType)        ntohl (MAKE_UNALIGNED (((unsigned int *) data)[i]));      md->items[i].data = GNUNET_strdup (&data[pos]);      pos += len;      i++;    }  if (i < ic)    {                           /* oops */      GNUNET_meta_data_destroy (md);      goto FAILURE;    }  if (compressed)    GNUNET_free (data);  return md;FAILURE:  if (compressed)    GNUNET_free (data);  return NULL;                  /* size too small */}/** * Test if two MDs are equal. */intGNUNET_meta_data_test_equal (const struct GNUNET_MetaData *md1,                             const struct GNUNET_MetaData *md2){  int i;  int j;  int found;  if (md1->itemCount != md2->itemCount)    return GNUNET_NO;  for (i = 0; i < md1->itemCount; i++)    {      found = GNUNET_NO;      for (j = 0; j < md2->itemCount; j++)        if ((md1->items[i].type == md2->items[j].type) &&            (0 == strcmp (md1->items[i].data, md2->items[j].data)))          found = GNUNET_YES;      if (found == GNUNET_NO)        return GNUNET_NO;    }  return GNUNET_YES;}/* end of meta.c */

⌨️ 快捷键说明

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