- interactive option to disable waiting on keystroke but wait instead for termination...
[oweals/gnunet.git] / src / gnsrecord / gnsrecord_serialization.c
1 /*
2      This file is part of GNUnet.
3      (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., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, 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     LOG (GNUNET_ERROR_TYPE_DEBUG,
123          "Serializing record %u with flags %d and expiration time %llu\n",
124          i,
125          rd[i].flags,
126          (unsigned long long) rd[i].expiration_time);
127     rec.expiration_time = GNUNET_htonll (rd[i].expiration_time);
128     rec.data_size = htonl ((uint32_t) rd[i].data_size);
129     rec.record_type = htonl (rd[i].record_type);
130     rec.flags = htonl (rd[i].flags);
131     if (off + sizeof (rec) > dest_size)
132       return -1;
133     memcpy (&dest[off], &rec, sizeof (rec));
134     off += sizeof (rec);
135     if (off + rd[i].data_size > dest_size)
136       return -1;
137     memcpy (&dest[off], rd[i].data, rd[i].data_size);
138     off += rd[i].data_size;
139   }
140   return off;
141 }
142
143
144 /**
145  * Deserialize the given records to the given destination.
146  *
147  * @param len size of the serialized record data
148  * @param src the serialized record data
149  * @param rd_count number of records in the rd array
150  * @param dest where to put the data
151  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
152  */
153 int
154 GNUNET_GNSRECORD_records_deserialize (size_t len,
155                                       const char *src,
156                                       unsigned int rd_count,
157                                       struct GNUNET_GNSRECORD_Data *dest)
158 {
159   struct NetworkRecord rec;
160   unsigned int i;
161   size_t off;
162
163   off = 0;
164   for (i=0;i<rd_count;i++)
165   {
166     if (off + sizeof (rec) > len)
167       return GNUNET_SYSERR;
168     memcpy (&rec, &src[off], sizeof (rec));
169     dest[i].expiration_time = GNUNET_ntohll (rec.expiration_time);
170     dest[i].data_size = ntohl ((uint32_t) rec.data_size);
171     dest[i].record_type = ntohl (rec.record_type);
172     dest[i].flags = ntohl (rec.flags);
173     off += sizeof (rec);
174     if (off + dest[i].data_size > len)
175       return GNUNET_SYSERR;
176     dest[i].data = &src[off];
177     off += dest[i].data_size;
178     LOG (GNUNET_ERROR_TYPE_DEBUG,
179          "Deserialized record %u with flags %d and expiration time %llu\n",
180          i,
181          dest[i].flags,
182          (unsigned long long) dest[i].expiration_time);
183   }
184   return GNUNET_OK;
185 }
186
187
188 /* end of gnsrecord_serialization.c */