f0c112ac759427872f1c5656fd2e949b1455a716
[oweals/gnunet.git] / src / rps / gnunet-service-rps_sampler_elem.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C)
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 /**
20  * @file rps/gnunet-service-rps_sampler.c
21  * @brief sampler implementation
22  * @author Julius Bünger
23  */
24 #include "platform.h"
25 #include "gnunet_util_lib.h"
26
27 #include "gnunet-service-rps_sampler_elem.h"
28
29 #include <inttypes.h>
30
31 #include "rps-test_util.h"
32
33 #define LOG(kind, ...) GNUNET_log_from(kind,"rps-sampler_elem",__VA_ARGS__)
34
35
36 /***********************************************************************
37  * WARNING: This section needs to be reviewed regarding the use of
38  * functions providing (pseudo)randomness!
39 ***********************************************************************/
40
41
42 /**
43  * Reinitialise a previously initialised sampler element.
44  *
45  * @param sampler_el The sampler element to (re-) initialise
46  */
47 void
48 RPS_sampler_elem_reinit (struct RPS_SamplerElement *sampler_elem)
49 {
50   sampler_elem->is_empty = EMPTY;
51
52   // I guess I don't need to call GNUNET_CRYPTO_hmac_derive_key()...
53   GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_STRONG,
54                              &(sampler_elem->auth_key.key),
55                              GNUNET_CRYPTO_HASH_LENGTH);
56
57   sampler_elem->last_client_request = GNUNET_TIME_UNIT_FOREVER_ABS;
58
59   sampler_elem->birth = GNUNET_TIME_absolute_get ();
60   sampler_elem->num_peers = 0;
61   sampler_elem->num_change = 0;
62 }
63
64
65 /**
66  * Create a sampler element and initialise it.
67  *
68  * In this implementation this means choosing an auth_key for later use in
69  * a hmac at random.
70  *
71  * @return a newly created RPS_SamplerElement which currently holds no id.
72  */
73 struct RPS_SamplerElement *
74 RPS_sampler_elem_create (void)
75 {
76   struct RPS_SamplerElement *s;
77
78   s = GNUNET_new (struct RPS_SamplerElement);
79
80   RPS_sampler_elem_reinit (s);
81
82   return s;
83 }
84
85
86 /**
87  * Destroy a sampler element.
88  *
89  * @param sampler_elem the element to destroy
90  */
91 void
92 RPS_sampler_elem_destroy (struct RPS_SamplerElement *sampler_elem)
93 {
94   GNUNET_free (sampler_elem);
95 }
96
97
98 /**
99  * Update a sampler element with a PeerID
100  *
101  * @param sampler_elem The sampler element to update
102  * @param new_ID The PeerID to update with
103  */
104 void
105 RPS_sampler_elem_next (struct RPS_SamplerElement *sampler_elem,
106                        const struct GNUNET_PeerIdentity *new_ID)
107 {
108   struct GNUNET_HashCode other_hash;
109
110   sampler_elem->num_peers++;
111
112   if (0 == GNUNET_CRYPTO_cmp_peer_identity (new_ID, &(sampler_elem->peer_id)))
113   {
114     LOG (GNUNET_ERROR_TYPE_DEBUG, "Have already PeerID %s\n",
115         GNUNET_i2s (&(sampler_elem->peer_id)));
116   }
117   else
118   {
119     GNUNET_CRYPTO_hmac(&sampler_elem->auth_key,
120         new_ID,
121         sizeof(struct GNUNET_PeerIdentity),
122         &other_hash);
123
124     if (EMPTY == sampler_elem->is_empty)
125     {
126       LOG (GNUNET_ERROR_TYPE_DEBUG,
127            "Got PeerID %s; Simply accepting (was empty previously).\n",
128            GNUNET_i2s(new_ID));
129       sampler_elem->peer_id = *new_ID;
130       sampler_elem->peer_id_hash = other_hash;
131
132       sampler_elem->num_change++;
133     }
134     else if (0 > GNUNET_CRYPTO_hash_cmp (&other_hash, &sampler_elem->peer_id_hash))
135     {
136       LOG (GNUNET_ERROR_TYPE_DEBUG, "Discarding old PeerID %s\n",
137           GNUNET_i2s (&sampler_elem->peer_id));
138       sampler_elem->peer_id = *new_ID;
139       sampler_elem->peer_id_hash = other_hash;
140
141       sampler_elem->num_change++;
142     }
143     else
144     {
145       LOG (GNUNET_ERROR_TYPE_DEBUG, "Keeping old PeerID %s\n",
146           GNUNET_i2s (&sampler_elem->peer_id));
147     }
148   }
149   sampler_elem->is_empty = NOT_EMPTY;
150 }
151
152 /**
153  * Set the min-wise independent function of the given sampler element.
154  *
155  * @param sampler_elem the sampler element
156  * @param auth_key the key to use
157  */
158 void
159 RPS_sampler_elem_set (struct RPS_SamplerElement *sampler_elem,
160                       struct GNUNET_CRYPTO_AuthKey auth_key)
161 {
162   sampler_elem->auth_key = auth_key;
163 }
164
165 /* end of gnunet-service-rps.c */