peestore: towards iterate functionality
[oweals/gnunet.git] / src / peerstore / peerstore_common.c
1 /*
2       This file is part of GNUnet
3       (C) 2012-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  * @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 record message ready to be sent
30  *
31  * @param sub_system sub system string
32  * @param peer Peer identity (can be NULL)
33  * @param key record key string (can be NULL)
34  * @param value record value BLOB (can be NULL)
35  * @param value_size record value size in bytes (set to 0 if value is NULL)
36  * @param expiry absolute time after which the record expires
37  * @param msg_type message type to be set in header
38  * @return pointer to record message struct
39  */
40 struct StoreRecordMessage *
41 PEERSTORE_create_record_message(const char *sub_system,
42     const struct GNUNET_PeerIdentity *peer,
43     const char *key,
44     const void *value,
45     size_t value_size,
46     struct GNUNET_TIME_Absolute *expiry,
47     uint16_t msg_type)
48 {
49   struct StoreRecordMessage *srm;
50   size_t ss_size;
51   size_t key_size;
52   size_t request_size;
53   void *dummy;
54
55   ss_size = strlen(sub_system) + 1;
56   if(NULL == key)
57     key_size = 0;
58   else
59     key_size = strlen(key) + 1;
60   request_size = sizeof(struct StoreRecordMessage) +
61       ss_size +
62       key_size +
63       value_size;
64   srm = GNUNET_malloc(request_size);
65   srm->header.size = htons(request_size);
66   srm->header.type = htons(msg_type);
67   srm->key_size = htons(key_size);
68   if(NULL != expiry)
69     srm->expiry = *expiry;
70   if(NULL == peer)
71     srm->peer_set = htons(GNUNET_NO);
72   else
73   {
74     srm->peer_set = htons(GNUNET_YES);
75     srm->peer = *peer;
76   }
77   srm->sub_system_size = htons(ss_size);
78   srm->value_size = htons(value_size);
79   dummy = &srm[1];
80   memcpy(dummy, sub_system, ss_size);
81   dummy += ss_size;
82   memcpy(dummy, key, key_size);
83   dummy += key_size;
84   memcpy(dummy, value, value_size);
85   return srm;
86
87 }
88
89 /**
90  * Creates a MQ envelope for a single record
91  *
92  * @param sub_system sub system string
93  * @param peer Peer identity (can be NULL)
94  * @param key record key string (can be NULL)
95  * @param value record value BLOB (can be NULL)
96  * @param value_size record value size in bytes (set to 0 if value is NULL)
97  * @param expiry time after which the record expires
98  * @param msg_type message type to be set in header
99  * @return pointer to record message struct
100  */
101 struct GNUNET_MQ_Envelope *
102 PEERSTORE_create_record_mq_envelope(const char *sub_system,
103     const struct GNUNET_PeerIdentity *peer,
104     const char *key,
105     const void *value,
106     size_t value_size,
107     struct GNUNET_TIME_Absolute *expiry,
108     uint16_t msg_type)
109 {
110   struct StoreRecordMessage *srm;
111   struct GNUNET_MQ_Envelope *ev;
112   size_t ss_size;
113   size_t key_size;
114   size_t msg_size;
115   void *dummy;
116
117   GNUNET_assert(NULL != sub_system);
118   ss_size = strlen(sub_system) + 1;
119   if(NULL == key)
120     key_size = 0;
121   else
122     key_size = strlen(key) + 1;
123   msg_size = ss_size +
124       key_size +
125       value_size;
126   ev = GNUNET_MQ_msg_extra(srm, msg_size, msg_type);
127   srm->key_size = htons(key_size);
128   if(NULL != expiry)
129     srm->expiry = *expiry;
130   if(NULL == peer)
131     srm->peer_set = htons(GNUNET_NO);
132   else
133   {
134     srm->peer_set = htons(GNUNET_YES);
135     srm->peer = *peer;
136   }
137   srm->sub_system_size = htons(ss_size);
138   srm->value_size = htons(value_size);
139   dummy = &srm[1];
140   memcpy(dummy, sub_system, ss_size);
141   dummy += ss_size;
142   memcpy(dummy, key, key_size);
143   dummy += key_size;
144   memcpy(dummy, value, value_size);
145
146   return ev;
147 }
148
149 /**
150  * Parses a message carrying a record
151  *
152  * @param message the actual message
153  * @return Pointer to record or NULL if error
154  */
155 struct GNUNET_PEERSTORE_Record *
156 PEERSTORE_parse_record_message(const struct GNUNET_MessageHeader *message)
157 {
158   struct StoreRecordMessage *srm;
159   struct GNUNET_PEERSTORE_Record *record;
160   uint16_t req_size;
161   uint16_t ss_size;
162   uint16_t key_size;
163   uint16_t value_size;
164   char *dummy;
165
166   req_size = ntohs(message->size);
167   if(req_size < sizeof(struct StoreRecordMessage))
168     return NULL;
169   srm = (struct StoreRecordMessage *)message;
170   ss_size = ntohs(srm->sub_system_size);
171   key_size = ntohs(srm->key_size);
172   value_size = ntohs(srm->value_size);
173   if(ss_size + key_size + value_size + sizeof(struct StoreRecordMessage)
174         != req_size)
175     return NULL;
176   record = GNUNET_new(struct GNUNET_PEERSTORE_Record);
177   if(GNUNET_YES == ntohs(srm->peer_set))
178   {
179     record->peer = GNUNET_new(struct GNUNET_PeerIdentity);
180     memcpy(record->peer, &srm->peer, sizeof(struct GNUNET_PeerIdentity));
181   }
182   record->expiry = GNUNET_new(struct GNUNET_TIME_Absolute);
183   *(record->expiry) = srm->expiry;
184   dummy = (char *)&srm[1];
185   if(ss_size > 0)
186   {
187     record->sub_system = GNUNET_strdup(dummy);
188     dummy += ss_size;
189   }
190   if(key_size > 0)
191   {
192     record->key = GNUNET_strdup(dummy);
193     dummy += key_size;
194   }
195   if(value_size > 0)
196   {
197     record->value = GNUNET_malloc(value_size);
198     memcpy(record->value, dummy, value_size);
199   }
200   record->value_size = value_size;
201
202   return record;
203 }