aboutsummaryrefslogtreecommitdiff
path: root/src/scalarproduct/gnunet-scalarproduct.c
diff options
context:
space:
mode:
authorChristian Fuchs <christian.fuchs@cfuchs.net>2014-05-07 08:21:49 +0000
committerChristian Fuchs <christian.fuchs@cfuchs.net>2014-05-07 08:21:49 +0000
commit8a2d1e6aedbf1bc95052e63ac67093b89385b0a1 (patch)
tree993d5f09035ce90f8f9a2d50cdcc417631d88227 /src/scalarproduct/gnunet-scalarproduct.c
parent3a658d6f0923662f193a49af8aae52a83aafae1c (diff)
downloadgnunet-8a2d1e6aedbf1bc95052e63ac67093b89385b0a1.tar.gz
gnunet-8a2d1e6aedbf1bc95052e63ac67093b89385b0a1.zip
WIP commit of scalar product 2.0. It is unfinished and does not yet pass tests. This commit happens because of the move from mesh->cadet.
- reverted SP API back to the original design from 2012 (using key-value pairs) - SP now uses set intersection to determine common elements from the set provided by the user - values are sorted based on their keys after intersection - removed state tracking, as simple tracking is now insufficient. Just checking for conditions directly is easier readable and less buggy - modified/renamed SP message types to reflect the changed behavior of SP
Diffstat (limited to 'src/scalarproduct/gnunet-scalarproduct.c')
-rw-r--r--src/scalarproduct/gnunet-scalarproduct.c219
1 files changed, 77 insertions, 142 deletions
diff --git a/src/scalarproduct/gnunet-scalarproduct.c b/src/scalarproduct/gnunet-scalarproduct.c
index a93902640..2bb708fc9 100644
--- a/src/scalarproduct/gnunet-scalarproduct.c
+++ b/src/scalarproduct/gnunet-scalarproduct.c
@@ -44,12 +44,12 @@ struct ScalarProductCallbackClosure
44 /** 44 /**
45 * the session key identifying this computation 45 * the session key identifying this computation
46 */ 46 */
47 struct GNUNET_HashCode key; 47 struct GNUNET_HashCode session_key;
48 48
49 /** 49 /**
50 * PeerID we want to compute a scalar product with 50 * PeerID we want to compute a scalar product with
51 */ 51 */
52 struct GNUNET_PeerIdentity peer; 52 struct GNUNET_PeerIdentity peer_id;
53}; 53};
54 54
55/** 55/**
@@ -60,7 +60,7 @@ static char *input_peer_id;
60/** 60/**
61 * Option -p: destination peer identity for checking message-ids with 61 * Option -p: destination peer identity for checking message-ids with
62 */ 62 */
63static char *input_key; 63static char *input_session_key;
64 64
65/** 65/**
66 * Option -e: vector to calculate a scalarproduct with 66 * Option -e: vector to calculate a scalarproduct with
@@ -68,15 +68,14 @@ static char *input_key;
68static char *input_elements; 68static char *input_elements;
69 69
70/** 70/**
71 * Option -m: message-ids to calculate a scalarproduct with
72 */
73static char *input_mask;
74
75/**
76 * Global return value 71 * Global return value
77 */ 72 */
78static int ret = -1; 73static int ret = -1;
79 74
75/**
76 * our Scalarproduct Computation handle
77 */
78struct GNUNET_SCALARPRODUCT_ComputationHandle * computation;
80 79
81/** 80/**
82 * Callback called if we are initiating a new computation session 81 * Callback called if we are initiating a new computation session
@@ -96,29 +95,30 @@ responder_callback (void *cls,
96 ret = 0; 95 ret = 0;
97 LOG (GNUNET_ERROR_TYPE_INFO, 96 LOG (GNUNET_ERROR_TYPE_INFO,
98 "Session %s concluded.\n", 97 "Session %s concluded.\n",
99 GNUNET_h2s (&closure->key)); 98 GNUNET_h2s (&closure->session_key));
100 break; 99 break;
101 case GNUNET_SCALARPRODUCT_Status_InvalidResponse: 100 case GNUNET_SCALARPRODUCT_Status_InvalidResponse:
102 LOG (GNUNET_ERROR_TYPE_ERROR, 101 LOG (GNUNET_ERROR_TYPE_ERROR,
103 "Session %s failed: invalid response\n", 102 "Session %s failed: invalid response\n",
104 GNUNET_h2s (&closure->key)); 103 GNUNET_h2s (&closure->session_key));
105 break; 104 break;
106 case GNUNET_SCALARPRODUCT_Status_Failure: 105 case GNUNET_SCALARPRODUCT_Status_Failure:
107 LOG (GNUNET_ERROR_TYPE_ERROR, 106 LOG (GNUNET_ERROR_TYPE_ERROR,
108 "Session %s failed: service failure\n", 107 "Session %s failed: service failure\n",
109 GNUNET_h2s (&closure->key)); 108 GNUNET_h2s (&closure->session_key));
110 break; 109 break;
111 case GNUNET_SCALARPRODUCT_Status_ServiceDisconnected: 110 case GNUNET_SCALARPRODUCT_Status_ServiceDisconnected:
112 LOG (GNUNET_ERROR_TYPE_ERROR, 111 LOG (GNUNET_ERROR_TYPE_ERROR,
113 "Session %s failed: service disconnect!\n", 112 "Session %s failed: service disconnect!\n",
114 GNUNET_h2s (&closure->key)); 113 GNUNET_h2s (&closure->session_key));
115 break; 114 break;
116 default: 115 default:
117 LOG (GNUNET_ERROR_TYPE_ERROR, 116 LOG (GNUNET_ERROR_TYPE_ERROR,
118 "Session %s failed: return code %d\n", 117 "Session %s failed: return code %d\n",
119 GNUNET_h2s (&closure->key), 118 GNUNET_h2s (&closure->session_key),
120 status); 119 status);
121 } 120 }
121 computation = NULL;
122 GNUNET_SCHEDULER_shutdown(); 122 GNUNET_SCHEDULER_shutdown();
123} 123}
124 124
@@ -155,28 +155,29 @@ requester_callback (void *cls,
155 case GNUNET_SCALARPRODUCT_Status_InvalidResponse: 155 case GNUNET_SCALARPRODUCT_Status_InvalidResponse:
156 LOG (GNUNET_ERROR_TYPE_ERROR, 156 LOG (GNUNET_ERROR_TYPE_ERROR,
157 "Session %s with peer %s failed: invalid response received\n", 157 "Session %s with peer %s failed: invalid response received\n",
158 GNUNET_h2s (&closure->key), 158 GNUNET_h2s (&closure->session_key),
159 GNUNET_i2s (&closure->peer)); 159 GNUNET_i2s (&closure->peer_id));
160 break; 160 break;
161 case GNUNET_SCALARPRODUCT_Status_Failure: 161 case GNUNET_SCALARPRODUCT_Status_Failure:
162 LOG (GNUNET_ERROR_TYPE_ERROR, 162 LOG (GNUNET_ERROR_TYPE_ERROR,
163 "Session %s with peer %s failed: API failure\n", 163 "Session %s with peer %s failed: API failure\n",
164 GNUNET_h2s (&closure->key), 164 GNUNET_h2s (&closure->session_key),
165 GNUNET_i2s (&closure->peer)); 165 GNUNET_i2s (&closure->peer_id));
166 break; 166 break;
167 case GNUNET_SCALARPRODUCT_Status_ServiceDisconnected: 167 case GNUNET_SCALARPRODUCT_Status_ServiceDisconnected:
168 LOG (GNUNET_ERROR_TYPE_ERROR, 168 LOG (GNUNET_ERROR_TYPE_ERROR,
169 "Session %s with peer %s was disconnected from service.\n", 169 "Session %s with peer %s was disconnected from service.\n",
170 GNUNET_h2s (&closure->key), 170 GNUNET_h2s (&closure->session_key),
171 GNUNET_i2s (&closure->peer)); 171 GNUNET_i2s (&closure->peer_id));
172 break; 172 break;
173 default: 173 default:
174 LOG (GNUNET_ERROR_TYPE_ERROR, 174 LOG (GNUNET_ERROR_TYPE_ERROR,
175 "Session %s with peer %s failed: return code %d\n", 175 "Session %s with peer %s failed: return code %d\n",
176 GNUNET_h2s (&closure->key), 176 GNUNET_h2s (&closure->session_key),
177 GNUNET_i2s (&closure->peer), 177 GNUNET_i2s (&closure->peer_id),
178 status); 178 status);
179 } 179 }
180 computation = NULL;
180 GNUNET_SCHEDULER_shutdown(); 181 GNUNET_SCHEDULER_shutdown();
181} 182}
182 183
@@ -191,7 +192,8 @@ static void
191shutdown_task (void *cls, 192shutdown_task (void *cls,
192 const struct GNUNET_SCHEDULER_TaskContext *tc) 193 const struct GNUNET_SCHEDULER_TaskContext *tc)
193{ 194{
194 GNUNET_SCALARPRODUCT_disconnect (); 195 if (NULL != computation)
196 GNUNET_SCALARPRODUCT_cancel(computation);
195} 197}
196 198
197 199
@@ -211,11 +213,8 @@ run (void *cls,
211{ 213{
212 char *begin = input_elements; 214 char *begin = input_elements;
213 char *end; 215 char *end;
214 int32_t element;
215 int i; 216 int i;
216 int32_t *elements; 217 struct GNUNET_SCALARPRODUCT_Element * elements;
217 unsigned char *mask;
218 uint32_t mask_bytes;
219 uint32_t element_count = 0; 218 uint32_t element_count = 0;
220 struct ScalarProductCallbackClosure * closure; 219 struct ScalarProductCallbackClosure * closure;
221 220
@@ -226,27 +225,27 @@ run (void *cls,
226 return; 225 return;
227 } 226 }
228 227
229 if (NULL == input_key) 228 if (NULL == input_session_key)
230 { 229 {
231 LOG (GNUNET_ERROR_TYPE_ERROR, 230 LOG (GNUNET_ERROR_TYPE_ERROR,
232 _ ("This program needs a session identifier for comparing vectors.\n")); 231 _ ("This program needs a session identifier for comparing vectors.\n"));
233 return; 232 return;
234 } 233 }
235 234
236 if (1 > strnlen (input_key, sizeof (struct GNUNET_HashCode))) 235 if (1 > strnlen (input_session_key, sizeof (struct GNUNET_HashCode)))
237 { 236 {
238 LOG (GNUNET_ERROR_TYPE_ERROR, 237 LOG (GNUNET_ERROR_TYPE_ERROR,
239 _ ("Please give a session key for --input_key!\n")); 238 _ ("Please give a session key for --input_key!\n"));
240 return; 239 return;
241 } 240 }
242 closure = GNUNET_new (struct ScalarProductCallbackClosure); 241 closure = GNUNET_new (struct ScalarProductCallbackClosure);
243 GNUNET_CRYPTO_hash (input_key, strlen (input_key), &closure->key); 242 GNUNET_CRYPTO_hash (input_session_key, strlen (input_session_key), &closure->session_key);
244 243
245 if (input_peer_id && 244 if (input_peer_id &&
246 (GNUNET_OK != 245 (GNUNET_OK !=
247 GNUNET_CRYPTO_eddsa_public_key_from_string (input_peer_id, 246 GNUNET_CRYPTO_eddsa_public_key_from_string (input_peer_id,
248 strlen (input_peer_id), 247 strlen (input_peer_id),
249 (struct GNUNET_CRYPTO_EddsaPublicKey *) &closure->peer))) { 248 (struct GNUNET_CRYPTO_EddsaPublicKey *) &closure->peer_id))) {
250 LOG (GNUNET_ERROR_TYPE_ERROR, 249 LOG (GNUNET_ERROR_TYPE_ERROR,
251 _ ("Tried to set initiator mode, as peer ID was given. " 250 _ ("Tried to set initiator mode, as peer ID was given. "
252 "However, `%s' is not a valid peer identifier.\n"), 251 "However, `%s' is not a valid peer identifier.\n"),
@@ -254,136 +253,75 @@ run (void *cls,
254 return; 253 return;
255 } 254 }
256 255
257 /* Count input_elements_peer1, and put in elements_peer1 array */ 256 for (end = begin; 0 != *end; end++)
258 do 257 if (*end == ';')
259 {
260 // get the length of the current element
261 for (end = begin; *end && *end != ','; end++);
262
263 if (0 == *begin)
264 {
265 break;
266 }
267 else if (1 == sscanf (begin, "%" SCNd32 ",", &element))
268 {
269 //element in the middle
270 element_count++; 258 element_count++;
271 begin = end; 259 if (0 == element_count) {
272 if (',' == *end)
273 begin += 1;
274 }
275 else
276 {
277 LOG (GNUNET_ERROR_TYPE_ERROR,
278 _ ("Could not convert `%s' to int32_t.\n"), begin);
279 return;
280 }
281 }
282 while (1);
283 if (0 == element_count)
284 {
285 LOG (GNUNET_ERROR_TYPE_ERROR, 260 LOG (GNUNET_ERROR_TYPE_ERROR,
286 _ ("Need elements to compute the vectorproduct, got none.\n")); 261 _ ("Need elements to compute the vectorproduct, got none.\n"));
287 return; 262 return;
288 } 263 }
289 264
290 begin = input_elements; 265 elements = (struct GNUNET_SCALARPRODUCT_Element *)
291 elements = GNUNET_malloc (sizeof (int32_t) * element_count); 266 GNUNET_malloc(sizeof(struct GNUNET_SCALARPRODUCT_Element)*element_count);
292 element_count = 0; 267
293 /* Read input_elements_peer1, and put in elements_peer1 array */ 268 for (i = 0; i < element_count;i++)
294 do
295 { 269 {
296 // get the length of the current element 270 struct GNUNET_SCALARPRODUCT_Element element;
297 for (end = begin; *end && *end != ','; end++); 271 char* separator=NULL;
298 272
299 if (0 == *begin) 273 // get the length of the current key,value; tupel
300 { 274 for (end = begin; *end != ';'; end++)
301 break; 275 if (*end == ',')
276 separator = end;
277
278 // final element
279 if ((NULL == separator)
280 || (begin == separator)
281 || (separator == end - 1 )) {
282 LOG (GNUNET_ERROR_TYPE_ERROR,
283 _ ("Malformed input, could not parse `%s'\n"), begin);
284 GNUNET_free(elements);
285 return;
302 } 286 }
303 else if (1 == sscanf (begin, "%" SCNd32 ",", &elements[element_count])) 287
304 { 288 // read the element's key
305 //element in the middle 289 *separator = 0;
306 element_count++; 290 GNUNET_CRYPTO_hash (begin, strlen (begin), &element.key);
307 begin = end; 291
308 if (',' == *end) 292 // read the element's value
309 begin += 1; 293 if (1 != sscanf (separator+1, "%" SCNd32 ";", &element.value))
310 }
311 else
312 { 294 {
313 LOG (GNUNET_ERROR_TYPE_ERROR, 295 LOG (GNUNET_ERROR_TYPE_ERROR,
314 _ ("Could not convert `%s' to int32_t.\n"), begin); 296 _ ("Could not convert `%s' to int32_t.\n"), begin);
297 GNUNET_free(elements);
315 return; 298 return;
316 } 299 }
300
301 elements[i]=element;
302 begin = end+1;
317 } 303 }
318 while (1);
319
320 mask_bytes = element_count / 8 + ( (element_count % 8) ? 1 : 0);
321 mask = GNUNET_malloc ((element_count / 8) + 1);
322 304
323 /* Read input_mask_peer1 and read in mask_peer1 array */ 305 if (((NULL != input_peer_id) &&
324 if ((NULL != input_peer_id) && (NULL != input_mask)) 306 (NULL == (computation = GNUNET_SCALARPRODUCT_start_computation (cfg,
325 { 307 &closure->session_key,
326 begin = input_mask; 308 &closure->peer_id,
327 unsigned short mask_count = 0;
328
329 do
330 {
331 // get the length of the current element and replace , with null
332 for (end = begin; *end && *end != ','; end++);
333
334 if (1 == sscanf (begin, "%" SCNd32 ",", &element))
335 {
336 //element in the middle
337 begin = end + 1;
338 }
339 else if (*begin == 0)
340 {
341 break;
342 }
343 else
344 {
345 LOG (GNUNET_ERROR_TYPE_ERROR,
346 _ ("Could not convert `%s' to integer.\n"), begin);
347 return;
348 }
349
350 if (element)
351 mask[mask_count / 8] = mask[mask_count / 8] | 1 << (mask_count % 8);
352 mask_count++;
353 }
354 while (mask_count < element_count);
355 }
356 else if (NULL != input_peer_id)
357 for (i = 0; i <= mask_bytes; i++)
358 mask[i] = UCHAR_MAX; // all 1's
359
360 if (input_peer_id &&
361 (NULL == GNUNET_SCALARPRODUCT_request (cfg,
362 &closure->key,
363 &closure->peer,
364 elements, element_count, 309 elements, element_count,
365 mask, mask_bytes,
366 &requester_callback, 310 &requester_callback,
367 (void *) &closure))) 311 (void *) &closure))))
368 { 312 ||
369 GNUNET_free (elements); 313 ((NULL == input_peer_id) &&
370 GNUNET_free (mask); 314 (NULL == (computation = GNUNET_SCALARPRODUCT_accept_computation (cfg,
371 return; 315 &closure->session_key,
372 }
373
374 if ((NULL == input_peer_id) &&
375 (NULL == GNUNET_SCALARPRODUCT_response (cfg,
376 &closure->key,
377 elements, element_count, 316 elements, element_count,
378 &responder_callback, 317 &responder_callback,
379 (void *) &closure))) 318 (void *) &closure)))))
380 { 319 {
381 GNUNET_free (elements); 320 GNUNET_free (elements);
382 GNUNET_free (mask);
383 return; 321 return;
384 } 322 }
323
385 GNUNET_free (elements); 324 GNUNET_free (elements);
386 GNUNET_free (mask);
387 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, 325 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
388 &shutdown_task, 326 &shutdown_task,
389 NULL); 327 NULL);
@@ -403,18 +341,15 @@ int
403main (int argc, char *const *argv) 341main (int argc, char *const *argv)
404{ 342{
405 static const struct GNUNET_GETOPT_CommandLineOption options[] = { 343 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
406 {'e', "elements", "\"val1,val2,...,valn\"", 344 {'e', "elements", "\"key1,val1;key2,val2;...,keyn,valn;\"",
407 gettext_noop ("A comma separated list of elements to compare as vector with our remote peer."), 345 gettext_noop ("A comma separated list of elements to compare as vector with our remote peer."),
408 1, &GNUNET_GETOPT_set_string, &input_elements}, 346 1, &GNUNET_GETOPT_set_string, &input_elements},
409 {'m', "mask", "\"0,1,...,maskn\"",
410 gettext_noop ("A comma separated mask to select which elements should actually be compared."),
411 1, &GNUNET_GETOPT_set_string, &input_mask},
412 {'p', "peer", "PEERID", 347 {'p', "peer", "PEERID",
413 gettext_noop ("[Optional] peer to calculate our scalarproduct with. If this parameter is not given, the service will wait for a remote peer to compute the request."), 348 gettext_noop ("[Optional] peer to calculate our scalarproduct with. If this parameter is not given, the service will wait for a remote peer to compute the request."),
414 1, &GNUNET_GETOPT_set_string, &input_peer_id}, 349 1, &GNUNET_GETOPT_set_string, &input_peer_id},
415 {'k', "key", "TRANSACTION_ID", 350 {'k', "key", "TRANSACTION_ID",
416 gettext_noop ("Transaction ID shared with peer."), 351 gettext_noop ("Transaction ID shared with peer."),
417 1, &GNUNET_GETOPT_set_string, &input_key}, 352 1, &GNUNET_GETOPT_set_string, &input_session_key},
418 GNUNET_GETOPT_OPTION_END 353 GNUNET_GETOPT_OPTION_END
419 }; 354 };
420 355