+/**
+ * We received a reservation result message. Validate and process it.
+ *
+ * @param ph our context with the callback
+ * @param msg the message
+ * @return GNUNET_OK if the message was well-formed
+ */
+static int
+process_ar_message (struct GNUNET_ATS_PerformanceHandle *ph,
+ const struct GNUNET_MessageHeader *msg)
+{
+ const struct PeerInformationMessage *pi;
+ struct GNUNET_ATS_AddressListHandle *alh;
+ struct GNUNET_ATS_AddressListHandle *next;
+ const struct GNUNET_ATS_Information *atsi;
+ const char *plugin_address;
+ const char *plugin_name;
+ struct GNUNET_HELLO_Address address;
+ struct GNUNET_PeerIdentity allzeros;
+ struct GNUNET_BANDWIDTH_Value32NBO bandwidth_zero;
+ uint16_t plugin_address_length;
+ uint16_t plugin_name_length;
+ uint32_t ats_count;
+ uint32_t active;
+ uint32_t id;
+
+ if (ntohs (msg->size) < sizeof(struct PeerInformationMessage))
+ {
+ GNUNET_break(0);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, _("Received %s message\n"),
+ "ATS_ADDRESSLIST_RESPONSE");
+
+ pi = (const struct PeerInformationMessage *) msg;
+ id = ntohl (pi->id);
+ ats_count = ntohl (pi->ats_count);
+ active = ntohl (pi->address_active);
+ plugin_address_length = ntohs (pi->address_length);
+ plugin_name_length = ntohs (pi->plugin_name_length);
+ atsi = (const struct GNUNET_ATS_Information *) &pi[1];
+ plugin_address = (const char *) &atsi[ats_count];
+ plugin_name = &plugin_address[plugin_address_length];
+ if ((plugin_address_length + plugin_name_length
+ + ats_count * sizeof(struct GNUNET_ATS_Information)
+ + sizeof(struct PeerInformationMessage) != ntohs (msg->size))
+ || (ats_count
+ > GNUNET_SERVER_MAX_MESSAGE_SIZE
+ / sizeof(struct GNUNET_ATS_Information))
+ || (plugin_name[plugin_name_length - 1] != '\0'))
+ {
+ GNUNET_break(0);
+ return GNUNET_SYSERR;
+ }
+
+ next = ph->addresslist_head;
+ while (NULL != (alh = next))
+ {
+ next = alh->next;
+ if (alh->id == id)
+ break;
+ }
+ if (NULL == alh)
+ {
+ /* was canceled */
+ return GNUNET_SYSERR;
+ }
+
+ memset (&allzeros, '\0', sizeof(allzeros));
+ if ((0 == memcmp (&allzeros, &pi->peer, sizeof(allzeros)))
+ && (0 == plugin_name_length) && (0 == plugin_address_length)
+ && (0 == ats_count))
+ {
+ /* Done */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, _("Received last message for %s \n"),
+ "ATS_ADDRESSLIST_RESPONSE");
+ bandwidth_zero.value__ = htonl (0);
+ if (NULL != alh->cb)
+ alh->cb (ph->addr_info_cb_cls, NULL, GNUNET_NO, bandwidth_zero,
+ bandwidth_zero, NULL, 0);
+ GNUNET_CONTAINER_DLL_remove(ph->addresslist_head, ph->addresslist_tail,
+ alh);
+ GNUNET_free(alh);
+ return GNUNET_OK;
+ }
+
+ address.peer = pi->peer;
+ address.address = plugin_address;
+ address.address_length = plugin_address_length;
+ address.transport_name = plugin_name;
+
+ if ((GNUNET_YES == alh->all_addresses) || (GNUNET_YES == active))
+ {
+ if (NULL != alh->cb)
+ alh->cb (ph->addr_info_cb_cls, &address, active, pi->bandwidth_out,
+ pi->bandwidth_in, atsi, ats_count);
+ }
+ return GNUNET_OK;
+}