-Merge branch 'master' of ssh://gnunet.org/gnunet into gsoc2018/rest_api
[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 it
6       under the terms of the GNU Affero General Public License as published
7       by the Free Software Foundation, either version 3 of the License,
8       or (at your 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       Affero General Public License for more details.
14      
15       You should have received a copy of the GNU Affero General Public License
16       along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 /**
19  * @file peerstore/peerstore_common.c
20  * @brief Helper peerstore functions
21  * @author Omar Tarabai
22  */
23
24 #include "peerstore_common.h"
25
26 /**
27  * Creates a hash of the given key combination
28  *
29  */
30 void
31 PEERSTORE_hash_key (const char *sub_system,
32                     const struct GNUNET_PeerIdentity *peer,
33                     const char *key,
34                     struct GNUNET_HashCode *ret)
35 {
36   size_t sssize;
37   size_t psize;
38   size_t ksize;
39   size_t totalsize;
40   void *block;
41   void *blockptr;
42
43   sssize = strlen (sub_system) + 1;
44   psize = sizeof (struct GNUNET_PeerIdentity);
45   ksize = strlen (key) + 1;
46   totalsize = sssize + psize + ksize;
47   block = GNUNET_malloc (totalsize);
48   blockptr = block;
49   GNUNET_memcpy (blockptr, sub_system, sssize);
50   blockptr += sssize;
51   GNUNET_memcpy (blockptr, peer, psize);
52   blockptr += psize;
53   GNUNET_memcpy (blockptr, key, ksize);
54   GNUNET_CRYPTO_hash (block, totalsize, ret);
55   GNUNET_free (block);
56 }
57
58
59 /**
60  * Creates a MQ envelope for a single record
61  *
62  * @param sub_system sub system string
63  * @param peer Peer identity (can be NULL)
64  * @param key record key string (can be NULL)
65  * @param value record value BLOB (can be NULL)
66  * @param value_size record value size in bytes (set to 0 if value is NULL)
67  * @param expiry time after which the record expires
68  * @param options options specific to the storage operation
69  * @param msg_type message type to be set in header
70  * @return pointer to record message struct
71  */
72 struct GNUNET_MQ_Envelope *
73 PEERSTORE_create_record_mq_envelope (const char *sub_system,
74                                      const struct GNUNET_PeerIdentity *peer,
75                                      const char *key,
76                                      const void *value,
77                                      size_t value_size,
78                                      struct GNUNET_TIME_Absolute expiry,
79                                      enum GNUNET_PEERSTORE_StoreOption options,
80                                      uint16_t msg_type)
81 {
82   struct StoreRecordMessage *srm;
83   struct GNUNET_MQ_Envelope *ev;
84   size_t ss_size;
85   size_t key_size;
86   size_t msg_size;
87   void *dummy;
88
89   GNUNET_assert (NULL != sub_system);
90   ss_size = strlen (sub_system) + 1;
91   if (NULL == key)
92     key_size = 0;
93   else
94     key_size = strlen (key) + 1;
95   msg_size = ss_size + key_size + value_size;
96   ev = GNUNET_MQ_msg_extra (srm, msg_size, msg_type);
97   srm->key_size = htons (key_size);
98   srm->expiry = GNUNET_TIME_absolute_hton (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   srm->options = htonl (options);
109   dummy = &srm[1];
110   GNUNET_memcpy (dummy, sub_system, ss_size);
111   dummy += ss_size;
112   GNUNET_memcpy (dummy, key, key_size);
113   dummy += key_size;
114   GNUNET_memcpy (dummy, value, value_size);
115   return ev;
116 }
117
118
119 /**
120  * Parses a message carrying a record
121  *
122  * @param srm the actual message
123  * @return Pointer to record or NULL if error
124  */
125 struct GNUNET_PEERSTORE_Record *
126 PEERSTORE_parse_record_message (const struct StoreRecordMessage *srm)
127 {
128   struct GNUNET_PEERSTORE_Record *record;
129   uint16_t req_size;
130   uint16_t ss_size;
131   uint16_t key_size;
132   uint16_t value_size;
133   char *dummy;
134
135   req_size = ntohs (srm->header.size) - sizeof (*srm);
136   ss_size = ntohs (srm->sub_system_size);
137   key_size = ntohs (srm->key_size);
138   value_size = ntohs (srm->value_size);
139   if (ss_size + key_size + value_size != req_size)
140   {
141     GNUNET_break (0);
142     return NULL;
143   }
144   record = GNUNET_new (struct GNUNET_PEERSTORE_Record);
145   if (GNUNET_YES == ntohs (srm->peer_set))
146   {
147     record->peer = srm->peer;
148   }
149   record->expiry = GNUNET_TIME_absolute_ntoh (srm->expiry);
150   dummy = (char *) &srm[1];
151   if (ss_size > 0)
152   {
153     record->sub_system = GNUNET_strdup (dummy);
154     dummy += ss_size;
155   }
156   if (key_size > 0)
157   {
158     record->key = GNUNET_strdup (dummy);
159     dummy += key_size;
160   }
161   if (value_size > 0)
162   {
163     record->value = GNUNET_malloc (value_size);
164     GNUNET_memcpy (record->value,
165                    dummy,
166                    value_size);
167   }
168   record->value_size = value_size;
169   return record;
170 }
171
172
173 /**
174  * Free any memory allocated for this record
175  *
176  * @param record
177  */
178 void
179 PEERSTORE_destroy_record (struct GNUNET_PEERSTORE_Record *record)
180 {
181   if (NULL != record->sub_system)
182     GNUNET_free (record->sub_system);
183   if (NULL != record->key)
184     GNUNET_free (record->key);
185   if (NULL != record->value)
186   {
187     GNUNET_free (record->value);
188     record->value = 0;
189   }
190   GNUNET_free (record);
191 }