fix #3869: outdated FSF address
[oweals/gnunet.git] / src / gnsrecord / gnsrecord_serialization.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009-2013 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20
21 /**
22  * @file gnsrecord/gnsrecord_serialization.c
23  * @brief API to serialize and deserialize GNS records
24  * @author Martin Schanzenbach
25  * @author Matthias Wachs
26  * @author Christian Grothoff
27  */
28 #include "platform.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet_constants.h"
31 #include "gnunet_signatures.h"
32 #include "gnunet_arm_service.h"
33 #include "gnunet_gnsrecord_lib.h"
34 #include "gnunet_dnsparser_lib.h"
35 #include "gnunet_tun_lib.h"
36
37
38 #define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__)
39
40 GNUNET_NETWORK_STRUCT_BEGIN
41
42
43 /**
44  * Internal format of a record in the serialized form.
45  */
46 struct NetworkRecord
47 {
48
49   /**
50    * Expiration time for the DNS record; relative or absolute depends
51    * on 'flags', network byte order.
52    */
53   uint64_t expiration_time GNUNET_PACKED;
54
55   /**
56    * Number of bytes in 'data', network byte order.
57    */
58   uint32_t data_size GNUNET_PACKED;
59
60   /**
61    * Type of the GNS/DNS record, network byte order.
62    */
63   uint32_t record_type GNUNET_PACKED;
64
65   /**
66    * Flags for the record, network byte order.
67    */
68   uint32_t flags GNUNET_PACKED;
69
70 };
71
72 GNUNET_NETWORK_STRUCT_END
73
74
75 /**
76  * Calculate how many bytes we will need to serialize the given
77  * records.
78  *
79  * @param rd_count number of records in the rd array
80  * @param rd array of #GNUNET_GNSRECORD_Data with @a rd_count elements
81  * @return the required size to serialize
82  */
83 size_t
84 GNUNET_GNSRECORD_records_get_size (unsigned int rd_count,
85                                    const struct GNUNET_GNSRECORD_Data *rd)
86 {
87   unsigned int i;
88   size_t ret;
89
90   ret = sizeof (struct NetworkRecord) * rd_count;
91   for (i=0;i<rd_count;i++)
92   {
93     GNUNET_assert ((ret + rd[i].data_size) >= ret);
94     ret += rd[i].data_size;
95   }
96   return ret;
97 }
98
99
100 /**
101  * Serialize the given records to the given destination buffer.
102  *
103  * @param rd_count number of records in the rd array
104  * @param rd array of #GNUNET_GNSRECORD_Data with @a rd_count elements
105  * @param dest_size size of the destination array
106  * @param dest where to write the result
107  * @return the size of serialized records, -1 if records do not fit
108  */
109 ssize_t
110 GNUNET_GNSRECORD_records_serialize (unsigned int rd_count,
111                                     const struct GNUNET_GNSRECORD_Data *rd,
112                                     size_t dest_size,
113                                     char *dest)
114 {
115   struct NetworkRecord rec;
116   unsigned int i;
117   size_t off;
118
119   off = 0;
120   for (i=0;i<rd_count;i++)
121   {
122 #if 0
123     LOG (GNUNET_ERROR_TYPE_DEBUG,
124          "Serializing record %u with flags %d and expiration time %llu\n",
125          i,
126          rd[i].flags,
127          (unsigned long long) rd[i].expiration_time);
128 #endif
129     rec.expiration_time = GNUNET_htonll (rd[i].expiration_time);
130     rec.data_size = htonl ((uint32_t) rd[i].data_size);
131     rec.record_type = htonl (rd[i].record_type);
132     rec.flags = htonl (rd[i].flags);
133     if (off + sizeof (rec) > dest_size)
134       return -1;
135     memcpy (&dest[off], &rec, sizeof (rec));
136     off += sizeof (rec);
137     if (off + rd[i].data_size > dest_size)
138       return -1;
139     memcpy (&dest[off], rd[i].data, rd[i].data_size);
140     off += rd[i].data_size;
141   }
142   return off;
143 }
144
145
146 /**
147  * Deserialize the given records to the given destination.
148  *
149  * @param len size of the serialized record data
150  * @param src the serialized record data
151  * @param rd_count number of records in the rd array
152  * @param dest where to put the data
153  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
154  */
155 int
156 GNUNET_GNSRECORD_records_deserialize (size_t len,
157                                       const char *src,
158                                       unsigned int rd_count,
159                                       struct GNUNET_GNSRECORD_Data *dest)
160 {
161   struct NetworkRecord rec;
162   unsigned int i;
163   size_t off;
164
165   off = 0;
166   for (i=0;i<rd_count;i++)
167   {
168     if (off + sizeof (rec) > len)
169       return GNUNET_SYSERR;
170     memcpy (&rec, &src[off], sizeof (rec));
171     dest[i].expiration_time = GNUNET_ntohll (rec.expiration_time);
172     dest[i].data_size = ntohl ((uint32_t) rec.data_size);
173     dest[i].record_type = ntohl (rec.record_type);
174     dest[i].flags = ntohl (rec.flags);
175     off += sizeof (rec);
176     if (off + dest[i].data_size > len)
177       return GNUNET_SYSERR;
178     dest[i].data = &src[off];
179     off += dest[i].data_size;
180 #if 0
181     LOG (GNUNET_ERROR_TYPE_DEBUG,
182          "Deserialized record %u with flags %d and expiration time %llu\n",
183          i,
184          dest[i].flags,
185          (unsigned long long) dest[i].expiration_time);
186 #endif
187   }
188   return GNUNET_OK;
189 }
190
191
192 /* end of gnsrecord_serialization.c */