+ size_t msize;
+ uint32_t putl;
+
+ msize = ntohs (msg->header.size) - sizeof (*msg);
+ putl = ntohl (msg->put_path_length);
+ if ((msize / sizeof (struct GNUNET_PeerIdentity)) < putl)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Process a put monitor message from the service.
+ *
+ * @param cls The DHT handle.
+ * @param msg Monitor put message from the service.
+ */
+static void
+handle_monitor_put (void *cls,
+ const struct GNUNET_DHT_MonitorPutMessage *msg)
+{
+ struct GNUNET_DHT_Handle *handle = cls;
+ size_t msize = ntohs (msg->header.size) - sizeof (*msg);
+ uint32_t putl = ntohl (msg->put_path_length);
+ const struct GNUNET_PeerIdentity *path;
+ struct GNUNET_DHT_MonitorHandle *mh;
+
+ path = (const struct GNUNET_PeerIdentity *) &msg[1];
+ for (mh = handle->monitor_head; NULL != mh; mh = mh->next)
+ {
+ if (NULL == mh->put_cb)
+ continue;
+ if ( ( (GNUNET_BLOCK_TYPE_ANY == mh->type) ||
+ (mh->type == ntohl(msg->type)) ) &&
+ ( (NULL == mh->key) ||
+ (0 == memcmp (mh->key,
+ &msg->key,
+ sizeof (struct GNUNET_HashCode))) ) )
+ mh->put_cb (mh->cb_cls,
+ ntohl (msg->options),
+ (enum GNUNET_BLOCK_Type) ntohl(msg->type),
+ ntohl (msg->hop_count),
+ ntohl (msg->desired_replication_level),
+ putl,
+ path,
+ GNUNET_TIME_absolute_ntoh(msg->expiration_time),
+ &msg->key,
+ (const void *) &path[putl],
+ msize - sizeof (struct GNUNET_PeerIdentity) * putl);
+ }
+}
+
+
+/**
+ * Verify that client result message received from the service is well-formed.
+ *
+ * @param cls The DHT handle.
+ * @param msg Monitor put message from the service.
+ * @return #GNUNET_OK if everything went fine,
+ * #GNUNET_SYSERR if the message is malformed.
+ */
+static int
+check_client_result (void *cls,
+ const struct GNUNET_DHT_ClientResultMessage *msg)
+{
+ size_t msize = ntohs (msg->header.size) - sizeof (*msg);
+ uint32_t put_path_length = ntohl (msg->put_path_length);
+ uint32_t get_path_length = ntohl (msg->get_path_length);
+ size_t meta_length;
+
+ meta_length =
+ sizeof (struct GNUNET_PeerIdentity) * (get_path_length + put_path_length);
+ if ( (msize < meta_length) ||
+ (get_path_length >
+ GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) ||
+ (put_path_length >
+ GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) )
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Process a given reply that might match the given request.
+ *
+ * @param cls the `struct GNUNET_DHT_ClientResultMessage`
+ * @param key query of the request
+ * @param value the `struct GNUNET_DHT_GetHandle` of a request matching the same key
+ * @return #GNUNET_YES to continue to iterate over all results
+ */
+static int
+process_client_result (void *cls,
+ const struct GNUNET_HashCode *key,
+ void *value)
+{
+ const struct GNUNET_DHT_ClientResultMessage *crm = cls;
+ struct GNUNET_DHT_GetHandle *get_handle = value;
+ size_t msize = ntohs (crm->header.size) - sizeof (*crm);
+ uint32_t put_path_length = ntohl (crm->put_path_length);
+ uint32_t get_path_length = ntohl (crm->get_path_length);
+ const struct GNUNET_PeerIdentity *put_path;
+ const struct GNUNET_PeerIdentity *get_path;
+ struct GNUNET_HashCode hc;
+ size_t data_length;
+ size_t meta_length;
+ const void *data;
+
+ if (crm->unique_id != get_handle->unique_id)
+ {
+ /* UID mismatch */
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Ignoring reply for %s: UID mismatch: %llu/%llu\n",
+ GNUNET_h2s (key),
+ crm->unique_id,
+ get_handle->unique_id);