-fix format warning
[oweals/gnunet.git] / src / peerstore / peerstore_common.c
1 /*
2       This file is part of GNUnet
3       Copyright (C) 2012-2013 GNUnet e.V.
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  * @file peerstore/peerstore_common.c
22  * @brief Helper peerstore functions
23  * @author Omar Tarabai
24  */
25
26 #include "peerstore_common.h"
27
28 /**
29  * Creates a hash of the given key combination
30  *
31  */
32 void
33 PEERSTORE_hash_key (const char *sub_system,
34                     const struct GNUNET_PeerIdentity *peer, const char *key,
35                     struct GNUNET_HashCode *ret)
36 {
37   size_t sssize;
38   size_t psize;
39   size_t ksize;
40   size_t totalsize;
41   void *block;
42   void *blockptr;
43
44   sssize = strlen (sub_system) + 1;
45   psize = sizeof (struct GNUNET_PeerIdentity);
46   ksize = strlen (key) + 1;
47   totalsize = sssize + psize + ksize;
48   block = GNUNET_malloc (totalsize);
49   blockptr = block;
50   memcpy (blockptr, sub_system, sssize);
51   blockptr += sssize;
52   memcpy (blockptr, peer, psize);
53   blockptr += psize;
54   memcpy (blockptr, key, ksize);
55   GNUNET_CRYPTO_hash (block, totalsize, ret);
56   GNUNET_free (block);
57 }
58
59
60 /**
61  * Creates a record message ready to be sent
62  *
63  * @param sub_system sub system string
64  * @param peer Peer identity (can be NULL)
65  * @param key record key string (can be NULL)
66  * @param value record value BLOB (can be NULL)
67  * @param value_size record value size in bytes (set to 0 if value is NULL)
68  * @param expiry absolute time after which the record expires
69  * @param msg_type message type to be set in header
70  * @return pointer to record message struct
71  */
72 struct StoreRecordMessage *
73 PEERSTORE_create_record_message (const char *sub_system,
74                                  const struct GNUNET_PeerIdentity *peer,
75                                  const char *key, const void *value,
76                                  size_t value_size,
77                                  struct GNUNET_TIME_Absolute *expiry,
78                                  uint16_t msg_type)
79 {
80   struct StoreRecordMessage *srm;
81   size_t ss_size;
82   size_t key_size;
83   size_t request_size;
84   void *dummy;
85
86   ss_size = strlen (sub_system) + 1;
87   if (NULL == key)
88     key_size = 0;
89   else
90     key_size = strlen (key) + 1;
91   request_size =
92       sizeof (struct StoreRecordMessage) + ss_size + key_size + value_size;
93   srm = GNUNET_malloc (request_size);
94   srm->header.size = htons (request_size);
95   srm->header.type = htons (msg_type);
96   srm->key_size = htons (key_size);
97   if (NULL != expiry)
98     srm->expiry = *expiry;
99   if (NULL == peer)
100     srm->peer_set = htons (GNUNET_NO);
101   else
102   {
103     srm->peer_set = htons (GNUNET_YES);
104     srm->peer = *peer;
105   }
106   srm->sub_system_size = htons (ss_size);
107   srm->value_size = htons (value_size);
108   dummy = &srm[1];
109   memcpy (dummy, sub_system, ss_size);
110   dummy += ss_size;
111   memcpy (dummy, key, key_size);
112   dummy += key_size;
113   memcpy (dummy, value, value_size);
114   return srm;
115 }
116
117
118 /**
119  * Creates a MQ envelope for a single record
120  *
121  * @param sub_system sub system string
122  * @param peer Peer identity (can be NULL)
123  * @param key record key string (can be NULL)
124  * @param value record value BLOB (can be NULL)
125  * @param value_size record value size in bytes (set to 0 if value is NULL)
126  * @param expiry time after which the record expires
127  * @param options options specific to the storage operation
128  * @param msg_type message type to be set in header
129  * @return pointer to record message struct
130  */
131 struct GNUNET_MQ_Envelope *
132 PEERSTORE_create_record_mq_envelope (const char *sub_system,
133                                      const struct GNUNET_PeerIdentity *peer,
134                                      const char *key, const void *value,
135                                      size_t value_size,
136                                      struct GNUNET_TIME_Absolute *expiry,
137                                      enum GNUNET_PEERSTORE_StoreOption options,
138                                      uint16_t msg_type)
139 {
140   struct StoreRecordMessage *srm;
141   struct GNUNET_MQ_Envelope *ev;
142   size_t ss_size;
143   size_t key_size;
144   size_t msg_size;
145   void *dummy;
146
147   GNUNET_assert (NULL != sub_system);
148   ss_size = strlen (sub_system) + 1;
149   if (NULL == key)
150     key_size = 0;
151   else
152     key_size = strlen (key) + 1;
153   msg_size = ss_size + key_size + value_size;
154   ev = GNUNET_MQ_msg_extra (srm, msg_size, msg_type);
155   srm->key_size = htons (key_size);
156   if (NULL != expiry)
157     srm->expiry = *expiry;
158   if (NULL == peer)
159     srm->peer_set = htons (GNUNET_NO);
160   else
161   {
162     srm->peer_set = htons (GNUNET_YES);
163     srm->peer = *peer;
164   }
165   srm->sub_system_size = htons (ss_size);
166   srm->value_size = htons (value_size);
167   srm->options = htonl (options);
168   dummy = &srm[1];
169   memcpy (dummy, sub_system, ss_size);
170   dummy += ss_size;
171   memcpy (dummy, key, key_size);
172   dummy += key_size;
173   memcpy (dummy, value, value_size);
174   return ev;
175 }
176
177
178 /**
179  * Parses a message carrying a record
180  *
181  * @param message the actual message
182  * @return Pointer to record or NULL if error
183  */
184 struct GNUNET_PEERSTORE_Record *
185 PEERSTORE_parse_record_message (const struct GNUNET_MessageHeader *message)
186 {
187   struct StoreRecordMessage *srm;
188   struct GNUNET_PEERSTORE_Record *record;
189   uint16_t req_size;
190   uint16_t ss_size;
191   uint16_t key_size;
192   uint16_t value_size;
193   char *dummy;
194
195   req_size = ntohs (message->size);
196   if (req_size < sizeof (struct StoreRecordMessage))
197   {
198     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
199                 "Received message with invalid size: (%d < %d).\n",
200                 (int) req_size,
201                 (int) sizeof (struct StoreRecordMessage));
202     return NULL;
203   }
204   srm = (struct StoreRecordMessage *) message;
205   ss_size = ntohs (srm->sub_system_size);
206   key_size = ntohs (srm->key_size);
207   value_size = ntohs (srm->value_size);
208   if (ss_size + key_size + value_size + sizeof (struct StoreRecordMessage) !=
209       req_size)
210   {
211     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
212                 "Received message with invalid sizes: (%d + %d + %d + %d != %d).\n",
213                 ss_size,
214                 key_size,
215                 value_size,
216                 (int) sizeof (struct StoreRecordMessage),
217                 req_size);
218     return NULL;
219   }
220   record = GNUNET_new (struct GNUNET_PEERSTORE_Record);
221   if (GNUNET_YES == ntohs (srm->peer_set))
222   {
223     record->peer = GNUNET_new (struct GNUNET_PeerIdentity);
224
225     memcpy (record->peer, &srm->peer, sizeof (struct GNUNET_PeerIdentity));
226   }
227   record->expiry = GNUNET_new (struct GNUNET_TIME_Absolute);
228
229   *(record->expiry) = srm->expiry;
230   dummy = (char *) &srm[1];
231   if (ss_size > 0)
232   {
233     record->sub_system = GNUNET_strdup (dummy);
234     dummy += ss_size;
235   }
236   if (key_size > 0)
237   {
238     record->key = GNUNET_strdup (dummy);
239     dummy += key_size;
240   }
241   if (value_size > 0)
242   {
243     record->value = GNUNET_malloc (value_size);
244     memcpy (record->value, dummy, value_size);
245   }
246   record->value_size = value_size;
247   return record;
248 }
249
250
251 /**
252  * Free any memory allocated for this record
253  *
254  * @param record
255  */
256 void
257 PEERSTORE_destroy_record (struct GNUNET_PEERSTORE_Record *record)
258 {
259   if (NULL != record->sub_system)
260     GNUNET_free (record->sub_system);
261   if (NULL != record->peer)
262     GNUNET_free (record->peer);
263   if (NULL != record->key)
264     GNUNET_free (record->key);
265   if (NULL != record->value)
266   {
267     GNUNET_free (record->value);
268     record->value = 0;
269   }
270   if (NULL != record->expiry)
271     GNUNET_free (record->expiry);
272   GNUNET_free (record);
273 }