-remove trailing whitespace
[oweals/gnunet.git] / src / scalarproduct / test_scalarproduct_api.c
1 /*
2      This file is part of GNUnet.
3      (C) 2013 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19  */
20
21 /**
22  * Aim of test_scalarproduct_api : This test creates two peers. Peer1 is the
23  * responder peer, Bob and Peer2 is the initiator peer, Alice. Both peers
24  * connect to VectorProduct Service, and use the API to issue requests to
25  * service. Test passes, when the expected scalar product is received from the
26  * service.
27  */
28
29 /**
30  * @file scalarproduct/testbed_scalarproduct_api.c
31  * @brief VectorProduct API testing between 4 peers using testing API
32  * @author Gaurav Kukreja
33  * @author Christian Fuchs
34  */
35
36 #include <string.h>
37
38 #include <inttypes.h>
39 #include "platform.h"
40 #include "gnunet_util_lib.h"
41 #include "gnunet_testbed_service.h"
42 #include "gnunet_common.h"
43 #include "gnunet_scalarproduct_service.h"
44 #include "gnunet_protocols.h"
45
46 #define NUM_PEERS 2
47
48 #define LOG(kind,...) GNUNET_log_from (kind, "test-scalarproduct-api",__VA_ARGS__)
49
50 /**
51  * Structure for holding peer's sockets and IO Handles
52  */
53 struct PeerData
54 {
55   /**
56    * Handle to testbed peer
57    */
58   struct GNUNET_TESTBED_Peer *peer;
59
60   /**
61    * The service connect operation to stream
62    */
63   struct GNUNET_TESTBED_Operation *op;
64
65   /**
66    * Our Peer id
67    */
68   struct GNUNET_PeerIdentity our_id;
69
70   /**
71    * Pointer to Vector Product Handle
72    */
73   struct GNUNET_SCALARPRODUCT_Handle *vh;
74 };
75
76 /**
77  * Different states in test setup
78  */
79 enum SetupState
80 {
81   /**
82    * Get the identity of peer 1
83    */
84   PEER1_GET_IDENTITY,
85
86   /**
87    * Get the identity of peer 2
88    */
89   PEER2_GET_IDENTITY,
90
91   /**
92    * Connect to stream service of peer 1
93    */
94   PEER1_SCALARPRODUCT_CONNECT,
95
96   /**
97    * Connect to stream service of peer 2
98    */
99   PEER2_SCALARPRODUCT_CONNECT
100
101 };
102
103 /******************************************************************************
104  *** Global Variables                            *****************************
105  ******************************************************************************/
106
107 /**
108  * Maximum allowed message-ids we can check in one go (with one GNUNET_message)
109  */
110 static unsigned int max_mids;
111
112 /**
113  * Session Key used by both the test peers
114  */
115 char input_key[103] = "helloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhe";
116
117 /**
118  * Input elements for peer1
119  */
120 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";
121 //char input_elements_peer1[] = "11,11,11";
122
123 /**
124  * Input Mask for peer 1
125  */
126 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";
127 //char input_mask_peer1[] = "1,1,1";
128
129 /**
130  * the array of converted message IDs to send to our service
131  */
132 static int32_t * elements_peer1 = NULL;
133
134 /**
135  * Number of elements
136  */
137 uint16_t element_count_peer1 = 0;
138
139 /**
140  * Input elements for peer2
141  */
142 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";
143 //char input_elements_peer2[] = "11,11,11";
144
145 /**
146  * Input Mask for peer 2
147  */
148 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";
149 //char input_mask_peer2[] = "1,1,1";
150
151 /**
152  * the array of converted message IDs to send to our service
153  */
154 static int32_t * elements_peer2 = NULL;
155
156 /**
157  * the array of converted message IDs to send to our service
158  */
159 static unsigned char * mask_peer2 = NULL;
160
161 /**
162  * Number of elements
163  */
164 uint16_t element_count_peer2 = 0;
165
166 /**
167  * Data context for peer 1
168  */
169 static struct PeerData peer1;
170
171 /**
172  * Data context for peer 2
173  */
174 static struct PeerData peer2;
175
176 /**
177  * Various states during test setup
178  */
179 static enum SetupState setup_state;
180
181 /**
182  * Testbed operation handle
183  */
184 static struct GNUNET_TESTBED_Operation *op;
185
186 static int ok;
187
188 static int responder_ok;
189
190 static int requester_ok;
191
192 static GNUNET_SCHEDULER_TaskIdentifier abort_task;
193 /******************************************************************************
194  *** Static Functions                             *****************************
195  ******************************************************************************/
196
197 static void
198 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
199
200
201 /**
202  * Close sockets and stop testing deamons nicely
203  */
204 static void
205 do_close (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
206 {
207
208   if (peer1.op != NULL)
209     do_shutdown (&peer1, NULL);
210
211   if (peer2.op != NULL)
212     do_shutdown (&peer2, NULL);
213
214   if (GNUNET_SCHEDULER_NO_TASK != abort_task)
215     GNUNET_SCHEDULER_cancel (abort_task);
216
217   GNUNET_SCHEDULER_shutdown (); /* For shutting down testbed */
218 }
219
220 /**
221  * Shutdown a peer
222  *
223  * @param cls pointer to "struct PeerData" of the peer to be disconnected
224  * @param tc Task Context
225  */
226 static void
227 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
228 {
229   static int shutdown;
230   shutdown++;
231   struct PeerData* peer = (struct PeerData*) cls;
232
233   if (peer == &peer1)
234     LOG (GNUNET_ERROR_TYPE_INFO, "Disconnecting Peer1\n\n");
235   else if (peer == &peer2)
236     LOG (GNUNET_ERROR_TYPE_INFO, "Disconnecting Peer2\n\n");
237
238   // peer->op contains handle to the TESTBED_connect_service operation
239   // calling operation done, leads to call to scalarproduct_da
240   if (peer->op != NULL)
241     {
242       GNUNET_TESTBED_operation_done (peer->op);
243       peer->op = NULL;
244     }
245
246   if (shutdown >= 2)
247     GNUNET_SCHEDULER_add_now (&do_close, NULL);
248 }
249
250
251 /**
252  * Something went wrong and timed out. Kill everything and set error flag
253  */
254 static void
255 do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
256 {
257   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: ABORT due to Timeout\n");
258   ok = GNUNET_SYSERR;
259   abort_task = 0;
260   do_close (cls, tc);
261 }
262
263
264 /**
265  * Controller event callback
266  *
267  * @param cls NULL
268  * @param event the controller event
269  */
270 static void
271 controller_event_cb (void *cls,
272                      const struct GNUNET_TESTBED_EventInformation *event)
273 {
274   GNUNET_assert (event->type == GNUNET_TESTBED_ET_OPERATION_FINISHED);
275
276   switch (setup_state)
277     {
278     case PEER1_SCALARPRODUCT_CONNECT:
279     case PEER2_SCALARPRODUCT_CONNECT:
280       GNUNET_assert (NULL == event->details.operation_finished.emsg);
281       break;
282     default:
283       GNUNET_assert (0);
284     }
285 }
286
287
288 static void
289 responder_callback (void *cls,
290                     const struct GNUNET_HashCode * key,
291                     enum GNUNET_SCALARPRODUCT_ResponseStatus status)
292 {
293
294   if (status == GNUNET_SCALARPRODUCT_Status_Failure)
295     {
296       LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received status failure\n");
297       responder_ok = -1;
298     }
299   else if (status == GNUNET_SCALARPRODUCT_Status_InvalidResponse)
300     {
301       LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received status invalid response\n");
302       responder_ok = -1;
303     }
304   else if (GNUNET_SCALARPRODUCT_Status_Timeout == status)
305     {
306       LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received timeout occured\n");
307       responder_ok = -1;
308     }
309   else if (GNUNET_SCALARPRODUCT_Status_ServiceDisconnected == status)
310     {
311       LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received service disconnected!!\n");
312       responder_ok = -1;
313     }
314   else if (GNUNET_SCALARPRODUCT_Status_Success == status)
315     {
316       LOG (GNUNET_ERROR_TYPE_INFO, "Responder Client expected response received!\n");
317       responder_ok = 1;
318     }
319   else
320     {
321       LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client status = %d!\n", (int) status);
322       responder_ok = -1;
323     }
324   // TODO : Responder Session Complete. Shutdown Test Cleanly!!!
325   //do_shutdown(&peer1, NULL);
326   GNUNET_SCHEDULER_add_now (&do_shutdown, &peer1);
327   return;
328 }
329
330
331 static void
332 requester_callback (void *cls,
333         const struct GNUNET_HashCode * key,
334         const struct GNUNET_PeerIdentity * peer,
335         enum GNUNET_SCALARPRODUCT_ResponseStatus status,
336         const struct GNUNET_SCALARPRODUCT_client_response *msg)
337 {
338   uint32_t product_len;
339
340   if (status == GNUNET_SCALARPRODUCT_Status_Failure)
341     {
342       LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client received status failure\n");
343       requester_ok = -1;
344     }
345   else if (status == GNUNET_SCALARPRODUCT_Status_InvalidResponse)
346     {
347       LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client received status invalid response\n");
348       requester_ok = -1;
349     }
350   else if (GNUNET_SCALARPRODUCT_Status_Timeout == status)
351     {
352       LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client timeout occured\n");
353       requester_ok = -1;
354     }
355   else if (GNUNET_SCALARPRODUCT_Status_ServiceDisconnected == status)
356     {
357       LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client service disconnected!!\n");
358       requester_ok = -1;
359     }
360   else if (GNUNET_SCALARPRODUCT_Status_Success != status)
361     {
362       LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client Status = %d\n", (int) status);
363       requester_ok = -1;
364     }
365   else if (GNUNET_SCALARPRODUCT_Status_Success == status)
366     {
367       LOG (GNUNET_ERROR_TYPE_INFO, "Requester Client expected response received!\n");
368       product_len = ntohl(msg->product_length);
369
370       if (0 < product_len)
371         {
372           gcry_mpi_t result;
373           gcry_error_t ret = 0;
374           size_t read = 0;
375           ret = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, &msg[1], product_len, &read);
376
377           if (0 != ret)
378             {
379               GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Could not convert to mpi to value!\n");
380               ok = -1;
381             }
382           else
383             {
384               uint16_t i = 0;
385
386               // calculate expected product
387               gcry_mpi_t expected_result;
388               gcry_mpi_t v1;
389               gcry_mpi_t v2;
390               gcry_mpi_t v1_v2_prod;
391
392               expected_result = gcry_mpi_new (0);
393
394               for (i = 0; i < element_count_peer1; i++)
395                 {
396                   uint32_t value;
397                   v1_v2_prod = gcry_mpi_new (0);
398
399                   // long to gcry_mpi_t
400                   value = elements_peer1[i] >= 0 ? elements_peer1[i] : -elements_peer1[i];
401                   if (elements_peer1[i] < 0)
402                     {
403                       v1 = gcry_mpi_new (0);
404                       gcry_mpi_sub_ui (v1, v1, value);
405                     }
406                   else
407                     v1 = gcry_mpi_set_ui (NULL, value);
408
409                   // long to gcry_mpi_t
410                   value = elements_peer2[i] >= 0 ? elements_peer2[i] : -elements_peer2[i];
411                   if (elements_peer2[i] < 0)
412                     {
413                       v2 = gcry_mpi_new (0);
414                       gcry_mpi_sub_ui (v2, v2, value);
415                     }
416                   else
417                     v2 = gcry_mpi_set_ui (NULL, value);
418
419                   gcry_mpi_mul (v1_v2_prod, v1, v2);
420                   gcry_mpi_add (expected_result, expected_result, v1_v2_prod);
421
422                   gcry_mpi_release (v1);
423                   gcry_mpi_release (v2);
424                   gcry_mpi_release (v1_v2_prod);
425
426                 }
427
428               // compare the result
429               if (!gcry_mpi_cmp (expected_result, result))
430                 {
431                   LOG (GNUNET_ERROR_TYPE_INFO, "Scalar Product matches expected Result!!\n");
432                   requester_ok = 1;
433                 }
434               else
435                 {
436                   LOG (GNUNET_ERROR_TYPE_WARNING, "Scalar Product DOES NOT match expected Result!!\n");
437                   requester_ok = -1;
438                 }
439               gcry_mpi_release (result);
440               gcry_mpi_release (expected_result);
441             }
442         }
443       else
444         { //currently not used, but if we get more info due to MESH we will need this
445           LOG (GNUNET_ERROR_TYPE_WARNING, "Error during computation of vector product, return code: %d\n", product_len);
446           requester_ok = -1;
447         }
448     }
449
450   //do_shutdown(&peer2, NULL);
451   GNUNET_SCHEDULER_add_now (&do_shutdown, &peer2);
452   return;
453 }
454
455 /**
456  * Prepare the message to be sent by peer2 to its scalarproduct service, to
457  * initiate a request to peer1.
458  */
459 static struct GNUNET_SCALARPRODUCT_QueueEntry *
460 requester_request ()
461 {
462   unsigned int i;
463   int exit_loop;
464   uint16_t mask_length = 0;
465   char * begin = input_elements_peer2;
466   char * end;
467   int32_t element;
468   struct GNUNET_SCALARPRODUCT_QueueEntry *qe;
469   struct GNUNET_HashCode key;
470
471   GNUNET_assert (peer2.vh != NULL);
472
473   GNUNET_CRYPTO_hash (input_key, strlen (input_key), &key);
474
475   /* Read input_elements_peer2, and put in elements_peer2 array */
476   exit_loop = 0;
477   do
478     {
479       unsigned int mcount = element_count_peer2;
480       //ignore empty rows of ,,,,,,
481       while (*begin == ',')
482         begin++;
483       // get the length of the current element and replace , with null
484       for (end = begin; *end && *end != ','; end++);
485
486       if (*end == '\0')
487         exit_loop = 1;
488
489       if (1 != sscanf (begin, "%" SCNd32, &element))
490         {
491           FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
492           ok = -1;
493           return NULL;
494         }
495
496       GNUNET_array_append (elements_peer2, mcount, element);
497       element_count_peer2++;
498
499       begin = ++end;
500     }
501   while (!exit_loop && element_count_peer2 < max_mids);
502   GNUNET_assert (elements_peer2 != NULL);
503   GNUNET_assert (element_count_peer2 >= 1);
504
505   /* Read input_mask_peer2 and read in mask_peer2 array */
506   mask_length = element_count_peer2 / 8 + (element_count_peer2 % 8 ? 1 : 0);
507   mask_peer2 = GNUNET_malloc ((element_count_peer2 / 8) + 2);
508   GNUNET_assert (NULL != mask_peer2);
509   if (NULL != input_mask_peer2)
510     {
511       begin = input_mask_peer2;
512       unsigned short mask_count = 0;
513       int exit_loop = 0;
514
515       do
516         {
517           //ignore empty rows of ,,,,,,
518           while (* begin == ',')
519             begin++;
520           // get the length of the current element and replace , with null
521           // gnunet_ascii-armor uses base32, thus we can use , as separator!
522           for (end = begin; *end && *end != ','; end++);
523
524           if (*end == '\0')
525             exit_loop = 1;
526
527           if (1 != sscanf (begin, "%" SCNd32, &element))
528             {
529               FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
530               ok = -1;
531               return NULL;
532             }
533
534           GNUNET_assert (mask_count <= element_count_peer2);
535
536           if (element)
537             mask_peer2[mask_count / 8] = mask_peer2[mask_count / 8] | 1 << (mask_count % 8);
538
539           mask_count++;
540           begin = ++end;
541         }
542       while (!exit_loop);
543       // +1 to see if we would have more data, which would indicate malformed/superficial input
544       GNUNET_assert (mask_count == element_count_peer2);
545     }
546   else
547     {
548       for (i = 0; i <= mask_length; i++)
549         mask_peer2[i] = UCHAR_MAX; // all 1's
550     }
551
552   qe = GNUNET_SCALARPRODUCT_request (peer2.vh,
553                                      &key,
554                                      &peer1.our_id,
555                                      element_count_peer2,
556                                      mask_length,
557                                      elements_peer2, mask_peer2,
558                                      GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
559                                      &requester_callback,
560                                      NULL);
561
562   if (qe == NULL)
563     {
564       LOG(GNUNET_ERROR_TYPE_ERROR, "Could not send request to scalarproduct service! Exitting!");
565       ok = -1;
566       return NULL;
567     }
568
569   return qe;
570 }
571
572
573 /**
574  * Function prepares the message to be sent by peer1 to its scalarproduct service
575  * to prepare response, and wait for a request session to be initiated by peer1
576  */
577 static struct GNUNET_SCALARPRODUCT_QueueEntry *
578 responder_prepare_response ()
579 {
580   GNUNET_assert (peer1.vh != NULL);
581
582   char * begin = input_elements_peer1;
583   char * end;
584   int32_t element;
585   struct GNUNET_SCALARPRODUCT_QueueEntry *qe;
586   struct GNUNET_HashCode key;
587
588   GNUNET_CRYPTO_hash (input_key, strlen (input_key), &key);
589
590   /* Read input_elements_peer1, and put in elements_peer1 array */
591   int exit_loop = 0;
592   do
593     {
594       unsigned int mcount = element_count_peer1;
595       //ignore empty rows of ,,,,,,
596       while (*begin == ',')
597         begin++;
598       // get the length of the current element and replace , with null
599       for (end = begin; *end && *end != ','; end++);
600
601       if (*end == '\0')
602         exit_loop = 1;
603
604       if (1 != sscanf (begin, "%" SCNd32, &element))
605         {
606           FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin);
607           ok = -1;
608           return NULL;
609         }
610
611       GNUNET_array_append (elements_peer1, mcount, element);
612       element_count_peer1++;
613
614       begin = ++end;
615     }
616   while (!exit_loop && element_count_peer1 < max_mids);
617   GNUNET_assert (elements_peer1 != NULL);
618   GNUNET_assert (element_count_peer1 >= 1);
619
620   qe = GNUNET_SCALARPRODUCT_prepare_response (peer1.vh,
621                                               &key,
622                                               element_count_peer1,
623                                               elements_peer1,
624                                               GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
625                                               &responder_callback,
626                                               NULL);
627
628   if (qe == NULL)
629     {
630       LOG(GNUNET_ERROR_TYPE_ERROR, "Could not send request to scalarproduct service! Exitting!");
631       ok = -1;
632       return NULL;
633     }
634
635   return qe;
636 }
637
638
639 /**
640  * Scheduler task to initiate requester client
641  *
642  * @param cls void* to struct PeerData
643  * @param tc Task Context
644  */
645 static void
646 request_task(void *cls,
647               const struct GNUNET_SCHEDULER_TaskContext
648               * tc)
649 {
650   requester_request();
651   return;
652 }
653
654 /**
655  * Scheduler task to initiate responder client
656  *
657  * @param cls void* to struct PeerData
658  * @param tc Task Context
659  */
660 static void
661 prepare_response_task(void *cls,
662               const struct GNUNET_SCHEDULER_TaskContext
663               * tc)
664 {
665   responder_prepare_response();
666   return;
667 }
668
669
670 /**
671  * Adapter function called to destroy a connection to
672  * a service. This function is called when GNUNET_TESTBED_operation_done is
673  * called for peer->op, which holds the handle for GNUNET_TESTBED_service_connect
674  * operation.
675  *
676  * @param cls closure
677  * @param op_result service handle returned from the connect adapter
678  */
679 static void
680 scalarproduct_da (void *cls, void *op_result)
681 {
682   struct PeerData* peer = (struct PeerData*) cls;
683
684   GNUNET_SCALARPRODUCT_cancel (peer->vh);
685   return;
686 }
687
688
689 /**
690  * Adapter function called to establish a connection to
691  * a service. This function is called to by GNUNET_TESTBED_service_connect.
692  *
693  * @param cls closure
694  * @param cfg configuration of the peer to connect to; will be available until
695  *          GNUNET_TESTBED_operation_done() is called on the operation returned
696  *          from GNUNET_TESTBED_service_connect()
697  * @return service handle to return in 'op_result', NULL on error
698  */
699 static void *
700 scalarproduct_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
701 {
702   struct PeerData *p = cls;
703
704   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", (&peer1 == p) ? 1 : 2,
705               GNUNET_i2s (&p->our_id));
706
707   switch (setup_state)
708     {
709     case PEER1_SCALARPRODUCT_CONNECT:
710       /* Connect peer 2 to scalarproduct service */
711       {
712         peer2.op = GNUNET_TESTBED_service_connect (&peer2, peer2.peer, "scalarproduct",
713                                                    NULL, NULL, scalarproduct_ca,
714                                                    scalarproduct_da, &peer2);
715         setup_state = PEER2_SCALARPRODUCT_CONNECT;
716       }
717
718       /* Actually connect peer 1 to scalarproduct service */
719       peer1.vh = GNUNET_SCALARPRODUCT_connect (cfg);
720       return peer1.vh;
721
722     case PEER2_SCALARPRODUCT_CONNECT:
723       /* Actually connect peer 2 to scalarproduct service */
724       peer2.vh = GNUNET_SCALARPRODUCT_connect (cfg);
725
726       /* Schedule tasks to initiate request from peer2 and prepare_response from peer1 */
727       if(peer1.vh != NULL && peer2.vh != NULL)
728       {
729         GNUNET_SCHEDULER_add_now(&prepare_response_task, &peer1);
730         GNUNET_SCHEDULER_add_now(&request_task, &peer2);
731       }
732
733       return peer2.vh;
734     default:
735       GNUNET_assert (0);
736     }
737 }
738
739
740 /**
741  * Callback to be called when the requested peer information is available
742  *
743  * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
744  * @param op the operation this callback corresponds to
745  * @param pinfo the result; will be NULL if the operation has failed
746  * @param emsg error message if the operation has failed; will be NULL if the
747  *          operation is successfull
748  */
749 static void
750 peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op_,
751              const struct GNUNET_TESTBED_PeerInformation *pinfo,
752              const char *emsg)
753 {
754   GNUNET_assert (NULL == emsg);
755   GNUNET_assert (op == op_);
756   switch (setup_state)
757     {
758     case PEER1_GET_IDENTITY:
759       {
760         memcpy (&peer1.our_id, pinfo->result.id,
761                 sizeof (struct GNUNET_PeerIdentity));
762         GNUNET_TESTBED_operation_done (op);
763
764         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 1 id: %s\n", GNUNET_i2s_full
765                     (&peer1.our_id));
766
767         /* Request for peer id of peer 2*/
768         op = GNUNET_TESTBED_peer_get_information (peer2.peer,
769                                                   GNUNET_TESTBED_PIT_IDENTITY,
770                                                   &peerinfo_cb, NULL);
771         setup_state = PEER2_GET_IDENTITY;
772       }
773       break;
774     case PEER2_GET_IDENTITY:
775       {
776         memcpy (&peer2.our_id, pinfo->result.id,
777                 sizeof (struct GNUNET_PeerIdentity));
778         GNUNET_TESTBED_operation_done (op);
779
780         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 2 id: %s\n", GNUNET_i2s_full
781                     (&peer2.our_id));
782
783         /* Connect peer 1 to scalarproduct service */
784         peer1.op = GNUNET_TESTBED_service_connect (&peer1, peer1.peer, "scalarproduct",
785                                                    NULL, NULL, scalarproduct_ca,
786                                                    scalarproduct_da, &peer1);
787         setup_state = PEER1_SCALARPRODUCT_CONNECT;
788       }
789       break;
790     default:
791       GNUNET_assert (0);
792     }
793 }
794
795
796 /**
797  * Signature of a main function for a testcase.
798  *
799  * @param cls closure
800  * @param num_peers number of peers in 'peers'
801  * @param peers handle to peers run in the testbed
802  */
803 static void
804 test_master (void *cls, unsigned int num_peers,
805              struct GNUNET_TESTBED_Peer **peers)
806 {
807   GNUNET_assert (NULL != peers);
808   GNUNET_assert (NULL != peers[0]);
809   GNUNET_assert (NULL != peers[1]);
810   peer1.peer = peers[0];
811   peer2.peer = peers[1];
812   /* Get the peer identity and configuration of peer 1 */
813   op = GNUNET_TESTBED_peer_get_information (peer1.peer,
814                                             GNUNET_TESTBED_PIT_IDENTITY,
815                                             &peerinfo_cb, NULL);
816   setup_state = PEER1_GET_IDENTITY;
817
818   /* Abort task for stopping test on timeout */
819   abort_task =
820           GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
821                                         (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort,
822                                         NULL);
823 }
824
825
826 /**
827  * Main function
828  */
829 int
830 main (int argc, char **argv)
831 {
832   uint64_t event_mask;
833
834   ok = GNUNET_NO;
835   event_mask = 0;
836   event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
837   max_mids = (GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_MessageHeader))
838           / sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1;
839
840   (void) GNUNET_TESTBED_test_run ("test_scalarproduct_api",
841                                   "test_scalarproduct_api_data.conf",
842                                   NUM_PEERS, event_mask, &controller_event_cb,
843                                   NULL,
844                                   &test_master, NULL);
845
846   if (GNUNET_SYSERR == ok)
847     {
848       LOG (GNUNET_ERROR_TYPE_ERROR, "Test failing due to some error before calling API for request or prepare_response\n");
849       return 1;
850     }
851   else if (GNUNET_SYSERR == responder_ok)
852     {
853       LOG (GNUNET_ERROR_TYPE_ERROR, "Test failing due to some error in responding_client\n");
854       return 1;
855     }
856   else if (GNUNET_SYSERR == requester_ok)
857     {
858       LOG (GNUNET_ERROR_TYPE_ERROR, "Test failing due to some error in requesting client\n");
859       return 1;
860     }
861   else
862     return 0;
863 }
864
865