diff options
Diffstat (limited to 'src/scalarproduct/test_vectorproduct_api_4peers.c')
-rw-r--r-- | src/scalarproduct/test_vectorproduct_api_4peers.c | 1084 |
1 files changed, 1084 insertions, 0 deletions
diff --git a/src/scalarproduct/test_vectorproduct_api_4peers.c b/src/scalarproduct/test_vectorproduct_api_4peers.c new file mode 100644 index 000000000..73ab634f9 --- /dev/null +++ b/src/scalarproduct/test_vectorproduct_api_4peers.c | |||
@@ -0,0 +1,1084 @@ | |||
1 | |||
2 | /* | ||
3 | This file is part of GNUnet. | ||
4 | (C) 2013 Christian Grothoff (and other contributing authors) | ||
5 | |||
6 | GNUnet is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published | ||
8 | by the Free Software Foundation; either version 3, or (at your | ||
9 | option) any later version. | ||
10 | |||
11 | GNUnet is distributed in the hope that it will be useful, but | ||
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with GNUnet; see the file COPYING. If not, write to the | ||
18 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
19 | Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | /** | ||
23 | * AIM OF THIS TEST | ||
24 | * | ||
25 | * The aim for the extended test is to verify the queuing functionality in the | ||
26 | * service and the API. The API queues requests received from the clients. The | ||
27 | * service queues requests that are received from other services. | ||
28 | * | ||
29 | * To test this, we create 4 peers. peer1 and peer2 are designated responders, | ||
30 | * and peer3 and peer4 are designated as requesters. Each peer calls API for the | ||
31 | * vectorproduct service accordingly. | ||
32 | * | ||
33 | * * peer1 tells the service to prepare response for requests with keys | ||
34 | * input_key_p1_p3(shared key b/w peer1 and peer3) and input_key_p1_p4. | ||
35 | * Similarly peer2 tells service to prepare response for requests with keys | ||
36 | * input_key_p2_p3, and input_key_p2_p4. | ||
37 | * * Simultaneously, peer3 tells its service to send a request to peer1 with key | ||
38 | * input_key_p1_p3, and a request to peer2 with key input_key_p2_p3. Similarly, | ||
39 | * peer 4 sends requests with appropriate keys. | ||
40 | * | ||
41 | * Each peer sends 2 requests to its service, which tests the queuing in API. | ||
42 | * Each service receives 2 requests from other service, which tests the queuing | ||
43 | * functionality in the service. | ||
44 | */ | ||
45 | |||
46 | |||
47 | /** | ||
48 | * @file vectorproduct/test_vectorproduct_api_4peers.c | ||
49 | * @brief Vectorproduct API testing between 4 peers using testing API | ||
50 | * @author Gaurav Kukreja | ||
51 | * @author Christian Fuchs | ||
52 | */ | ||
53 | |||
54 | #include <string.h> | ||
55 | |||
56 | #include <inttypes.h> | ||
57 | #include "platform.h" | ||
58 | #include "gnunet_util_lib.h" | ||
59 | #include "gnunet_testbed_service.h" | ||
60 | #include "gnunet_common.h" | ||
61 | #include "gnunet_vectorproduct_service.h" | ||
62 | #include "gnunet_protocols.h" | ||
63 | |||
64 | #define LOG(kind,...) GNUNET_log_from (kind, "test-vectorproduct-api-4peers",__VA_ARGS__) | ||
65 | |||
66 | #define NUM_PEERS 4 | ||
67 | |||
68 | /** | ||
69 | * Structure for holding peer's sockets and IO Handles | ||
70 | */ | ||
71 | struct PeerData | ||
72 | { | ||
73 | /** | ||
74 | * Handle to testbed peer | ||
75 | */ | ||
76 | struct GNUNET_TESTBED_Peer *peer; | ||
77 | |||
78 | /** | ||
79 | * The service connect operation to stream | ||
80 | */ | ||
81 | struct GNUNET_TESTBED_Operation *op; | ||
82 | |||
83 | /** | ||
84 | * Our Peer id | ||
85 | */ | ||
86 | struct GNUNET_PeerIdentity our_id; | ||
87 | |||
88 | /** | ||
89 | * Pointer to Vector Product Handle | ||
90 | */ | ||
91 | struct GNUNET_VECTORPRODUCT_Handle *vh; | ||
92 | |||
93 | /** | ||
94 | * Input elements for peer | ||
95 | */ | ||
96 | char * input_elements; | ||
97 | |||
98 | /** | ||
99 | * Input Mask for peer | ||
100 | */ | ||
101 | char * input_mask; | ||
102 | |||
103 | /** | ||
104 | * 2 Input keys for peer for 2 sessions of each peer | ||
105 | */ | ||
106 | char * input_keys[2]; | ||
107 | |||
108 | /** | ||
109 | * Number of requests(or prepare_response) sent by the peer | ||
110 | */ | ||
111 | int request_num; | ||
112 | |||
113 | /** | ||
114 | * Number of callbacks received by the peer | ||
115 | */ | ||
116 | int callback_num; | ||
117 | |||
118 | /** | ||
119 | * PeerData of the peers, this peer will talk to | ||
120 | */ | ||
121 | struct PeerData * peers[2]; | ||
122 | |||
123 | |||
124 | }; | ||
125 | |||
126 | /** | ||
127 | * Different states in test setup | ||
128 | */ | ||
129 | enum SetupState | ||
130 | { | ||
131 | /** | ||
132 | * Get the identity of peer 1 | ||
133 | */ | ||
134 | PEER1_GET_IDENTITY, | ||
135 | |||
136 | /** | ||
137 | * Get the identity of peer 2 | ||
138 | */ | ||
139 | PEER2_GET_IDENTITY, | ||
140 | |||
141 | /** | ||
142 | * Get the identity of peer 3 | ||
143 | */ | ||
144 | PEER3_GET_IDENTITY, | ||
145 | |||
146 | /** | ||
147 | * Get the identity of peer 4 | ||
148 | */ | ||
149 | PEER4_GET_IDENTITY, | ||
150 | |||
151 | /** | ||
152 | * Connect to stream service of peer 1 | ||
153 | */ | ||
154 | PEER1_VECTORPRODUCT_CONNECT, | ||
155 | |||
156 | /** | ||
157 | * Connect to stream service of peer 2 | ||
158 | */ | ||
159 | PEER2_VECTORPRODUCT_CONNECT, | ||
160 | |||
161 | /** | ||
162 | * Connect to stream service of peer 3 | ||
163 | */ | ||
164 | PEER3_VECTORPRODUCT_CONNECT, | ||
165 | |||
166 | /** | ||
167 | * Connect to stream service of peer 4 | ||
168 | */ | ||
169 | PEER4_VECTORPRODUCT_CONNECT | ||
170 | |||
171 | }; | ||
172 | |||
173 | /****************************************************************************** | ||
174 | *** Global Variables ***************************** | ||
175 | ******************************************************************************/ | ||
176 | |||
177 | /** | ||
178 | * Maximum allowed message-ids we can check in one go (with one GNUNET_message) | ||
179 | */ | ||
180 | static unsigned int max_mids; | ||
181 | |||
182 | /** | ||
183 | * Session Key used by both the test peers | ||
184 | */ | ||
185 | char input_key_p1_p3[103] = "111111111111111111111111111111111111111111111111113333333333333333333333333333333333333333333333333333"; | ||
186 | |||
187 | /** | ||
188 | * Session Key used by both the test peers | ||
189 | */ | ||
190 | char input_key_p1_p4[103] = "111111111111111111111111111111111111111111111111114444444444444444444444444444444444444444444444444444"; | ||
191 | |||
192 | /** | ||
193 | * Session Key used by both the test peers | ||
194 | */ | ||
195 | char input_key_p2_p3[103] = "222222222222222222222222222222222222222222222222223333333333333333333333333333333333333333333333333333"; | ||
196 | |||
197 | /** | ||
198 | * Session Key used by both the test peers | ||
199 | */ | ||
200 | char input_key_p2_p4[103] = "222222222222222222222222222222222222222222222222224444444444444444444444444444444444444444444444444444"; | ||
201 | |||
202 | /** | ||
203 | * Input elements for peer1 | ||
204 | */ | ||
205 | //char input_elements_peer1[] = "11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11"; | ||
206 | char input_elements_peer1[] = "11,11,11"; | ||
207 | |||
208 | /** | ||
209 | * Input Mask for peer 1 | ||
210 | */ | ||
211 | //char input_mask_peer1[] = "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"; | ||
212 | char input_mask_peer1[] = "1,1,1"; | ||
213 | |||
214 | /** | ||
215 | * Input elements for peer2 | ||
216 | */ | ||
217 | //char input_elements_peer2[] = "11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11"; | ||
218 | char input_elements_peer2[] = "11,11,11"; | ||
219 | /** | ||
220 | * Input Mask for peer 2 | ||
221 | */ | ||
222 | //char input_mask_peer2[] = "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"; | ||
223 | char input_mask_peer2[] = "1,1,1"; | ||
224 | |||
225 | /** | ||
226 | * Input elements for peer3 | ||
227 | */ | ||
228 | //char input_elements_peer3[] = "11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11"; | ||
229 | char input_elements_peer3[] = "11,11,11"; | ||
230 | |||
231 | /** | ||
232 | * Input Mask for peer 3 | ||
233 | */ | ||
234 | //char input_mask_peer3[] = "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"; | ||
235 | char input_mask_peer3[] = "1,1,1"; | ||
236 | |||
237 | /** | ||
238 | * Input elements for peer4 | ||
239 | */ | ||
240 | //char input_elements_peer4[] = "11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11"; | ||
241 | char input_elements_peer4[] = "11,11,11"; | ||
242 | /** | ||
243 | * Input Mask for peer 4 | ||
244 | */ | ||
245 | //char input_mask_peer4[] = "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"; | ||
246 | char input_mask_peer4[] = "1,1,1"; | ||
247 | |||
248 | |||
249 | /** | ||
250 | * Data context for peer 1 | ||
251 | */ | ||
252 | static struct PeerData peer1; | ||
253 | |||
254 | /** | ||
255 | * Data context for peer 2 | ||
256 | */ | ||
257 | static struct PeerData peer2; | ||
258 | |||
259 | /** | ||
260 | * Data context for peer 3 | ||
261 | */ | ||
262 | static struct PeerData peer3; | ||
263 | |||
264 | /** | ||
265 | * Data context for peer 4 | ||
266 | */ | ||
267 | static struct PeerData peer4; | ||
268 | |||
269 | /** | ||
270 | * Various states during test setup | ||
271 | */ | ||
272 | static enum SetupState setup_state; | ||
273 | |||
274 | /** | ||
275 | * Testbed operation handle | ||
276 | */ | ||
277 | static struct GNUNET_TESTBED_Operation *op; | ||
278 | |||
279 | /** | ||
280 | * Return value for the test | ||
281 | */ | ||
282 | static int ok; | ||
283 | |||
284 | /** | ||
285 | * Abort Task for timeout | ||
286 | */ | ||
287 | static GNUNET_SCHEDULER_TaskIdentifier abort_task; | ||
288 | /****************************************************************************** | ||
289 | *** Static Functions ***************************** | ||
290 | ******************************************************************************/ | ||
291 | |||
292 | static void | ||
293 | do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
294 | |||
295 | |||
296 | /** | ||
297 | * Close sockets and stop testing deamons nicely | ||
298 | */ | ||
299 | static void | ||
300 | do_close (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
301 | { | ||
302 | if (peer1.op != NULL) | ||
303 | GNUNET_SCHEDULER_add_now (&do_shutdown, &peer1); | ||
304 | |||
305 | if (peer2.op != NULL) | ||
306 | GNUNET_SCHEDULER_add_now (&do_shutdown, &peer2); | ||
307 | |||
308 | if (peer3.op != NULL) | ||
309 | GNUNET_SCHEDULER_add_now (&do_shutdown, &peer3); | ||
310 | |||
311 | if (peer4.op != NULL) | ||
312 | GNUNET_SCHEDULER_add_now (&do_shutdown, &peer4); | ||
313 | |||
314 | if (GNUNET_SCHEDULER_NO_TASK != abort_task) | ||
315 | GNUNET_SCHEDULER_cancel (abort_task); | ||
316 | |||
317 | GNUNET_SCHEDULER_shutdown (); /* For shutting down testbed */ | ||
318 | } | ||
319 | |||
320 | |||
321 | static void | ||
322 | do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
323 | { | ||
324 | static int shutdown; | ||
325 | shutdown++; | ||
326 | struct PeerData* peer = (struct PeerData*) cls; | ||
327 | |||
328 | if (peer == &peer1) | ||
329 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down Peer 1!!! \n"); | ||
330 | else if (peer == &peer2) | ||
331 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down Peer 2!!! \n"); | ||
332 | else if (peer == &peer3) | ||
333 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down Peer 3!!! \n"); | ||
334 | else if (peer == &peer4) | ||
335 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down Peer 4!!! \n"); | ||
336 | |||
337 | // peer->op contains handle to the TESTBED_connect_service operation | ||
338 | // calling operation done, leads to call to vectorproduct_da | ||
339 | GNUNET_TESTBED_operation_done (peer->op); | ||
340 | peer->op = NULL; | ||
341 | |||
342 | if (shutdown == 4) | ||
343 | GNUNET_SCHEDULER_add_now (&do_close, NULL); | ||
344 | } | ||
345 | |||
346 | |||
347 | /** | ||
348 | * Something went wrong and timed out. Kill everything and set error flag | ||
349 | */ | ||
350 | static void | ||
351 | do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
352 | { | ||
353 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: ABORT due to Timeout\n"); | ||
354 | ok = GNUNET_SYSERR; | ||
355 | abort_task = 0; | ||
356 | do_close (cls, tc); | ||
357 | } | ||
358 | |||
359 | |||
360 | /** | ||
361 | * Controller event callback | ||
362 | * | ||
363 | * @param cls NULL | ||
364 | * @param event the controller event | ||
365 | */ | ||
366 | static void | ||
367 | controller_event_cb (void *cls, | ||
368 | const struct GNUNET_TESTBED_EventInformation *event) | ||
369 | { | ||
370 | switch (event->type) | ||
371 | { | ||
372 | case GNUNET_TESTBED_ET_OPERATION_FINISHED: | ||
373 | switch (setup_state) | ||
374 | { | ||
375 | case PEER1_VECTORPRODUCT_CONNECT: | ||
376 | case PEER2_VECTORPRODUCT_CONNECT: | ||
377 | GNUNET_assert (NULL == event->details.operation_finished.emsg); | ||
378 | break; | ||
379 | default: | ||
380 | GNUNET_assert (0); | ||
381 | } | ||
382 | break; | ||
383 | default: | ||
384 | GNUNET_assert (0); | ||
385 | } | ||
386 | } | ||
387 | |||
388 | |||
389 | static void | ||
390 | responder_callback (void *cls, | ||
391 | const struct GNUNET_HashCode * key, | ||
392 | enum GNUNET_VECTORPRODUCT_ResponseStatus status) | ||
393 | { | ||
394 | struct PeerData * peer = cls; | ||
395 | |||
396 | peer->callback_num++; | ||
397 | |||
398 | if (peer == &peer1) | ||
399 | { | ||
400 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer1 received callback!!!\n"); | ||
401 | } | ||
402 | else if (peer == &peer2) | ||
403 | { | ||
404 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer2 received callback!!!\n"); | ||
405 | } | ||
406 | else | ||
407 | LOG (GNUNET_ERROR_TYPE_ERROR, "Requester callback received, but peer is neither peer1 nor peer2!!!\n"); | ||
408 | |||
409 | |||
410 | if (status == GNUNET_VECTORPRODUCT_Status_Failure) | ||
411 | { | ||
412 | LOG (GNUNET_ERROR_TYPE_ERROR, "Responder Client received status failure\n"); | ||
413 | ok = -1; | ||
414 | } | ||
415 | else if (status == GNUNET_VECTORPRODUCT_Status_InvalidResponse) | ||
416 | { | ||
417 | LOG (GNUNET_ERROR_TYPE_ERROR, "Responder Client received status invalid response\n"); | ||
418 | ok = -1; | ||
419 | } | ||
420 | else if (GNUNET_VECTORPRODUCT_Status_Timeout == status) | ||
421 | { | ||
422 | LOG (GNUNET_ERROR_TYPE_ERROR, "Responder Client received timeout occured\n"); | ||
423 | ok = -1; | ||
424 | } | ||
425 | else if (GNUNET_VECTORPRODUCT_Status_ServiceDisconnected == status) | ||
426 | { | ||
427 | LOG (GNUNET_ERROR_TYPE_ERROR, "Responder Client received service disconnected!!\n"); | ||
428 | ok = -1; | ||
429 | } | ||
430 | else if (GNUNET_VECTORPRODUCT_Status_Success == status) | ||
431 | { | ||
432 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Responder Client expected response received!\n"); | ||
433 | ok = 1; | ||
434 | } | ||
435 | else | ||
436 | { | ||
437 | LOG (GNUNET_ERROR_TYPE_ERROR, "Responder Client status = %d!\n", (int) status); | ||
438 | ok = -1; | ||
439 | } | ||
440 | |||
441 | // TODO : Responder Session Complete. Shutdown Test Cleanly!!! | ||
442 | if (peer->callback_num == 2) | ||
443 | GNUNET_SCHEDULER_add_now (&do_shutdown, peer); | ||
444 | } | ||
445 | |||
446 | |||
447 | static void | ||
448 | requester_callback (void *cls, | ||
449 | const struct GNUNET_HashCode * key, | ||
450 | const struct GNUNET_PeerIdentity * peer, | ||
451 | enum GNUNET_VECTORPRODUCT_ResponseStatus status, | ||
452 | const struct GNUNET_VECTORPRODUCT_client_response *msg) | ||
453 | { | ||
454 | struct PeerData * peer_ = cls; | ||
455 | uint32_t product_len; | ||
456 | |||
457 | peer_->callback_num++; | ||
458 | |||
459 | if (peer_ == &peer3) | ||
460 | { | ||
461 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer3 received callback!!!\n"); | ||
462 | } | ||
463 | else if (peer_ == &peer4) | ||
464 | { | ||
465 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer4 received callback!!!\n"); | ||
466 | } | ||
467 | else | ||
468 | LOG (GNUNET_ERROR_TYPE_ERROR, "Requester callback received, but peer is neither peer3 nor peer4!!!\n"); | ||
469 | |||
470 | |||
471 | if (status == GNUNET_VECTORPRODUCT_Status_Failure) | ||
472 | { | ||
473 | LOG (GNUNET_ERROR_TYPE_ERROR, "Requester Client received status failure\n"); | ||
474 | ok = -1; | ||
475 | } | ||
476 | else if (status == GNUNET_VECTORPRODUCT_Status_InvalidResponse) | ||
477 | { | ||
478 | LOG (GNUNET_ERROR_TYPE_ERROR, "Requester Client received status invalid response\n"); | ||
479 | ok = -1; | ||
480 | } | ||
481 | else if (GNUNET_VECTORPRODUCT_Status_Timeout == status) | ||
482 | { | ||
483 | LOG (GNUNET_ERROR_TYPE_ERROR, "Requester Client timeout occured\n"); | ||
484 | ok = -1; | ||
485 | } | ||
486 | else if (GNUNET_VECTORPRODUCT_Status_ServiceDisconnected == status) | ||
487 | { | ||
488 | LOG (GNUNET_ERROR_TYPE_ERROR, "Requester Client service disconnected!!\n"); | ||
489 | ok = -1; | ||
490 | } | ||
491 | else if (GNUNET_VECTORPRODUCT_Status_Success != status) | ||
492 | { | ||
493 | LOG (GNUNET_ERROR_TYPE_ERROR, "Requester Client Status = %d\n", (int) status); | ||
494 | ok = -1; | ||
495 | } | ||
496 | else if (GNUNET_VECTORPRODUCT_Status_Success == status) | ||
497 | { | ||
498 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Requester client received status successful!\n"); | ||
499 | product_len = ntohl (msg->product_length); | ||
500 | |||
501 | if (0 < product_len) | ||
502 | { | ||
503 | gcry_mpi_t result; | ||
504 | gcry_error_t ret = 0; | ||
505 | size_t read = 0; | ||
506 | |||
507 | ret = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, (void*) &(msg[1]), product_len, &read); | ||
508 | |||
509 | if (0 != ret) | ||
510 | { | ||
511 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not convert to mpi to value!\n"); | ||
512 | } | ||
513 | else | ||
514 | { | ||
515 | gcry_mpi_release (result); | ||
516 | } | ||
517 | ok = 1; | ||
518 | } | ||
519 | else | ||
520 | { | ||
521 | //currently not used, but if we get more info due to MESH we will need this | ||
522 | LOG (GNUNET_ERROR_TYPE_ERROR, "Error during computation of vector product, return code: %d\n", product_len); | ||
523 | ok = -1; | ||
524 | } | ||
525 | } | ||
526 | |||
527 | if (peer_->callback_num == 2) | ||
528 | GNUNET_SCHEDULER_add_now (&do_shutdown, peer_); | ||
529 | } | ||
530 | |||
531 | |||
532 | static struct GNUNET_VECTORPRODUCT_QueueEntry * | ||
533 | requester_request (char * input_elements, | ||
534 | char * input_mask, | ||
535 | char * input_key, | ||
536 | struct PeerData * peer, | ||
537 | struct PeerData * to_peer) | ||
538 | { | ||
539 | |||
540 | |||
541 | unsigned int i; | ||
542 | uint16_t element_count = 0; | ||
543 | int32_t * elements = NULL; | ||
544 | uint16_t mask_length = 0; | ||
545 | unsigned char * mask = NULL; | ||
546 | int32_t element; | ||
547 | struct GNUNET_VECTORPRODUCT_QueueEntry *qe; | ||
548 | struct GNUNET_HashCode key; | ||
549 | int exit_loop; | ||
550 | char * begin = input_elements; | ||
551 | char * end; | ||
552 | |||
553 | GNUNET_assert (peer->vh != NULL); | ||
554 | |||
555 | GNUNET_CRYPTO_hash_from_string (input_key, &key); | ||
556 | |||
557 | exit_loop = 0; | ||
558 | /* Read input_elements, and put in elements array */ | ||
559 | do | ||
560 | { | ||
561 | unsigned int mcount = element_count; | ||
562 | //ignore empty rows of ,,,,,, | ||
563 | while (*begin == ',') | ||
564 | begin++; | ||
565 | // get the length of the current element and replace , with null | ||
566 | for (end = begin; *end && *end != ','; end++); | ||
567 | |||
568 | if (*end == '\0') | ||
569 | exit_loop = 1; | ||
570 | |||
571 | |||
572 | if (1 != sscanf (begin, "%" SCNd32, &element)) | ||
573 | { | ||
574 | FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin); | ||
575 | ok = -1; | ||
576 | return NULL; | ||
577 | } | ||
578 | |||
579 | GNUNET_array_append (elements, mcount, element); | ||
580 | element_count++; | ||
581 | |||
582 | begin = ++end; | ||
583 | } | ||
584 | while (!exit_loop && element_count < max_mids); | ||
585 | GNUNET_assert (elements != NULL); | ||
586 | GNUNET_assert (element_count >= 1); | ||
587 | |||
588 | /* Read input_mask and read in mask array */ | ||
589 | mask_length = element_count / 8 + (element_count % 8 ? 1 : 0); | ||
590 | mask = GNUNET_malloc ((element_count / 8) + 2); | ||
591 | GNUNET_assert (NULL != mask); | ||
592 | if (NULL != input_mask) | ||
593 | { | ||
594 | begin = input_mask; | ||
595 | unsigned short mask_count = 0; | ||
596 | int exit_loop = 0; | ||
597 | |||
598 | do | ||
599 | { | ||
600 | //ignore empty rows of ,,,,,, | ||
601 | while (* begin == ',') | ||
602 | begin++; | ||
603 | // get the length of the current element and replace , with null | ||
604 | // gnunet_ascii-armor uses base32, thus we can use , as separator! | ||
605 | for (end = begin; *end && *end != ','; end++); | ||
606 | |||
607 | if (*end == '\0') | ||
608 | exit_loop = 1; | ||
609 | |||
610 | |||
611 | if (1 != sscanf (begin, "%" SCNd32, &element)) | ||
612 | { | ||
613 | FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin); | ||
614 | ok = -1; | ||
615 | return NULL; | ||
616 | } | ||
617 | |||
618 | GNUNET_assert (mask_count <= element_count); | ||
619 | |||
620 | if (element) | ||
621 | mask[mask_count / 8] = mask[mask_count / 8] | 1 << (mask_count % 8); | ||
622 | |||
623 | mask_count++; | ||
624 | begin = ++end; | ||
625 | } | ||
626 | while (!exit_loop); | ||
627 | // +1 to see if we would have more data, which would indicate malformed/superficial input | ||
628 | GNUNET_assert (mask_count == element_count); | ||
629 | } | ||
630 | else | ||
631 | { | ||
632 | for (i = 0; i <= mask_length; i++) | ||
633 | mask[i] = UCHAR_MAX; // all 1's | ||
634 | } | ||
635 | |||
636 | qe = GNUNET_VECTORPRODUCT_request (peer->vh, | ||
637 | &key, | ||
638 | &to_peer->our_id, | ||
639 | element_count, | ||
640 | mask_length, | ||
641 | elements, mask, | ||
642 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60), | ||
643 | &requester_callback, | ||
644 | peer); | ||
645 | |||
646 | if (qe == NULL) | ||
647 | { | ||
648 | LOG(GNUNET_ERROR_TYPE_WARNING, "Could not send request to vectorproduct service! Exitting!"); | ||
649 | ok = -1; | ||
650 | return NULL; | ||
651 | } | ||
652 | |||
653 | return qe; | ||
654 | } | ||
655 | |||
656 | |||
657 | /** | ||
658 | * Function prepares the message to be sent by peer1 to its vectorproduct service | ||
659 | * to prepare response, and wait for a request session to be initiated by peer1 | ||
660 | */ | ||
661 | static struct GNUNET_VECTORPRODUCT_QueueEntry * | ||
662 | responder_prepare_response (char * input_elements, | ||
663 | char * input_mask, | ||
664 | char * input_key, | ||
665 | struct PeerData * peer) | ||
666 | { | ||
667 | GNUNET_assert (peer->vh != NULL); | ||
668 | |||
669 | unsigned int i; | ||
670 | uint16_t element_count = 0; | ||
671 | int32_t * elements = NULL; | ||
672 | unsigned short mask_length = 0; | ||
673 | unsigned char * mask = NULL; | ||
674 | int32_t element; | ||
675 | struct GNUNET_VECTORPRODUCT_QueueEntry *qe; | ||
676 | struct GNUNET_HashCode key; | ||
677 | int exit_loop; | ||
678 | char * begin; | ||
679 | char * end; | ||
680 | |||
681 | GNUNET_CRYPTO_hash_from_string (input_key, &key); | ||
682 | |||
683 | /* Read input_elements, and put in elements array */ | ||
684 | exit_loop = 0; | ||
685 | begin = input_elements; | ||
686 | do | ||
687 | { | ||
688 | unsigned int mcount = element_count; | ||
689 | //ignore empty rows of ,,,,,, | ||
690 | while (*begin == ',') | ||
691 | begin++; | ||
692 | // get the length of the current element and replace , with null | ||
693 | for (end = begin; *end && *end != ','; end++); | ||
694 | |||
695 | if (*end == '\0') | ||
696 | exit_loop = 1; | ||
697 | |||
698 | if (1 != sscanf (begin, "%" SCNd32, &element)) | ||
699 | { | ||
700 | FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin); | ||
701 | ok = -1; | ||
702 | return NULL; | ||
703 | } | ||
704 | |||
705 | GNUNET_array_append (elements, mcount, element); | ||
706 | element_count++; | ||
707 | |||
708 | begin = ++end; | ||
709 | } | ||
710 | while (!exit_loop && element_count < max_mids); | ||
711 | GNUNET_assert (elements != NULL); | ||
712 | GNUNET_assert (element_count >= 1); | ||
713 | |||
714 | /* Read input_mask and read in mask array */ | ||
715 | mask_length = element_count / 8 + (element_count % 8 ? 1 : 0); | ||
716 | mask = GNUNET_malloc ((element_count / 8) + 2); | ||
717 | GNUNET_assert (NULL != mask); | ||
718 | if (NULL != input_mask) | ||
719 | { | ||
720 | begin = input_mask; | ||
721 | unsigned short mask_count = 0; | ||
722 | int exit_loop = 0; | ||
723 | |||
724 | do | ||
725 | { | ||
726 | //ignore empty rows of ,,,,,, | ||
727 | while (* begin == ',') | ||
728 | begin++; | ||
729 | // get the length of the current element and replace , with null | ||
730 | // gnunet_ascii-armor uses base32, thus we can use , as separator! | ||
731 | for (end = begin; *end && *end != ','; end++); | ||
732 | |||
733 | if (*end == '\0') | ||
734 | exit_loop = 1; | ||
735 | |||
736 | if (1 != sscanf (begin, "%" SCNd32, &element)) | ||
737 | { | ||
738 | FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin); | ||
739 | ok = -1; | ||
740 | return NULL; | ||
741 | } | ||
742 | |||
743 | GNUNET_assert (mask_count <= element_count); | ||
744 | |||
745 | if (element) | ||
746 | mask[mask_count / 8] = mask[mask_count / 8] | 1 << (mask_count % 8); | ||
747 | |||
748 | mask_count++; | ||
749 | begin = ++end; | ||
750 | } | ||
751 | while (!exit_loop); | ||
752 | // +1 to see if we would have more data, which would indicate malformed/superficial input | ||
753 | GNUNET_assert (mask_count == element_count); | ||
754 | } | ||
755 | else | ||
756 | { | ||
757 | for (i = 0; i <= mask_length; i++) | ||
758 | mask[i] = UCHAR_MAX; // all 1's | ||
759 | } | ||
760 | |||
761 | qe = GNUNET_VECTORPRODUCT_prepare_response (peer->vh, | ||
762 | &key, | ||
763 | element_count, | ||
764 | elements, | ||
765 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60), | ||
766 | &responder_callback, | ||
767 | peer); | ||
768 | |||
769 | if (qe == NULL) | ||
770 | { | ||
771 | LOG(GNUNET_ERROR_TYPE_ERROR, "Could not send request to vectorproduct service! Exitting!"); | ||
772 | ok = -1; | ||
773 | return NULL; | ||
774 | } | ||
775 | |||
776 | return qe; | ||
777 | } | ||
778 | |||
779 | |||
780 | static void | ||
781 | request_task (void *cls, | ||
782 | const struct GNUNET_SCHEDULER_TaskContext | ||
783 | * tc) | ||
784 | { | ||
785 | struct PeerData * peer = cls; | ||
786 | |||
787 | requester_request (peer->input_elements, peer->input_mask, peer->input_keys[peer->request_num], peer, peer->peers[peer->request_num]); | ||
788 | peer->request_num++; | ||
789 | return; | ||
790 | } | ||
791 | |||
792 | |||
793 | static void | ||
794 | prepare_response_task (void *cls, | ||
795 | const struct GNUNET_SCHEDULER_TaskContext | ||
796 | * tc) | ||
797 | { | ||
798 | struct PeerData * peer = cls; | ||
799 | |||
800 | responder_prepare_response (peer->input_elements, peer->input_mask, peer->input_keys[peer->request_num], peer); | ||
801 | peer->request_num++; | ||
802 | return; | ||
803 | } | ||
804 | |||
805 | |||
806 | /** | ||
807 | * Adapter function called to destroy a connection to | ||
808 | * a service. This function is called when GNUNET_TESTBED_operation_done is | ||
809 | * called for peer->op, which holds the handle for GNUNET_TESTBED_service_connect | ||
810 | * operation. | ||
811 | * | ||
812 | * @param cls closure | ||
813 | * @param op_result service handle returned from the connect adapter | ||
814 | */ | ||
815 | static void | ||
816 | vectorproduct_da (void *cls, void *op_result) | ||
817 | { | ||
818 | struct PeerData* peer = (struct PeerData*) cls; | ||
819 | |||
820 | GNUNET_VECTORPRODUCT_disconnect (peer->vh); | ||
821 | return; | ||
822 | |||
823 | GNUNET_assert (0); | ||
824 | } | ||
825 | |||
826 | |||
827 | /** | ||
828 | * Adapter function called to establish a connection to | ||
829 | * a service. This function is called to by GNUNET_TESTBED_service_connect. | ||
830 | * | ||
831 | * @param cls closure | ||
832 | * @param cfg configuration of the peer to connect to; will be available until | ||
833 | * GNUNET_TESTBED_operation_done() is called on the operation returned | ||
834 | * from GNUNET_TESTBED_service_connect() | ||
835 | * @return service handle to return in 'op_result', NULL on error | ||
836 | */ | ||
837 | static void * | ||
838 | vectorproduct_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
839 | { | ||
840 | struct PeerData *p = cls; | ||
841 | |||
842 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", (&peer1 == p) ? 1 : 2, | ||
843 | GNUNET_i2s (&p->our_id)); | ||
844 | |||
845 | switch (setup_state) | ||
846 | { | ||
847 | case PEER1_VECTORPRODUCT_CONNECT: | ||
848 | /* Connect peer 2 to vectorproduct service */ | ||
849 | { | ||
850 | peer2.op = GNUNET_TESTBED_service_connect (&peer2, peer2.peer, "vectorproduct", | ||
851 | NULL, NULL, vectorproduct_ca, | ||
852 | vectorproduct_da, &peer2); | ||
853 | setup_state = PEER2_VECTORPRODUCT_CONNECT; | ||
854 | } | ||
855 | |||
856 | peer1.vh = GNUNET_VECTORPRODUCT_connect (cfg); | ||
857 | return peer1.vh; | ||
858 | |||
859 | case PEER2_VECTORPRODUCT_CONNECT: | ||
860 | /* Connect peer 3 to vectorproduct service */ | ||
861 | { | ||
862 | peer3.op = GNUNET_TESTBED_service_connect (&peer3, peer3.peer, "vectorproduct", | ||
863 | NULL, NULL, vectorproduct_ca, | ||
864 | vectorproduct_da, &peer3); | ||
865 | setup_state = PEER3_VECTORPRODUCT_CONNECT; | ||
866 | } | ||
867 | |||
868 | peer2.vh = GNUNET_VECTORPRODUCT_connect (cfg); | ||
869 | return peer2.vh; | ||
870 | |||
871 | case PEER3_VECTORPRODUCT_CONNECT: | ||
872 | /* Connect peer 4 to vectorproduct service */ | ||
873 | { | ||
874 | peer4.op = GNUNET_TESTBED_service_connect (&peer4, peer4.peer, "vectorproduct", | ||
875 | NULL, NULL, vectorproduct_ca, | ||
876 | vectorproduct_da, &peer4); | ||
877 | setup_state = PEER4_VECTORPRODUCT_CONNECT; | ||
878 | } | ||
879 | |||
880 | peer3.vh = GNUNET_VECTORPRODUCT_connect (cfg); | ||
881 | return peer3.vh; | ||
882 | |||
883 | case PEER4_VECTORPRODUCT_CONNECT: | ||
884 | peer4.vh = GNUNET_VECTORPRODUCT_connect (cfg); | ||
885 | |||
886 | /* Schedule the tasks to issue prepare_response calls from peer1 and peer2 | ||
887 | * for peer3 and peer4. | ||
888 | */ | ||
889 | GNUNET_SCHEDULER_add_now (&prepare_response_task, &peer1); | ||
890 | GNUNET_SCHEDULER_add_now (&prepare_response_task, &peer1); | ||
891 | GNUNET_SCHEDULER_add_now (&prepare_response_task, &peer2); | ||
892 | GNUNET_SCHEDULER_add_now (&prepare_response_task, &peer2); | ||
893 | |||
894 | /* | ||
895 | * Schedule the tasks to issue requests calls from peer3 and peer4 | ||
896 | * to peer1 and peer2 | ||
897 | */ | ||
898 | GNUNET_SCHEDULER_add_now (&request_task, &peer3); | ||
899 | GNUNET_SCHEDULER_add_now (&request_task, &peer3); | ||
900 | GNUNET_SCHEDULER_add_now (&request_task, &peer4); | ||
901 | GNUNET_SCHEDULER_add_now (&request_task, &peer4); | ||
902 | |||
903 | return peer2.vh; | ||
904 | default: | ||
905 | GNUNET_assert (0); | ||
906 | } | ||
907 | } | ||
908 | |||
909 | |||
910 | /** | ||
911 | * Callback to be called when the requested peer information is available | ||
912 | * | ||
913 | * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information() | ||
914 | * @param op the operation this callback corresponds to | ||
915 | * @param pinfo the result; will be NULL if the operation has failed | ||
916 | * @param emsg error message if the operation has failed; will be NULL if the | ||
917 | * operation is successfull | ||
918 | */ | ||
919 | static void | ||
920 | peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op_, | ||
921 | const struct GNUNET_TESTBED_PeerInformation *pinfo, | ||
922 | const char *emsg) | ||
923 | { | ||
924 | GNUNET_assert (NULL == emsg); | ||
925 | GNUNET_assert (op == op_); | ||
926 | switch (setup_state) | ||
927 | { | ||
928 | case PEER1_GET_IDENTITY: | ||
929 | { | ||
930 | memcpy (&peer1.our_id, pinfo->result.id, | ||
931 | sizeof (struct GNUNET_PeerIdentity)); | ||
932 | GNUNET_TESTBED_operation_done (op); | ||
933 | |||
934 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 1 id: %s\n", GNUNET_i2s_full | ||
935 | (&peer1.our_id)); | ||
936 | |||
937 | /* Request for peer id of peer 2*/ | ||
938 | op = GNUNET_TESTBED_peer_get_information (peer2.peer, | ||
939 | GNUNET_TESTBED_PIT_IDENTITY, | ||
940 | &peerinfo_cb, NULL); | ||
941 | setup_state = PEER2_GET_IDENTITY; | ||
942 | } | ||
943 | break; | ||
944 | case PEER2_GET_IDENTITY: | ||
945 | { | ||
946 | memcpy (&peer2.our_id, pinfo->result.id, | ||
947 | sizeof (struct GNUNET_PeerIdentity)); | ||
948 | GNUNET_TESTBED_operation_done (op); | ||
949 | |||
950 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 2 id: %s\n", GNUNET_i2s_full | ||
951 | (&peer2.our_id)); | ||
952 | |||
953 | /* Request for peer id of peer 3*/ | ||
954 | op = GNUNET_TESTBED_peer_get_information (peer3.peer, | ||
955 | GNUNET_TESTBED_PIT_IDENTITY, | ||
956 | &peerinfo_cb, NULL); | ||
957 | setup_state = PEER3_GET_IDENTITY; | ||
958 | } | ||
959 | break; | ||
960 | case PEER3_GET_IDENTITY: | ||
961 | { | ||
962 | memcpy (&peer3.our_id, pinfo->result.id, | ||
963 | sizeof (struct GNUNET_PeerIdentity)); | ||
964 | GNUNET_TESTBED_operation_done (op); | ||
965 | |||
966 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 3 id: %s\n", GNUNET_i2s_full | ||
967 | (&peer3.our_id)); | ||
968 | |||
969 | /* Request for peer id of peer 4*/ | ||
970 | op = GNUNET_TESTBED_peer_get_information (peer4.peer, | ||
971 | GNUNET_TESTBED_PIT_IDENTITY, | ||
972 | &peerinfo_cb, NULL); | ||
973 | setup_state = PEER4_GET_IDENTITY; | ||
974 | } | ||
975 | break; | ||
976 | case PEER4_GET_IDENTITY: | ||
977 | { | ||
978 | memcpy (&peer4.our_id, pinfo->result.id, | ||
979 | sizeof (struct GNUNET_PeerIdentity)); | ||
980 | GNUNET_TESTBED_operation_done (op); | ||
981 | |||
982 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 2 id: %s\n", GNUNET_i2s_full | ||
983 | (&peer2.our_id)); | ||
984 | |||
985 | /* Connect peer 1 to vectorproduct service */ | ||
986 | peer1.op = GNUNET_TESTBED_service_connect (&peer1, peer1.peer, "vectorproduct", | ||
987 | NULL, NULL, vectorproduct_ca, | ||
988 | vectorproduct_da, &peer1); | ||
989 | setup_state = PEER1_VECTORPRODUCT_CONNECT; | ||
990 | } | ||
991 | break; | ||
992 | default: | ||
993 | GNUNET_assert (0); | ||
994 | } | ||
995 | } | ||
996 | |||
997 | |||
998 | /** | ||
999 | * Signature of a main function for a testcase. | ||
1000 | * | ||
1001 | * @param cls closure | ||
1002 | * @param num_peers number of peers in 'peers' | ||
1003 | * @param peers handle to peers run in the testbed | ||
1004 | */ | ||
1005 | static void | ||
1006 | test_master (void *cls, unsigned int num_peers, | ||
1007 | struct GNUNET_TESTBED_Peer **peers) | ||
1008 | { | ||
1009 | GNUNET_assert (NULL != peers); | ||
1010 | GNUNET_assert (NULL != peers[0]); | ||
1011 | GNUNET_assert (NULL != peers[1]); | ||
1012 | GNUNET_assert (NULL != peers[2]); | ||
1013 | GNUNET_assert (NULL != peers[3]); | ||
1014 | peer1.peer = peers[0]; | ||
1015 | peer1.input_elements = input_elements_peer1; | ||
1016 | peer1.input_mask = input_mask_peer1; | ||
1017 | peer1.request_num = 0; | ||
1018 | peer1.callback_num = 0; | ||
1019 | peer1.input_keys[0] = input_key_p1_p3; | ||
1020 | peer1.input_keys[1] = input_key_p1_p4; | ||
1021 | |||
1022 | peer2.peer = peers[1]; | ||
1023 | peer2.input_elements = input_elements_peer2; | ||
1024 | peer2.input_mask = input_mask_peer2; | ||
1025 | peer2.request_num = 0; | ||
1026 | peer2.callback_num = 0; | ||
1027 | peer2.input_keys[0] = input_key_p2_p3; | ||
1028 | peer2.input_keys[1] = input_key_p2_p4; | ||
1029 | |||
1030 | peer3.peer = peers[2]; | ||
1031 | peer3.input_elements = input_elements_peer3; | ||
1032 | peer3.input_mask = input_mask_peer3; | ||
1033 | peer3.request_num = 0; | ||
1034 | peer3.callback_num = 0; | ||
1035 | peer3.input_keys[0] = input_key_p1_p3; | ||
1036 | peer3.input_keys[1] = input_key_p2_p3; | ||
1037 | peer3.peers[0] = &peer1; | ||
1038 | peer3.peers[1] = &peer2; | ||
1039 | |||
1040 | |||
1041 | peer4.peer = peers[3]; | ||
1042 | peer4.input_elements = input_elements_peer4; | ||
1043 | peer4.input_mask = input_mask_peer4; | ||
1044 | peer4.request_num = 0; | ||
1045 | peer4.callback_num = 0; | ||
1046 | peer4.input_keys[0] = input_key_p1_p4; | ||
1047 | peer4.input_keys[1] = input_key_p2_p4; | ||
1048 | peer4.peers[0] = &peer1; | ||
1049 | peer4.peers[1] = &peer2; | ||
1050 | |||
1051 | /* Get the peer identity and configuration of peer 1 */ | ||
1052 | op = GNUNET_TESTBED_peer_get_information (peer1.peer, | ||
1053 | GNUNET_TESTBED_PIT_IDENTITY, | ||
1054 | &peerinfo_cb, NULL); | ||
1055 | setup_state = PEER1_GET_IDENTITY; | ||
1056 | abort_task = | ||
1057 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
1058 | (GNUNET_TIME_UNIT_SECONDS, 120), &do_abort, | ||
1059 | NULL); | ||
1060 | } | ||
1061 | |||
1062 | |||
1063 | /** | ||
1064 | * Main function | ||
1065 | */ | ||
1066 | int | ||
1067 | main (int argc, char **argv) | ||
1068 | { | ||
1069 | uint64_t event_mask; | ||
1070 | |||
1071 | ok = GNUNET_NO; | ||
1072 | event_mask = 0; | ||
1073 | event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); | ||
1074 | max_mids = (GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_MessageHeader)) | ||
1075 | / sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1; | ||
1076 | (void) GNUNET_TESTBED_test_run ("test_vectorproduct_api_4peers", | ||
1077 | "test_vectorproduct_api_data.conf", | ||
1078 | NUM_PEERS, event_mask, &controller_event_cb, | ||
1079 | NULL, | ||
1080 | &test_master, NULL); | ||
1081 | if (GNUNET_SYSERR == ok) | ||
1082 | return 1; | ||
1083 | return 0; | ||
1084 | } | ||