+static int _iterargs_(struct iterdata *id, enum MHD_ValueKind kind, const char *key, const char *value)
+{
+ if (get_data(id->hreq, key, 0))
+ return 1;
+ return id->iterator(id->closure, (struct afb_arg){
+ .name = key,
+ .value = value,
+ .size = 0,
+ .is_file = 0
+ });
+}
+
+static void req_iterate(struct afb_hreq *hreq, int (*iterator)(void *closure, struct afb_arg arg), void *closure)
+{
+ struct iterdata id = { .hreq = hreq, .iterator = iterator, .closure = closure };
+ struct hreq_data *hdat = hreq->data;
+ while (hdat) {
+ if (!iterator(closure, (struct afb_arg){
+ .name = hdat->key,
+ .value = hdat->value,
+ .size = hdat->length,
+ .is_file = (hdat->file != 0)}))
+ return;
+ hdat = hdat->next;
+ }
+ MHD_get_connection_values (hreq->connection, MHD_GET_ARGUMENT_KIND, (void*)_iterargs_, &id);
+}
+
+void afb_hreq_drop_data(struct afb_hreq *hreq)
+{
+ struct hreq_data *data = hreq->data;
+ while (data) {
+ hreq->data = data->next;
+ free(data->key);
+ free(data->value);
+ free(data);
+ data = hreq->data;
+ }
+}
+static ssize_t send_json_cb(json_object *obj, uint64_t pos, char *buf, size_t max)
+{
+ ssize_t len = stpncpy(buf, json_object_to_json_string(obj)+pos, max) - buf;
+ return len ? : -1;
+}
+
+static void req_reply(struct afb_hreq *hreq, unsigned retcode, const char *status, const char *info, json_object *resp)
+{
+ json_object *root, *request;
+ struct MHD_Response *response;
+
+ root = json_object_new_object();
+ json_object_object_add(root, "jtype", json_object_new_string("afb-reply"));
+ request = json_object_new_object();
+ json_object_object_add(root, "request", request);
+ json_object_object_add(request, "status", json_object_new_string(status));
+ if (info)
+ json_object_object_add(request, "info", json_object_new_string(info));
+ if (resp)
+ json_object_object_add(root, "response", resp);
+
+ response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, SIZE_RESPONSE_BUFFER, (void*)send_json_cb, root, (void*)json_object_put);
+ MHD_queue_response(hreq->connection, retcode, response);
+ MHD_destroy_response(response);
+}
+
+static void req_fail(struct afb_hreq *hreq, const char *status, const char *info)
+{
+ req_reply(hreq, MHD_HTTP_OK, status, info, NULL);
+}
+
+static void req_success(struct afb_hreq *hreq, json_object *obj, const char *info)
+{
+ req_reply(hreq, MHD_HTTP_OK, "success", info, obj);
+}
+