-renaming gnunet-gns to gnunet-namestore
[oweals/gnunet.git] / src / namestore / namestore_common.c
index 7112303513ff2a359dd3701bd28f242b10c359a0..c1b5ddc1e0b776d6fd6e63e1ec89511bd81195a4 100644 (file)
 #include "platform.h"
 #include "gnunet_util_lib.h"
 #include "gnunet_constants.h"
+#include "gnunet_signatures.h"
 #include "gnunet_arm_service.h"
 #include "gnunet_namestore_service.h"
 #include "namestore.h"
 #define DEBUG_GNS_API GNUNET_EXTRA_LOGGING
 
 #define LOG(kind,...) GNUNET_log_from (kind, "gns-api",__VA_ARGS__)
+
+
+/**
+ * Internal format of a record in the serialized form.
+ */
+struct NetworkRecord
+{
+
+  /**
+   * Expiration time for the DNS record.
+   */
+  struct GNUNET_TIME_AbsoluteNBO expiration;
+
+  /**
+   * Number of bytes in 'data', network byte order.
+   */
+  uint32_t data_size;
+
+  /**
+   * Type of the GNS/DNS record, network byte order.
+   */
+  uint32_t record_type;
+
+  /**
+   * Flags for the record, network byte order.
+   */
+  uint32_t flags;
+  
+};
+
 /**
- * Serialize an array of GNUNET_NAMESTORE_RecordData *rd to transmit over the
- * network
+ * Calculate how many bytes we will need to serialize the given
+ * records.
  *
- * @param dest where to write the serialized data
- * @param rd_count number of elements in array
- * @param rd array
+ * @param rd_count number of records in the rd array
+ * @param rd array of GNUNET_NAMESTORE_RecordData with rd_count elements
+ *
+ * @return the required size to serialize
  *
- * @return number of bytes written to destination dest
  */
 size_t
-GNUNET_NAMESTORE_records_serialize (char ** dest,
-                             unsigned int rd_count,
-                             const struct GNUNET_NAMESTORE_RecordData *rd)
+GNUNET_NAMESTORE_records_get_size (unsigned int rd_count,
+                                  const struct GNUNET_NAMESTORE_RecordData *rd)
 {
-  //size_t len = 0;
-  struct GNUNET_NAMESTORE_NetworkRecord * nr;
-  char * d = (*dest);
-  int c = 0;
-  int offset;
-
-  GNUNET_assert (rd != NULL);
-
-  size_t total_len = rd_count * sizeof (struct GNUNET_NAMESTORE_NetworkRecord);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Struct size: %u\n", total_len);
+  unsigned int i;
+  size_t ret;
 
-  /* figure out total len required */
-  for (c = 0; c < rd_count; c ++)
+  ret = sizeof (struct NetworkRecord) * rd_count;
+  for (i=0;i<rd_count;i++)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data size record[%i] : %u\n", c, rd[c].data_size);
-    total_len += rd[c].data_size;
+    GNUNET_assert (ret + rd[i].data_size >= ret);
+    ret += rd[i].data_size;
   }
+  return ret;  
+}
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Serializing %i records with total length of %llu\n", rd_count, total_len);
-
-  (*dest) = GNUNET_malloc (total_len);
-  d = (*dest);
-
-  /* copy records */
-  offset = 0;
 
