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