-again trying to delete old vectorproduct dir
[oweals/gnunet.git] / src / scalarproduct / test_scalarproduct_api_4peers.c
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  * scalarproduct 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 scalarproduct/test_scalarproduct_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_scalarproduct_service.h"
62 #include "gnunet_protocols.h"
63
64 #define LOG(kind,...) GNUNET_log_from (kind, "test-scalarproduct-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_SCALARPRODUCT_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_SCALARPRODUCT_CONNECT,
155
156   /**
157    * Connect to stream service of peer 2
158    */
159   PEER2_SCALARPRODUCT_CONNECT,
160
161   /**
162    * Connect to stream service of peer 3
163    */
164   PEER3_SCALARPRODUCT_CONNECT,
165
166   /**
167    * Connect to stream service of peer 4
168    */
169   PEER4_SCALARPRODUCT_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 scalarproduct_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_SCALARPRODUCT_CONNECT:
376         case PEER2_SCALARPRODUCT_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_SCALARPRODUCT_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_SCALARPRODUCT_Status_Failure)
411     {
412       LOG (GNUNET_ERROR_TYPE_ERROR, "Responder Client received status failure\n");
413       ok = -1;
414     }
415   else if (status == GNUNET_SCALARPRODUCT_Status_InvalidResponse)
416     {
417       LOG (GNUNET_ERROR_TYPE_ERROR, "Responder Client received status invalid response\n");
418       ok = -1;
419     }
420   else if (GNUNET_SCALARPRODUCT_Status_Timeout == status)
421     {
422       LOG (GNUNET_ERROR_TYPE_ERROR, "Responder Client received timeout occured\n");
423       ok = -1;
424     }
425   else if (GNUNET_SCALARPRODUCT_Status_ServiceDisconnected == status)
426     {
427       LOG (GNUNET_ERROR_TYPE_ERROR, "Responder Client received service disconnected!!\n");
428       ok = -1;
429     }
430   else if (GNUNET_SCALARPRODUCT_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_SCALARPRODUCT_ResponseStatus status,
452                     const struct GNUNET_SCALARPRODUCT_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_SCALARPRODUCT_Status_Failure)
472     {
473       LOG (GNUNET_ERROR_TYPE_ERROR, "Requester Client received status failure\n");
474       ok = -1;
475     }
476   else if (status == GNUNET_SCALARPRODUCT_Status_InvalidResponse)
477     {
478       LOG (GNUNET_ERROR_TYPE_ERROR, "Requester Client received status invalid response\n");
479       ok = -1;
480     }
481   else if (GNUNET_SCALARPRODUCT_Status_Timeout == status)
482     {
483       LOG (GNUNET_ERROR_TYPE_ERROR, "Requester Client timeout occured\n");
484       ok = -1;
485     }
486   else if (GNUNET_SCALARPRODUCT_Status_ServiceDisconnected == status)
487     {
488       LOG (GNUNET_ERROR_TYPE_ERROR, "Requester Client service disconnected!!\n");
489       ok = -1;
490     }
491   else if (GNUNET_SCALARPRODUCT_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_SCALARPRODUCT_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_SCALARPRODUCT_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_SCALARPRODUCT_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_SCALARPRODUCT_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 scalarproduct 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 scalarproduct service
659  * to prepare response, and wait for a request session to be initiated by peer1
660  */
661 static struct GNUNET_SCALARPRODUCT_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_SCALARPRODUCT_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_SCALARPRODUCT_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 scalarproduct 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 scalarproduct_da (void *cls, void *op_result)
817 {
818   struct PeerData* peer = (struct PeerData*) cls;
819
820   GNUNET_SCALARPRODUCT_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 scalarproduct_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_SCALARPRODUCT_CONNECT:
848       /* Connect peer 2 to scalarproduct service */
849       {
850         peer2.op = GNUNET_TESTBED_service_connect (&peer2, peer2.peer, "scalarproduct",
851                                                    NULL, NULL, scalarproduct_ca,
852                                                    scalarproduct_da, &peer2);
853         setup_state = PEER2_SCALARPRODUCT_CONNECT;
854       }
855
856       peer1.vh = GNUNET_SCALARPRODUCT_connect (cfg);
857       return peer1.vh;
858
859     case PEER2_SCALARPRODUCT_CONNECT:
860       /* Connect peer 3 to scalarproduct service */
861       {
862         peer3.op = GNUNET_TESTBED_service_connect (&peer3, peer3.peer, "scalarproduct",
863                                                    NULL, NULL, scalarproduct_ca,
864                                                    scalarproduct_da, &peer3);
865         setup_state = PEER3_SCALARPRODUCT_CONNECT;
866       }
867
868       peer2.vh = GNUNET_SCALARPRODUCT_connect (cfg);
869       return peer2.vh;
870
871     case PEER3_SCALARPRODUCT_CONNECT:
872       /* Connect peer 4 to scalarproduct service */
873       {
874         peer4.op = GNUNET_TESTBED_service_connect (&peer4, peer4.peer, "scalarproduct",
875                                                    NULL, NULL, scalarproduct_ca,
876                                                    scalarproduct_da, &peer4);
877         setup_state = PEER4_SCALARPRODUCT_CONNECT;
878       }
879
880       peer3.vh = GNUNET_SCALARPRODUCT_connect (cfg);
881       return peer3.vh;
882
883     case PEER4_SCALARPRODUCT_CONNECT:
884       peer4.vh = GNUNET_SCALARPRODUCT_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 scalarproduct service */
986         peer1.op = GNUNET_TESTBED_service_connect (&peer1, peer1.peer, "scalarproduct",
987                                                    NULL, NULL, scalarproduct_ca,
988                                                    scalarproduct_da, &peer1);
989         setup_state = PEER1_SCALARPRODUCT_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_scalarproduct_api_4peers",
1077                                   "test_scalarproduct_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 }