-  for (c = 0; c < rd_count; c ++)
+/**
+ * Serialize the given records to the given destination buffer.
+ *
+ * @param rd_count number of records in the rd array
+ * @param rd array of GNUNET_NAMESTORE_RecordData with rd_count elements
+ * @param dest_size size of the destination array
+ * @param dest where to write the result
+ *
+ * @return the size of serialized records
+ */
+ssize_t
+GNUNET_NAMESTORE_records_serialize (unsigned int rd_count,
+                                   const struct GNUNET_NAMESTORE_RecordData *rd,
+                                   size_t dest_size,
+                                   char *dest)
+{
+  struct NetworkRecord rec;
+  unsigned int i;
+  size_t off;
+  
+  off = 0;
+  for (i=0;i<rd_count;i++)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Serialized record [%i]: data_size %i\n", c,rd[c].data_size);
-
-    nr = (struct GNUNET_NAMESTORE_NetworkRecord *) &d[offset];
-    nr->data_size = htonl (rd[c].data_size);
-    nr->flags = htonl (rd[c].flags);
-    nr->record_type = htonl (rd[c].record_type);
-    nr->expiration = GNUNET_TIME_absolute_hton(rd[c].expiration);
-
-    /*put data here */
-    offset += sizeof (struct GNUNET_NAMESTORE_NetworkRecord);
-    memcpy (&d[offset], rd[c].data, rd[c].data_size);
-    offset += rd[c].data_size;
+    rec.expiration = GNUNET_TIME_absolute_hton (rd[i].expiration);
+    rec.data_size = htonl ((uint32_t) rd[i].data_size);
+    rec.record_type = htonl (rd[i].record_type);
+    rec.flags = htonl (rd[i].flags);
+    if (off + sizeof (rec) > dest_size)
+      return -1;
+    memcpy (&dest[off], &rec, sizeof (rec));
+    off += sizeof (rec);
+    if (off + rd[i].data_size > dest_size)
+      return -1;
+    memcpy (&dest[off], rd[i].data, rd[i].data_size);
+    off += rd[i].data_size;
   }
-
-  GNUNET_assert (offset == total_len);
-  return total_len;
+  return off;
 }
 
-void
-GNUNET_NAMESTORE_records_free (unsigned int rd_count, struct GNUNET_NAMESTORE_RecordData *rd)
+/**
+ * Compares if two records are equal
+ *
+ * @param a record
+ * @param b record
+ *
+ * @return GNUNET_YES or GNUNET_NO
+ */
+int
+GNUNET_NAMESTORE_records_cmp (const struct GNUNET_NAMESTORE_RecordData *a,
+                              const struct GNUNET_NAMESTORE_RecordData *b)
 {
-  int c;
-  if ((rd == NULL) || (rd_count == 0))
-    return;
-
-  for (c = 0; c < rd_count; c++)
-    GNUNET_free_non_null ((void *) rd[c].data);
-  GNUNET_free (rd);
+  if ((a->record_type == b->record_type) &&
+      (a->expiration.abs_value == b->expiration.abs_value) &&
+      (a->data_size == b->data_size) &&
+      (0 == memcmp (a->data, b->data, a->data_size)))
+    return GNUNET_YES;
+  else
+    return GNUNET_NO;
 }
 
 
 /**
- * Deserialize an array of GNUNET_NAMESTORE_RecordData *rd after transmission
- * over the network
+ * Deserialize the given records to the given destination.
  *
- * @param source where to read the data to deserialize
- * @param rd_count number of elements in array
- * @param rd array
+ * @param len size of the serialized record data
+ * @param src the serialized record data
+ * @param rd_count number of records in the rd array
+ * @param dest where to put the data
  *
- * @return number of elements deserialized
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error
  */
 int
-GNUNET_NAMESTORE_records_deserialize ( struct GNUNET_NAMESTORE_RecordData **dest, char *src, size_t len)
+GNUNET_NAMESTORE_records_deserialize (size_t len,
+                                     const char *src,
+                                     unsigned int rd_count,
+                                     struct GNUNET_NAMESTORE_RecordData *dest)
 {
-  struct GNUNET_NAMESTORE_NetworkRecord * nr;
-  struct GNUNET_NAMESTORE_RecordData *d = (*dest);
-  int elements;
-  size_t offset;
-  uint32_t data_size;
-  int c;
-
-  offset = 0;
-  elements = 0;
-  while (offset < len)
+  struct NetworkRecord rec;
+  unsigned int i;
+  size_t off;
+  
+  off = 0;
+  for (i=0;i<rd_count;i++)
   {
-    nr = (struct GNUNET_NAMESTORE_NetworkRecord *) &src[offset];
-    offset += sizeof (struct GNUNET_NAMESTORE_NetworkRecord);
+    if (off + sizeof (rec) > len)
+      return GNUNET_SYSERR;
+    memcpy (&rec, &src[off], sizeof (rec));
+    dest[i].expiration = GNUNET_TIME_absolute_ntoh (rec.expiration);
+    dest[i].data_size = ntohl ((uint32_t) rec.data_size);
+    dest[i].record_type = ntohl (rec.record_type);
+    dest[i].flags = ntohl (rec.flags);
+    off += sizeof (rec);
+
+    if (off + dest[i].data_size > len)
+      return GNUNET_SYSERR;
+    dest[i].data = &src[off];
+    off += dest[i].data_size;
+  }
+  return GNUNET_OK; 
+}
 
