-test cleanup
[oweals/gnunet.git] / src / ats / gnunet-service-ats_performance.c
1 /*
2      This file is part of GNUnet.
3      (C) 2011-2014 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  * @file ats/gnunet-service-ats_performance.c
23  * @brief ats service, interaction with 'performance' API
24  * @author Matthias Wachs
25  * @author Christian Grothoff
26  */
27 #include "platform.h"
28 #include "gnunet-service-ats.h"
29 #include "gnunet-service-ats_addresses.h"
30 #include "gnunet-service-ats_performance.h"
31 #include "gnunet-service-ats_reservations.h"
32 #include "ats.h"
33
34 /**
35  * We keep clients that are interested in performance in a linked list.
36  */
37 struct PerformanceClient
38 {
39   /**
40    * Next in doubly-linked list.
41    */
42   struct PerformanceClient *next;
43
44   /**
45    * Previous in doubly-linked list.
46    */
47   struct PerformanceClient *prev;
48
49   /**
50    * Actual handle to the client.
51    */
52   struct GNUNET_SERVER_Client *client;
53
54   /**
55    * Options for the client.
56    */
57   enum StartFlag flag;
58
59 };
60
61
62 /**
63  * Address handle
64  */
65 static struct GAS_Addresses_Handle *GSA_addresses;
66
67 /**
68  * Head of linked list of all clients to this service.
69  */
70 static struct PerformanceClient *pc_head;
71
72 /**
73  * Tail of linked list of all clients to this service.
74  */
75 static struct PerformanceClient *pc_tail;
76
77 /**
78  * Context for sending messages to performance clients.
79  */
80 static struct GNUNET_SERVER_NotificationContext *nc;
81
82
83 /**
84  * Find the performance client associated with the given handle.
85  *
86  * @param client server handle
87  * @return internal handle
88  */
89 static struct PerformanceClient *
90 find_client (struct GNUNET_SERVER_Client *client)
91 {
92   struct PerformanceClient *pc;
93
94   for (pc = pc_head; pc != NULL; pc = pc->next)
95     if (pc->client == client)
96       return pc;
97   return NULL;
98 }
99
100
101 /**
102  * Unregister a client (which may have been a performance client,
103  * but this is not assured).
104  *
105  * @param client handle of the (now dead) client
106  */
107 void
108 GAS_performance_remove_client (struct GNUNET_SERVER_Client *client)
109 {
110   struct PerformanceClient *pc;
111
112   pc = find_client (client);
113   if (NULL == pc)
114     return;
115   GNUNET_CONTAINER_DLL_remove (pc_head, pc_tail, pc);
116   GAS_addresses_preference_client_disconnect (GSA_addresses, client);
117   GNUNET_free (pc);
118 }
119
120
121 /**
122  * Transmit the given performance information to all performance
123  * clients.
124  *
125  * @param pc performance client to send to
126  * @param peer peer for which this is an address suggestion
127  * @param plugin_name 0-termintated string specifying the transport plugin
128  * @param plugin_addr binary address for the plugin to use
129  * @param plugin_addr_len number of bytes in plugin_addr
130  * @param active #GNUNET_YES if this address is actively used
131  *        to maintain a connection to a peer;
132  *        #GNUNET_NO if the address is not actively used;
133  *        #GNUNET_SYSERR if this address is no longer available for ATS
134  * @param atsi performance data for the address
135  * @param atsi_count number of performance records in @a atsi
136  * @param bandwidth_out assigned outbound bandwidth
137  * @param bandwidth_in assigned inbound bandwidth
138  */
139 void
140 GAS_performance_notify_client (struct PerformanceClient *pc,
141                                const struct GNUNET_PeerIdentity *peer,
142                                const char *plugin_name,
143                                const void *plugin_addr,
144                                size_t plugin_addr_len,
145                                int active,
146                                const struct GNUNET_ATS_Information *atsi,
147                                uint32_t atsi_count,
148                                struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
149                                struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
150 {
151
152   struct PeerInformationMessage *msg;
153   size_t plugin_name_length = strlen (plugin_name) + 1;
154   size_t msize =
155       sizeof (struct PeerInformationMessage) +
156       atsi_count * sizeof (struct GNUNET_ATS_Information) + plugin_addr_len +
157       plugin_name_length;
158   char buf[msize] GNUNET_ALIGN;
159   struct GNUNET_ATS_Information *atsp;
160   char *addrp;
161
162   GNUNET_assert (NULL != pc);
163   if (NULL == find_client (pc->client))
164     return; /* Client disconnected */
165
166   GNUNET_assert (msize < GNUNET_SERVER_MAX_MESSAGE_SIZE);
167   GNUNET_assert (atsi_count <
168                  GNUNET_SERVER_MAX_MESSAGE_SIZE /
169                  sizeof (struct GNUNET_ATS_Information));
170   msg = (struct PeerInformationMessage *) buf;
171   msg->header.size = htons (msize);
172   msg->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_PEER_INFORMATION);
173   msg->id = htonl (0);
174   msg->ats_count = htonl (atsi_count);
175   msg->peer = *peer;
176   msg->address_length = htons (plugin_addr_len);
177   msg->address_active = ntohl ((uint32_t) active);
178   msg->plugin_name_length = htons (plugin_name_length);
179   msg->bandwidth_out = bandwidth_out;
180   msg->bandwidth_in = bandwidth_in;
181   atsp = (struct GNUNET_ATS_Information *) &msg[1];
182   memcpy (atsp, atsi, sizeof (struct GNUNET_ATS_Information) * atsi_count);
183   addrp = (char *) &atsp[atsi_count];
184   memcpy (addrp, plugin_addr, plugin_addr_len);
185   strcpy (&addrp[plugin_addr_len], plugin_name);
186   GNUNET_SERVER_notification_context_unicast (nc,
187                                               pc->client,
188                                               &msg->header,
189                                               GNUNET_YES);
190 }
191
192
193 /**
194  * Transmit the given performance information to all performance
195  * clients.
196  *
197  * @param peer peer for which this is an address suggestion
198  * @param plugin_name 0-termintated string specifying the transport plugin
199  * @param plugin_addr binary address for the plugin to use
200  * @param plugin_addr_len number of bytes in @a plugin_addr
201  * @param active #GNUNET_YES if this address is actively used
202  *        to maintain a connection to a peer;
203  *        #GNUNET_NO if the address is not actively used;
204  *        #GNUNET_SYSERR if this address is no longer available for ATS
205  * @param atsi performance data for the address
206  * @param atsi_count number of performance records in @a atsi
207  * @param bandwidth_out assigned outbound bandwidth
208  * @param bandwidth_in assigned inbound bandwidth
209  */
210 void
211 GAS_performance_notify_all_clients (const struct GNUNET_PeerIdentity *peer,
212                                     const char *plugin_name,
213                                     const void *plugin_addr,
214                                     size_t plugin_addr_len,
215                                     int active,
216                                     const struct GNUNET_ATS_Information *atsi,
217                                     uint32_t atsi_count,
218                                     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
219                                     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
220 {
221   struct PerformanceClient *pc;
222
223   for (pc = pc_head; pc != NULL; pc = pc->next)
224     if (pc->flag == START_FLAG_PERFORMANCE_WITH_PIC)
225     {
226         GAS_performance_notify_client (pc,
227                                        peer,
228                                        plugin_name,
229                                        plugin_addr,
230                                        plugin_addr_len,
231                                        active,
232                                        atsi, atsi_count,
233                                        bandwidth_out, bandwidth_in);
234     }
235   GNUNET_STATISTICS_update (GSA_stats,
236                             "# performance updates given to clients", 1,
237                             GNUNET_NO);
238 }
239
240
241
242 /**
243  * Iterator for called from #GAS_addresses_get_peer_info()
244  *
245  * @param cls closure with the `struct PerformanceClient *`
246  * @param id the peer id
247  * @param plugin_name plugin name
248  * @param plugin_addr address
249  * @param plugin_addr_len length of @a plugin_addr
250  * @param active is address actively used
251  * @param atsi ats performance information
252  * @param atsi_count number of ats performance elements in @a atsi
253  * @param bandwidth_out current outbound bandwidth assigned to address
254  * @param bandwidth_in current inbound bandwidth assigned to address
255  */
256 static void
257 peerinfo_it (void *cls,
258              const struct GNUNET_PeerIdentity *id,
259              const char *plugin_name,
260              const void *plugin_addr,
261              size_t plugin_addr_len,
262              int active,
263              const struct GNUNET_ATS_Information *atsi,
264              uint32_t atsi_count,
265              struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
266              struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
267 {
268   struct PerformanceClient *pc = cls;
269
270   GNUNET_assert (NULL != pc);
271   if (NULL == id)
272     return;
273   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
274               "Callback for peer `%s' plugin `%s' BW out %u, BW in %u \n",
275               GNUNET_i2s (id),
276               plugin_name,
277               (unsigned int) ntohl (bandwidth_out.value__),
278               (unsigned int) ntohl (bandwidth_in.value__));
279   GAS_performance_notify_client (pc,
280                                  id,
281                                  plugin_name,
282                                  plugin_addr,
283                                  plugin_addr_len,
284                                  active,
285                                  atsi, atsi_count,
286                                  bandwidth_out,
287                                  bandwidth_in);
288 }
289
290
291 /**
292  * Register a new performance client.
293  *
294  * @param client handle of the new client
295  * @param flag flag specifying the type of the client
296  */
297 void
298 GAS_performance_add_client (struct GNUNET_SERVER_Client *client,
299                             enum StartFlag flag)
300 {
301   struct PerformanceClient *pc;
302
303   GNUNET_break (NULL == find_client (client));
304   pc = GNUNET_new (struct PerformanceClient);
305   pc->client = client;
306   pc->flag = flag;
307
308   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
309               "Adding performance client %s PIC\n",
310               (flag == START_FLAG_PERFORMANCE_WITH_PIC) ? "with" : "without");
311
312   GNUNET_SERVER_notification_context_add (nc,
313                                           client);
314   GNUNET_CONTAINER_DLL_insert (pc_head,
315                                pc_tail,
316                                pc);
317   GAS_addresses_get_peer_info (GSA_addresses,
318                                NULL,
319                                &peerinfo_it,
320                                pc);
321 }
322
323
324 /**
325  * Information we need for the callbacks to return a list of addresses
326  * back to the client.
327  */
328 struct AddressIteration
329 {
330   /**
331    * Actual handle to the client.
332    */
333   struct PerformanceClient *pc;
334
335   /**
336    * Are we sending all addresses, or only those that are active?
337    */
338   int all;
339
340   /**
341    * Which ID should be included in the response?
342    */
343   uint32_t id;
344
345 };
346
347
348 /**
349  * Send a #GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE with the
350  * given address details to the client identified in @a ai.
351  *
352  * @param ai our address information context (identifies the client)
353  * @param id the peer id this address is for
354  * @param plugin_name name of the plugin that supports this address
355  * @param plugin_addr address
356  * @param plugin_addr_len length of @a plugin_addr
357  * @param active #GNUNET_YES if this address is actively used
358  * @param atsi ats performance information
359  * @param atsi_count number of ats performance elements in @a atsi
360  * @param bandwidth_out current outbound bandwidth assigned to address
361  * @param bandwidth_in current inbound bandwidth assigned to address
362  */
363 static void
364 transmit_req_addr (struct AddressIteration *ai,
365                    const struct GNUNET_PeerIdentity *id,
366                    const char *plugin_name,
367                    const void *plugin_addr,
368                    size_t plugin_addr_len,
369                    int active,
370                    const struct GNUNET_ATS_Information *atsi,
371                    uint32_t atsi_count,
372                    struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
373                    struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
374
375 {
376   struct GNUNET_ATS_Information *atsp;
377   struct PeerInformationMessage *msg;
378   char *addrp;
379   size_t plugin_name_length;
380   size_t msize;
381
382   if (NULL != plugin_name)
383     plugin_name_length = strlen (plugin_name) + 1;
384   else
385     plugin_name_length = 0;
386   msize = sizeof (struct PeerInformationMessage) +
387           atsi_count * sizeof (struct GNUNET_ATS_Information) +
388           plugin_addr_len + plugin_name_length;
389   char buf[msize] GNUNET_ALIGN;
390
391   GNUNET_assert (msize < GNUNET_SERVER_MAX_MESSAGE_SIZE);
392   GNUNET_assert (atsi_count <
393                  GNUNET_SERVER_MAX_MESSAGE_SIZE /
394                  sizeof (struct GNUNET_ATS_Information));
395   msg = (struct PeerInformationMessage *) buf;
396   msg->header.size = htons (msize);
397   msg->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE);
398   msg->ats_count = htonl (atsi_count);
399   msg->id = htonl (ai->id);
400   if (NULL != id)
401     msg->peer = *id;
402   else
403     memset (&msg->peer, '\0', sizeof (struct GNUNET_PeerIdentity));
404   msg->address_length = htons (plugin_addr_len);
405   msg->address_active = ntohl (active);
406   msg->plugin_name_length = htons (plugin_name_length);
407   msg->bandwidth_out = bandwidth_out;
408   msg->bandwidth_in = bandwidth_in;
409   atsp = (struct GNUNET_ATS_Information *) &msg[1];
410   memcpy (atsp, atsi, sizeof (struct GNUNET_ATS_Information) * atsi_count);
411   addrp = (char *) &atsp[atsi_count];
412   if (NULL != plugin_addr)
413     memcpy (addrp, plugin_addr, plugin_addr_len);
414   if (NULL != plugin_name)
415     strcpy (&addrp[plugin_addr_len], plugin_name);
416   GNUNET_SERVER_notification_context_unicast (nc,
417                                               ai->pc->client,
418                                               &msg->header,
419                                               GNUNET_NO);
420 }
421
422
423 /**
424  * Iterator for #GAS_addresses_get_peer_info(), called with peer-specific
425  * information to be passed back to the client.
426  *
427  * @param cls closure with our `struct AddressIteration *`
428  * @param id the peer id
429  * @param plugin_name plugin name
430  * @param plugin_addr address
431  * @param plugin_addr_len length of @a plugin_addr
432  * @param active is address actively used
433  * @param atsi ats performance information
434  * @param atsi_count number of ats performance elements in @a atsi
435  * @param bandwidth_out current outbound bandwidth assigned to address
436  * @param bandwidth_in current inbound bandwidth assigned to address
437  */
438 static void
439 req_addr_peerinfo_it (void *cls,
440                       const struct GNUNET_PeerIdentity *id,
441                       const char *plugin_name,
442                       const void *plugin_addr,
443                       size_t plugin_addr_len,
444                       int active,
445                       const struct GNUNET_ATS_Information *atsi,
446                       uint32_t atsi_count,
447                       struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
448                       struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
449 {
450   struct AddressIteration *ai = cls;
451
452   if ( (NULL == id) &&
453        (NULL == plugin_name) &&
454        (NULL == plugin_addr) )
455   {
456     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
457                 "Address iteration done for one peer\n");
458     return;
459   }
460   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
461               "Callback for %s peer `%s' plugin `%s' BW out %u, BW in %u\n",
462               (active == GNUNET_YES) ? "ACTIVE" : "INACTIVE",
463               GNUNET_i2s (id),
464               plugin_name,
465               (unsigned int) ntohl (bandwidth_out.value__),
466               (unsigned int) ntohl (bandwidth_in.value__));
467
468   /* Transmit result (either if address is active, or if
469      client wanted all addresses) */
470   if ( (GNUNET_YES == ai->all) ||
471        (GNUNET_YES == active))
472   {
473     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
474                 "Sending result for %s peer `%s' plugin `%s' BW out %u, BW in %u\n",
475                 (active == GNUNET_YES) ? "ACTIVE" : "INACTIVE",
476                 GNUNET_i2s (id),
477                 plugin_name,
478                 (unsigned int) ntohl (bandwidth_out.value__),
479                 (unsigned int) ntohl (bandwidth_in.value__));
480     transmit_req_addr (ai,
481                        id,
482                        plugin_name,
483                        plugin_addr, plugin_addr_len,
484                        active,
485                        atsi,
486                        atsi_count,
487                        bandwidth_out,
488                        bandwidth_in);
489   }
490 }
491
492
493 /**
494  * Handle 'address list request' messages from clients.
495  *
496  * @param cls unused, NULL
497  * @param client client that sent the request
498  * @param message the request message
499  */
500 void
501 GAS_handle_request_address_list (void *cls,
502                                  struct GNUNET_SERVER_Client *client,
503                                  const struct GNUNET_MessageHeader *message)
504 {
505   struct PerformanceClient *pc;
506   struct AddressIteration ai;
507   const struct AddressListRequestMessage *alrm;
508   struct GNUNET_PeerIdentity allzeros;
509   struct GNUNET_BANDWIDTH_Value32NBO bandwidth_zero;
510
511   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
512               "Received `%s' message\n",
513               "ADDRESSLIST_REQUEST");
514   if (NULL == (pc = find_client(client)))
515   {
516     GNUNET_break (0);
517     return;
518   }
519   alrm = (const struct AddressListRequestMessage *) message;
520   ai.all = ntohl (alrm->all);
521   ai.id = ntohl (alrm->id);
522   ai.pc = pc;
523
524   memset (&allzeros, '\0', sizeof (struct GNUNET_PeerIdentity));
525   bandwidth_zero.value__ = htonl (0);
526   if (0 == memcmp (&alrm->peer,
527                    &allzeros,
528                    sizeof (struct GNUNET_PeerIdentity)))
529   {
530     /* Return addresses for all peers */
531     GAS_addresses_get_peer_info (GSA_addresses,
532                                  NULL,
533                                  &req_addr_peerinfo_it,
534                                  &ai);
535   }
536   else
537   {
538     /* Return addresses for a specific peer */
539     GAS_addresses_get_peer_info (GSA_addresses,
540                                  &alrm->peer,
541                                  &req_addr_peerinfo_it,
542                                  &ai);
543   }
544   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
545               "Finished handling `%s' message\n",
546               "ADDRESSLIST_REQUEST");
547   transmit_req_addr (&ai,
548                      NULL, NULL, NULL,
549                      0, GNUNET_NO,
550                      NULL, 0,
551                      bandwidth_zero,
552                      bandwidth_zero);
553   GNUNET_SERVER_receive_done (client,
554                               GNUNET_OK);
555 }
556
557
558 /**
559  * Handle 'reservation request' messages from clients.
560  *
561  * @param cls unused, NULL
562  * @param client client that sent the request
563  * @param message the request message
564  */
565 void
566 GAS_handle_reservation_request (void *cls,
567                                 struct GNUNET_SERVER_Client *client,
568                                 const struct GNUNET_MessageHeader *message)
569 {
570   const struct ReservationRequestMessage *msg =
571       (const struct ReservationRequestMessage *) message;
572   struct ReservationResultMessage result;
573   int32_t amount;
574   struct GNUNET_TIME_Relative res_delay;
575
576   if (NULL == find_client (client))
577   {
578     /* missing start message! */
579     GNUNET_break (0);
580     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
581     return;
582   }
583   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
584               "Received `%s' message\n",
585               "RESERVATION_REQUEST");
586   amount = (int32_t) ntohl (msg->amount);
587   res_delay = GAS_reservations_reserve (&msg->peer, amount);
588   if (res_delay.rel_value_us > 0)
589     amount = 0;
590   result.header.size = htons (sizeof (struct ReservationResultMessage));
591   result.header.type = htons (GNUNET_MESSAGE_TYPE_ATS_RESERVATION_RESULT);
592   result.amount = htonl (amount);
593   result.peer = msg->peer;
594   result.res_delay = GNUNET_TIME_relative_hton (res_delay);
595   GNUNET_STATISTICS_update (GSA_stats,
596                             "# reservation requests processed", 1,
597                             GNUNET_NO);
598   GNUNET_SERVER_notification_context_unicast (nc, client, &result.header,
599                                               GNUNET_NO);
600   GNUNET_SERVER_receive_done (client, GNUNET_OK);
601 }
602
603
604 /**
605  * Handle 'preference change' messages from clients.
606  *
607  * @param cls unused, NULL
608  * @param client client that sent the request
609  * @param message the request message
610  */
611 void
612 GAS_handle_preference_change (void *cls,
613                               struct GNUNET_SERVER_Client *client,
614                               const struct GNUNET_MessageHeader *message)
615 {
616   const struct ChangePreferenceMessage *msg;
617   const struct PreferenceInformation *pi;
618   uint16_t msize;
619   uint32_t nump;
620   uint32_t i;
621
622   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n",
623               "PREFERENCE_CHANGE");
624   msize = ntohs (message->size);
625   if (msize < sizeof (struct ChangePreferenceMessage))
626   {
627     GNUNET_break (0);
628     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
629     return;
630   }
631   msg = (const struct ChangePreferenceMessage *) message;
632   nump = ntohl (msg->num_preferences);
633   if (msize !=
634       sizeof (struct ChangePreferenceMessage) +
635       nump * sizeof (struct PreferenceInformation))
636   {
637     GNUNET_break (0);
638     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
639     return;
640   }
641   GNUNET_STATISTICS_update (GSA_stats,
642                             "# preference change requests processed",
643                             1, GNUNET_NO);
644   pi = (const struct PreferenceInformation *) &msg[1];
645   for (i = 0; i < nump; i++)
646     GAS_addresses_preference_change (GSA_addresses,
647                                      client,
648                                      &msg->peer,
649                                      (enum GNUNET_ATS_PreferenceKind)
650                                      ntohl (pi[i].preference_kind),
651                                      pi[i].preference_value);
652   GNUNET_SERVER_receive_done (client, GNUNET_OK);
653 }
654
655
656 /**
657  * Handle 'preference feedback' messages from clients.
658  *
659  * @param cls unused, NULL
660  * @param client client that sent the request
661  * @param message the request message
662  */
663 void
664 GAS_handle_preference_feedback (void *cls,
665                               struct GNUNET_SERVER_Client *client,
666                               const struct GNUNET_MessageHeader *message)
667 {
668   const struct FeedbackPreferenceMessage *msg;
669   const struct PreferenceInformation *pi;
670   uint16_t msize;
671   uint32_t nump;
672   uint32_t i;
673
674   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
675               "Received `%s' message\n",
676               "PREFERENCE_FEEDBACK");
677   msize = ntohs (message->size);
678   if (msize < sizeof (struct FeedbackPreferenceMessage))
679   {
680     GNUNET_break (0);
681     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
682     return;
683   }
684   msg = (const struct FeedbackPreferenceMessage *) message;
685   nump = ntohl (msg->num_feedback);
686   if (msize !=
687       sizeof (struct FeedbackPreferenceMessage) +
688       nump * sizeof (struct PreferenceInformation))
689   {
690     GNUNET_break (0);
691     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
692     return;
693   }
694   GNUNET_STATISTICS_update (GSA_stats,
695                             "# preference feedbacks requests processed",
696                             1, GNUNET_NO);
697   pi = (const struct PreferenceInformation *) &msg[1];
698   for (i = 0; i < nump; i++)
699     GAS_addresses_preference_feedback (GSA_addresses,
700                                      client,
701                                      &msg->peer,
702                                      GNUNET_TIME_relative_ntoh(msg->scope),
703                                      (enum GNUNET_ATS_PreferenceKind)
704                                      ntohl (pi[i].preference_kind),
705                                      pi[i].preference_value);
706   GNUNET_SERVER_receive_done (client, GNUNET_OK);
707 }
708
709
710
711 /**
712  * Initialize performance subsystem.
713  *
714  * @param server handle to our server
715  * @param addresses the address handle to use
716  */
717 void
718 GAS_performance_init (struct GNUNET_SERVER_Handle *server,
719                       struct GAS_Addresses_Handle *addresses)
720 {
721   GSA_addresses = addresses;
722   nc = GNUNET_SERVER_notification_context_create (server, 128);
723 }
724
725
726 /**
727  * Shutdown performance subsystem.
728  */
729 void
730 GAS_performance_done ()
731 {
732   GNUNET_SERVER_notification_context_destroy (nc);
733   nc = NULL;
734 }
735
736 /* end of gnunet-service-ats_performance.c */