+ if (NULL == ph->client)
+ return; /* currently reconnecting */
+ ph->th = GNUNET_CLIENT_notify_transmit_ready (ph->client, p->size,
+ GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &transmit_message_to_ats, ph);
+}
+
+/**
+ * We received a peer information 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_pi_message (struct GNUNET_ATS_PerformanceHandle *ph,
+ const struct GNUNET_MessageHeader *msg)
+{
+ const struct PeerInformationMessage *pi;
+ const struct GNUNET_ATS_Information *atsi;
+ const char *plugin_address;
+ const char *plugin_name;
+ struct GNUNET_HELLO_Address address;
+ uint16_t plugin_address_length;
+ uint16_t plugin_name_length;
+ uint32_t ats_count;
+ int addr_active;
+
+ if (ntohs (msg->size) < sizeof(struct PeerInformationMessage))
+ {
+ GNUNET_break(0);
+ return GNUNET_SYSERR;
+ }
+
+ pi = (const struct PeerInformationMessage *) msg;
+ ats_count = ntohl (pi->ats_count);
+ plugin_address_length = ntohs (pi->address_length);
+ plugin_name_length = ntohs (pi->plugin_name_length);
+ addr_active = ntohl (pi->address_active);
+ 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;
+ }
+
+ if (NULL != ph->addr_info_cb)
+ {
+ address.peer = pi->peer;
+ address.address = plugin_address;
+ address.address_length = plugin_address_length;
+ address.transport_name = plugin_name;
+
+ ph->addr_info_cb (ph->addr_info_cb_cls, &address, addr_active,
+ pi->bandwidth_out, pi->bandwidth_in, atsi, ats_count);
+ }
+ return GNUNET_OK;
+}
+
+/**
+ * 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_rr_message (struct GNUNET_ATS_PerformanceHandle *ph,
+ const struct GNUNET_MessageHeader *msg)
+{
+ const struct ReservationResultMessage *rr;
+ struct GNUNET_ATS_ReservationContext *rc;
+ int32_t amount;
+
+ if (ntohs (msg->size) < sizeof(struct ReservationResultMessage))
+ {
+ GNUNET_break(0);
+ return GNUNET_SYSERR;
+ }
+ rr = (const struct ReservationResultMessage *) msg;
+ amount = ntohl (rr->amount);
+ rc = ph->reservation_head;
+ if (0 != memcmp (&rr->peer, &rc->peer, sizeof(struct GNUNET_PeerIdentity)))
+ {
+ GNUNET_break(0);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_CONTAINER_DLL_remove(ph->reservation_head, ph->reservation_tail, rc);
+ if ((amount == 0) || (rc->rcb != NULL ))
+ {
+ /* tell client if not cancelled */
+ if (rc->rcb != NULL )
+ rc->rcb (rc->rcb_cls, &rr->peer, amount,
+ GNUNET_TIME_relative_ntoh (rr->res_delay));
+ GNUNET_free(rc);
+ return GNUNET_OK;
+ }
+ /* amount non-zero, but client cancelled, consider undo! */
+ if (GNUNET_YES != rc->undo)
+ {
+ GNUNET_free(rc);
+ return GNUNET_OK; /* do not try to undo failed undos or negative amounts */
+ }
+ GNUNET_free(rc);
+ (void) GNUNET_ATS_reserve_bandwidth (ph, &rr->peer, -amount, NULL, NULL );
+ return GNUNET_OK;