-    data_size = ntohl (nr->data_size);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Datasize record[%i]: %u\n", elements, data_size);
-    offset += data_size;
-    elements ++;
+/**
+ * Sign name and records
+ *
+ * @param key the private key
+ * @param name the name
+ * @param rd record data
+ * @param rd_count number of records
+ *
+ * @return the signature
+ */
+struct GNUNET_CRYPTO_RsaSignature *
+GNUNET_NAMESTORE_create_signature (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
+    const char *name,
+    struct GNUNET_NAMESTORE_RecordData *rd,
+    unsigned int rd_count)
+{
+  struct GNUNET_CRYPTO_RsaSignature *sig = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaSignature));
+  struct GNUNET_CRYPTO_RsaSignaturePurpose *sig_purpose;
+  size_t rd_ser_len;
+  size_t name_len;
+  char * name_tmp;
+  char * rd_tmp;
+  int res;
+
+  if (name == NULL)
+  {
+    GNUNET_break (0);
+    GNUNET_free (sig);
+    return NULL;
   }
+  name_len = strlen (name) + 1;
+
+  rd_ser_len = GNUNET_NAMESTORE_records_get_size(rd_count, rd);
+  char rd_ser[rd_ser_len];
+  GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
+
+  sig_purpose = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + rd_ser_len + name_len);
 
-  GNUNET_assert (len == offset);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deserializing %i records with total length of %u\n", elements, len);
+  sig_purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose)+ rd_ser_len + name_len);
+  sig_purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
+  name_tmp = (char *) &sig_purpose[1];
+  rd_tmp = &name_tmp[name_len];
+  memcpy (name_tmp, name, name_len);
+  memcpy (rd_tmp, rd_ser, rd_ser_len);
 
-  (*dest) = GNUNET_malloc (elements * sizeof (struct GNUNET_NAMESTORE_RecordData));
-  d = (*dest);
+  res = GNUNET_CRYPTO_rsa_sign (key, sig_purpose, sig);
 
-  offset = 0;
-  for (c = 0; c < elements; c++)
+  GNUNET_free (sig_purpose);
+
+  if (GNUNET_OK != res)
   {
-    nr = (struct GNUNET_NAMESTORE_NetworkRecord *) &src[offset];
-    d[c].expiration = GNUNET_TIME_absolute_ntoh(nr->expiration);
-    d[c].record_type = ntohl (nr->record_type);
-    d[c].flags = ntohl (nr->flags);
-    d[c].data_size = ntohl (nr->data_size);
-    if (d[c].data_size > 0)
-      d[c].data = GNUNET_malloc (d[c].data_size);
-    else
-      d[c].data = NULL;
-
-    offset += sizeof (struct GNUNET_NAMESTORE_NetworkRecord);
-    memcpy((char *) d[c].data, &src[offset], d[c].data_size);
-
-    offset += d[c].data_size;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deserialized record[%i] /w data_size %i\n", c, d[c].data_size);
+    GNUNET_break (0);
+    GNUNET_free (sig);
+    return NULL;
   }
-  GNUNET_assert(offset == len);
-
-  return elements;
+  return sig;
 }
 
 /* end of namestore_api.c */