Add /v1/pel/run endpoint
This commit is contained in:
parent
dc89345b3e
commit
08922ef22d
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,2 +1,4 @@
|
||||||
/build/
|
/build/
|
||||||
*.sock
|
*.sock
|
||||||
|
.amduat-asl/
|
||||||
|
artifact.bin
|
||||||
|
|
|
||||||
|
|
@ -15,5 +15,6 @@ target_include_directories(amduatd
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(amduatd
|
target_link_libraries(amduatd
|
||||||
PRIVATE amduat_asl_store_fs amduat_asl amduat_enc amduat_hash_asl1 amduat_util
|
PRIVATE amduat_pel amduat_format amduat_asl_store_fs amduat_asl amduat_enc
|
||||||
|
amduat_hash_asl1 amduat_util
|
||||||
)
|
)
|
||||||
|
|
|
||||||
11
README.md
11
README.md
|
|
@ -58,6 +58,14 @@ curl --unix-socket amduatd.sock \
|
||||||
'http://localhost/v1/artifacts/<ref>?format=artifact' --output artifact.bin
|
'http://localhost/v1/artifacts/<ref>?format=artifact' --output artifact.bin
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Run a PEL program from store-backed refs (default `scheme_ref=dag`):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl --unix-socket amduatd.sock -X POST http://localhost/v1/pel/run \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-d '{"program_ref":"<program_ref>","input_refs":["<input_ref_0>"],"params_ref":"<params_ref>"}'
|
||||||
|
```
|
||||||
|
|
||||||
## Current endpoints
|
## Current endpoints
|
||||||
|
|
||||||
- `GET /v1/meta` → `{store_id, encoding_profile_id, hash_id}`
|
- `GET /v1/meta` → `{store_id, encoding_profile_id, hash_id}`
|
||||||
|
|
@ -67,6 +75,9 @@ curl --unix-socket amduatd.sock \
|
||||||
- `GET|HEAD /v1/artifacts/{ref}`
|
- `GET|HEAD /v1/artifacts/{ref}`
|
||||||
- raw bytes default
|
- raw bytes default
|
||||||
- artifact framing: `?format=artifact`
|
- artifact framing: `?format=artifact`
|
||||||
|
- `POST /v1/pel/run`
|
||||||
|
- request: `{program_ref, input_refs[], params_ref?, scheme_ref?}` (refs are hex strings; omit `scheme_ref` to use `dag`)
|
||||||
|
- response: `{result_ref, trace_ref?, output_refs[], status}`
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
|
|
|
||||||
766
src/amduatd.c
766
src/amduatd.c
|
|
@ -6,6 +6,10 @@
|
||||||
#include "amduat/asl/ref_text.h"
|
#include "amduat/asl/ref_text.h"
|
||||||
#include "amduat/asl/store.h"
|
#include "amduat/asl/store.h"
|
||||||
#include "amduat/enc/asl1_core_codec.h"
|
#include "amduat/enc/asl1_core_codec.h"
|
||||||
|
#include "amduat/enc/pel1_result.h"
|
||||||
|
#include "amduat/format/pel.h"
|
||||||
|
#include "amduat/pel/program_dag_desc.h"
|
||||||
|
#include "amduat/pel/run.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
@ -288,6 +292,364 @@ static const char *amduatd_query_param(const char *path,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *data;
|
||||||
|
size_t len;
|
||||||
|
size_t cap;
|
||||||
|
} amduatd_strbuf_t;
|
||||||
|
|
||||||
|
static void amduatd_strbuf_free(amduatd_strbuf_t *b) {
|
||||||
|
if (b == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
free(b->data);
|
||||||
|
b->data = NULL;
|
||||||
|
b->len = 0;
|
||||||
|
b->cap = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduatd_strbuf_reserve(amduatd_strbuf_t *b, size_t extra) {
|
||||||
|
size_t need;
|
||||||
|
size_t next_cap;
|
||||||
|
char *next;
|
||||||
|
|
||||||
|
if (b == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (extra > (SIZE_MAX - b->len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
need = b->len + extra;
|
||||||
|
if (need <= b->cap) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
next_cap = b->cap != 0 ? b->cap : 256u;
|
||||||
|
while (next_cap < need) {
|
||||||
|
if (next_cap > (SIZE_MAX / 2u)) {
|
||||||
|
next_cap = need;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
next_cap *= 2u;
|
||||||
|
}
|
||||||
|
next = (char *)realloc(b->data, next_cap);
|
||||||
|
if (next == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
b->data = next;
|
||||||
|
b->cap = next_cap;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduatd_strbuf_append(amduatd_strbuf_t *b,
|
||||||
|
const char *s,
|
||||||
|
size_t n) {
|
||||||
|
if (b == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (n == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (s == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduatd_strbuf_reserve(b, n + 1u)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memcpy(b->data + b->len, s, n);
|
||||||
|
b->len += n;
|
||||||
|
b->data[b->len] = '\0';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduatd_strbuf_append_cstr(amduatd_strbuf_t *b, const char *s) {
|
||||||
|
return amduatd_strbuf_append(b, s != NULL ? s : "", s != NULL ? strlen(s) : 0u);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduatd_strbuf_append_char(amduatd_strbuf_t *b, char c) {
|
||||||
|
return amduatd_strbuf_append(b, &c, 1u);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *amduatd_json_skip_ws(const char *p, const char *end) {
|
||||||
|
while (p < end) {
|
||||||
|
char c = *p;
|
||||||
|
if (c != ' ' && c != '\t' && c != '\n' && c != '\r') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduatd_json_expect(const char **p,
|
||||||
|
const char *end,
|
||||||
|
char expected) {
|
||||||
|
const char *cur;
|
||||||
|
if (p == NULL || *p == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cur = amduatd_json_skip_ws(*p, end);
|
||||||
|
if (cur >= end || *cur != expected) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*p = cur + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduatd_json_parse_string_noesc(const char **p,
|
||||||
|
const char *end,
|
||||||
|
const char **out_start,
|
||||||
|
size_t *out_len) {
|
||||||
|
const char *cur;
|
||||||
|
const char *s;
|
||||||
|
if (out_start != NULL) {
|
||||||
|
*out_start = NULL;
|
||||||
|
}
|
||||||
|
if (out_len != NULL) {
|
||||||
|
*out_len = 0;
|
||||||
|
}
|
||||||
|
if (p == NULL || *p == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cur = amduatd_json_skip_ws(*p, end);
|
||||||
|
if (cur >= end || *cur != '"') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cur++;
|
||||||
|
s = cur;
|
||||||
|
while (cur < end) {
|
||||||
|
unsigned char c = (unsigned char)*cur;
|
||||||
|
if (c == '"') {
|
||||||
|
if (out_start != NULL) {
|
||||||
|
*out_start = s;
|
||||||
|
}
|
||||||
|
if (out_len != NULL) {
|
||||||
|
*out_len = (size_t)(cur - s);
|
||||||
|
}
|
||||||
|
*p = cur + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (c == '\\' || c < 0x20u) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduatd_json_skip_string(const char **p, const char *end) {
|
||||||
|
const char *cur;
|
||||||
|
if (p == NULL || *p == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cur = amduatd_json_skip_ws(*p, end);
|
||||||
|
if (cur >= end || *cur != '"') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cur++;
|
||||||
|
while (cur < end) {
|
||||||
|
unsigned char c = (unsigned char)*cur++;
|
||||||
|
if (c == '"') {
|
||||||
|
*p = cur;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (c == '\\') {
|
||||||
|
if (cur >= end) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cur++;
|
||||||
|
} else if (c < 0x20u) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduatd_json_skip_value(const char **p,
|
||||||
|
const char *end,
|
||||||
|
int depth);
|
||||||
|
|
||||||
|
static bool amduatd_json_skip_array(const char **p,
|
||||||
|
const char *end,
|
||||||
|
int depth) {
|
||||||
|
const char *cur;
|
||||||
|
if (!amduatd_json_expect(p, end, '[')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cur = amduatd_json_skip_ws(*p, end);
|
||||||
|
if (cur < end && *cur == ']') {
|
||||||
|
*p = cur + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
if (!amduatd_json_skip_value(p, end, depth + 1)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cur = amduatd_json_skip_ws(*p, end);
|
||||||
|
if (cur >= end) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (*cur == ',') {
|
||||||
|
*p = cur + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*cur == ']') {
|
||||||
|
*p = cur + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduatd_json_skip_object(const char **p,
|
||||||
|
const char *end,
|
||||||
|
int depth) {
|
||||||
|
const char *cur;
|
||||||
|
if (!amduatd_json_expect(p, end, '{')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cur = amduatd_json_skip_ws(*p, end);
|
||||||
|
if (cur < end && *cur == '}') {
|
||||||
|
*p = cur + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
if (!amduatd_json_skip_string(p, end)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduatd_json_expect(p, end, ':')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduatd_json_skip_value(p, end, depth + 1)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cur = amduatd_json_skip_ws(*p, end);
|
||||||
|
if (cur >= end) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (*cur == ',') {
|
||||||
|
*p = cur + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*cur == '}') {
|
||||||
|
*p = cur + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduatd_json_skip_value(const char **p,
|
||||||
|
const char *end,
|
||||||
|
int depth) {
|
||||||
|
const char *cur;
|
||||||
|
if (p == NULL || *p == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (depth > 32) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cur = amduatd_json_skip_ws(*p, end);
|
||||||
|
if (cur >= end) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (*cur == '"') {
|
||||||
|
return amduatd_json_skip_string(p, end);
|
||||||
|
}
|
||||||
|
if (*cur == '{') {
|
||||||
|
return amduatd_json_skip_object(p, end, depth);
|
||||||
|
}
|
||||||
|
if (*cur == '[') {
|
||||||
|
return amduatd_json_skip_array(p, end, depth);
|
||||||
|
}
|
||||||
|
if (*cur == 't' && (end - cur) >= 4 && memcmp(cur, "true", 4) == 0) {
|
||||||
|
*p = cur + 4;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (*cur == 'f' && (end - cur) >= 5 && memcmp(cur, "false", 5) == 0) {
|
||||||
|
*p = cur + 5;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (*cur == 'n' && (end - cur) >= 4 && memcmp(cur, "null", 4) == 0) {
|
||||||
|
*p = cur + 4;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (*cur == '-' || (*cur >= '0' && *cur <= '9')) {
|
||||||
|
cur++;
|
||||||
|
while (cur < end) {
|
||||||
|
char c = *cur;
|
||||||
|
if ((c >= '0' && c <= '9') || c == '.' || c == 'e' || c == 'E' ||
|
||||||
|
c == '+' || c == '-') {
|
||||||
|
cur++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*p = cur;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduatd_copy_json_str(const char *s,
|
||||||
|
size_t len,
|
||||||
|
char **out) {
|
||||||
|
char *buf;
|
||||||
|
if (out == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*out = NULL;
|
||||||
|
if (len > (SIZE_MAX - 1u)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
buf = (char *)malloc(len + 1u);
|
||||||
|
if (buf == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (len != 0) {
|
||||||
|
memcpy(buf, s, len);
|
||||||
|
}
|
||||||
|
buf[len] = '\0';
|
||||||
|
*out = buf;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduatd_decode_ref_hex_str(const char *s,
|
||||||
|
size_t len,
|
||||||
|
amduat_reference_t *out_ref) {
|
||||||
|
char *tmp = NULL;
|
||||||
|
bool ok;
|
||||||
|
if (out_ref == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memset(out_ref, 0, sizeof(*out_ref));
|
||||||
|
if (!amduatd_copy_json_str(s, len, &tmp)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ok = amduat_asl_ref_decode_hex(tmp, out_ref);
|
||||||
|
free(tmp);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduatd_send_json_error(int fd,
|
||||||
|
int code,
|
||||||
|
const char *reason,
|
||||||
|
const char *msg) {
|
||||||
|
amduatd_strbuf_t b;
|
||||||
|
memset(&b, 0, sizeof(b));
|
||||||
|
if (!amduatd_strbuf_append_cstr(&b, "{\"error\":\"") ||
|
||||||
|
!amduatd_strbuf_append_cstr(&b, msg != NULL ? msg : "error") ||
|
||||||
|
!amduatd_strbuf_append_cstr(&b, "\"}\n")) {
|
||||||
|
amduatd_strbuf_free(&b);
|
||||||
|
return amduatd_http_send_text(fd, 500, "Internal Server Error", "error\n",
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
bool ok = amduatd_http_send_json(fd, code, reason, b.data, false);
|
||||||
|
amduatd_strbuf_free(&b);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void amduatd_path_without_query(const char *path,
|
static void amduatd_path_without_query(const char *path,
|
||||||
char *out,
|
char *out,
|
||||||
size_t cap) {
|
size_t cap) {
|
||||||
|
|
@ -541,6 +903,407 @@ static bool amduatd_handle_post_artifacts(int fd,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool amduatd_handle_post_pel_run(int fd,
|
||||||
|
amduat_asl_store_t *store,
|
||||||
|
const amduatd_http_req_t *req) {
|
||||||
|
uint8_t *body = NULL;
|
||||||
|
const char *p = NULL;
|
||||||
|
const char *end = NULL;
|
||||||
|
bool have_program_ref = false;
|
||||||
|
bool have_input_refs = false;
|
||||||
|
bool have_scheme_ref = false;
|
||||||
|
bool scheme_is_dag = false;
|
||||||
|
bool has_params_ref = false;
|
||||||
|
amduat_reference_t scheme_ref;
|
||||||
|
amduat_reference_t program_ref;
|
||||||
|
amduat_reference_t params_ref;
|
||||||
|
amduat_reference_t *input_refs = NULL;
|
||||||
|
size_t input_refs_len = 0;
|
||||||
|
amduat_pel_run_result_t run_result;
|
||||||
|
int status_code = 200;
|
||||||
|
const char *status_reason = "OK";
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
memset(&scheme_ref, 0, sizeof(scheme_ref));
|
||||||
|
memset(&program_ref, 0, sizeof(program_ref));
|
||||||
|
memset(¶ms_ref, 0, sizeof(params_ref));
|
||||||
|
memset(&run_result, 0, sizeof(run_result));
|
||||||
|
|
||||||
|
if (store == NULL || req == NULL) {
|
||||||
|
return amduatd_send_json_error(fd, 500, "Internal Server Error",
|
||||||
|
"internal error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req->content_length > (1u * 1024u * 1024u)) {
|
||||||
|
return amduatd_send_json_error(fd, 413, "Payload Too Large",
|
||||||
|
"payload too large");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req->content_length == 0) {
|
||||||
|
return amduatd_send_json_error(fd, 400, "Bad Request", "missing body");
|
||||||
|
}
|
||||||
|
|
||||||
|
body = NULL;
|
||||||
|
if (req->content_length != 0) {
|
||||||
|
body = (uint8_t *)malloc(req->content_length);
|
||||||
|
if (body == NULL) {
|
||||||
|
return amduatd_send_json_error(fd, 500, "Internal Server Error", "oom");
|
||||||
|
}
|
||||||
|
if (!amduatd_read_exact(fd, body, req->content_length)) {
|
||||||
|
free(body);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p = (const char *)body;
|
||||||
|
end = (const char *)body + req->content_length;
|
||||||
|
if (!amduatd_json_expect(&p, end, '{')) {
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request", "invalid json");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
const char *key = NULL;
|
||||||
|
size_t key_len = 0;
|
||||||
|
const char *sv = NULL;
|
||||||
|
size_t sv_len = 0;
|
||||||
|
const char *cur = NULL;
|
||||||
|
|
||||||
|
cur = amduatd_json_skip_ws(p, end);
|
||||||
|
if (cur < end && *cur == '}') {
|
||||||
|
p = cur + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduatd_json_parse_string_noesc(&p, end, &key, &key_len)) {
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request",
|
||||||
|
"invalid json key");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
if (!amduatd_json_expect(&p, end, ':')) {
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request", "invalid json");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_len == strlen("program_ref") &&
|
||||||
|
memcmp(key, "program_ref", key_len) == 0) {
|
||||||
|
if (have_program_ref) {
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request",
|
||||||
|
"duplicate program_ref");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
if (!amduatd_json_parse_string_noesc(&p, end, &sv, &sv_len) ||
|
||||||
|
!amduatd_decode_ref_hex_str(sv, sv_len, &program_ref)) {
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request",
|
||||||
|
"invalid program_ref");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
have_program_ref = true;
|
||||||
|
} else if (key_len == strlen("scheme_ref") &&
|
||||||
|
memcmp(key, "scheme_ref", key_len) == 0) {
|
||||||
|
if (have_scheme_ref) {
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request",
|
||||||
|
"duplicate scheme_ref");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
if (!amduatd_json_parse_string_noesc(&p, end, &sv, &sv_len)) {
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request",
|
||||||
|
"invalid scheme_ref");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
if (sv_len == 3 && memcmp(sv, "dag", 3) == 0) {
|
||||||
|
scheme_ref = amduat_pel_program_dag_scheme_ref();
|
||||||
|
scheme_is_dag = true;
|
||||||
|
} else if (!amduatd_decode_ref_hex_str(sv, sv_len, &scheme_ref)) {
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request",
|
||||||
|
"invalid scheme_ref");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
have_scheme_ref = true;
|
||||||
|
} else if (key_len == strlen("params_ref") &&
|
||||||
|
memcmp(key, "params_ref", key_len) == 0) {
|
||||||
|
if (has_params_ref) {
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request",
|
||||||
|
"duplicate params_ref");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
if (!amduatd_json_parse_string_noesc(&p, end, &sv, &sv_len) ||
|
||||||
|
!amduatd_decode_ref_hex_str(sv, sv_len, ¶ms_ref)) {
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request",
|
||||||
|
"invalid params_ref");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
has_params_ref = true;
|
||||||
|
} else if (key_len == strlen("input_refs") &&
|
||||||
|
memcmp(key, "input_refs", key_len) == 0) {
|
||||||
|
size_t cap = 0;
|
||||||
|
if (have_input_refs) {
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request",
|
||||||
|
"duplicate input_refs");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
if (!amduatd_json_expect(&p, end, '[')) {
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request",
|
||||||
|
"invalid input_refs");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
cur = amduatd_json_skip_ws(p, end);
|
||||||
|
if (cur < end && *cur == ']') {
|
||||||
|
p = cur + 1;
|
||||||
|
have_input_refs = true;
|
||||||
|
} else {
|
||||||
|
for (;;) {
|
||||||
|
amduat_reference_t ref;
|
||||||
|
memset(&ref, 0, sizeof(ref));
|
||||||
|
if (!amduatd_json_parse_string_noesc(&p, end, &sv, &sv_len) ||
|
||||||
|
!amduatd_decode_ref_hex_str(sv, sv_len, &ref)) {
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request",
|
||||||
|
"invalid input_ref");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
if (input_refs_len == cap) {
|
||||||
|
size_t next_cap = cap != 0 ? cap * 2u : 4u;
|
||||||
|
amduat_reference_t *next;
|
||||||
|
if (next_cap > (SIZE_MAX / sizeof(*input_refs))) {
|
||||||
|
amduat_reference_free(&ref);
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request",
|
||||||
|
"too many input_refs");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
next = (amduat_reference_t *)realloc(
|
||||||
|
input_refs, next_cap * sizeof(*input_refs));
|
||||||
|
if (next == NULL) {
|
||||||
|
amduat_reference_free(&ref);
|
||||||
|
ok = amduatd_send_json_error(fd, 500, "Internal Server Error",
|
||||||
|
"oom");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
input_refs = next;
|
||||||
|
cap = next_cap;
|
||||||
|
}
|
||||||
|
input_refs[input_refs_len++] = ref;
|
||||||
|
|
||||||
|
cur = amduatd_json_skip_ws(p, end);
|
||||||
|
if (cur >= end) {
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request",
|
||||||
|
"invalid input_refs");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
if (*cur == ',') {
|
||||||
|
p = cur + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*cur == ']') {
|
||||||
|
p = cur + 1;
|
||||||
|
have_input_refs = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request",
|
||||||
|
"invalid input_refs");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!amduatd_json_skip_value(&p, end, 0)) {
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request", "invalid json");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = amduatd_json_skip_ws(p, end);
|
||||||
|
if (cur >= end) {
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request", "invalid json");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
if (*cur == ',') {
|
||||||
|
p = cur + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*cur == '}') {
|
||||||
|
p = cur + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request", "invalid json");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = amduatd_json_skip_ws(p, end);
|
||||||
|
if (p != end) {
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request", "invalid json");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
free(body);
|
||||||
|
body = NULL;
|
||||||
|
|
||||||
|
if (!have_program_ref) {
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request",
|
||||||
|
"missing program_ref");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
if (!have_input_refs) {
|
||||||
|
ok = amduatd_send_json_error(fd, 400, "Bad Request",
|
||||||
|
"missing input_refs");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
if (!have_scheme_ref) {
|
||||||
|
scheme_ref = amduat_pel_program_dag_scheme_ref();
|
||||||
|
scheme_is_dag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_pel_surf_run_with_result(store,
|
||||||
|
scheme_ref,
|
||||||
|
program_ref,
|
||||||
|
input_refs,
|
||||||
|
input_refs_len,
|
||||||
|
has_params_ref,
|
||||||
|
params_ref,
|
||||||
|
&run_result)) {
|
||||||
|
ok = amduatd_send_json_error(fd, 500, "Internal Server Error",
|
||||||
|
"pel run failed");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (run_result.has_result_value && run_result.result_value.has_store_failure) {
|
||||||
|
if (run_result.result_value.store_failure.error_code ==
|
||||||
|
AMDUAT_PEL_STORE_ERROR_NOT_FOUND) {
|
||||||
|
status_code = 404;
|
||||||
|
status_reason = "Not Found";
|
||||||
|
} else {
|
||||||
|
status_code = 500;
|
||||||
|
status_reason = "Internal Server Error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
amduatd_strbuf_t resp;
|
||||||
|
char *result_hex = NULL;
|
||||||
|
char *trace_hex = NULL;
|
||||||
|
const char *status = "UNKNOWN";
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
memset(&resp, 0, sizeof(resp));
|
||||||
|
|
||||||
|
if (!amduat_asl_ref_encode_hex(run_result.result_ref, &result_hex)) {
|
||||||
|
amduatd_strbuf_free(&resp);
|
||||||
|
ok = amduatd_send_json_error(fd, 500, "Internal Server Error",
|
||||||
|
"encode error");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (run_result.has_result_value) {
|
||||||
|
status = amduat_format_pel_status_name(
|
||||||
|
run_result.result_value.core_result.status);
|
||||||
|
if (run_result.result_value.has_trace_ref) {
|
||||||
|
if (!amduat_asl_ref_encode_hex(run_result.result_value.trace_ref,
|
||||||
|
&trace_hex)) {
|
||||||
|
free(result_hex);
|
||||||
|
amduatd_strbuf_free(&resp);
|
||||||
|
ok = amduatd_send_json_error(fd, 500, "Internal Server Error",
|
||||||
|
"encode error");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduatd_strbuf_append_cstr(&resp, "{\"result_ref\":\"") ||
|
||||||
|
!amduatd_strbuf_append_cstr(&resp, result_hex) ||
|
||||||
|
!amduatd_strbuf_append_cstr(&resp, "\"")) {
|
||||||
|
free(result_hex);
|
||||||
|
free(trace_hex);
|
||||||
|
amduatd_strbuf_free(&resp);
|
||||||
|
ok = amduatd_send_json_error(fd, 500, "Internal Server Error", "oom");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
free(result_hex);
|
||||||
|
|
||||||
|
if (trace_hex != NULL) {
|
||||||
|
if (!amduatd_strbuf_append_cstr(&resp, ",\"trace_ref\":\"") ||
|
||||||
|
!amduatd_strbuf_append_cstr(&resp, trace_hex) ||
|
||||||
|
!amduatd_strbuf_append_cstr(&resp, "\"")) {
|
||||||
|
free(trace_hex);
|
||||||
|
amduatd_strbuf_free(&resp);
|
||||||
|
ok = amduatd_send_json_error(fd, 500, "Internal Server Error", "oom");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
free(trace_hex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduatd_strbuf_append_cstr(&resp, ",\"output_refs\":[")) {
|
||||||
|
amduatd_strbuf_free(&resp);
|
||||||
|
ok = amduatd_send_json_error(fd, 500, "Internal Server Error", "oom");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < run_result.output_refs_len; ++i) {
|
||||||
|
char *out_hex = NULL;
|
||||||
|
if (!amduat_asl_ref_encode_hex(run_result.output_refs[i], &out_hex)) {
|
||||||
|
amduatd_strbuf_free(&resp);
|
||||||
|
ok = amduatd_send_json_error(fd, 500, "Internal Server Error",
|
||||||
|
"encode error");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
if (i != 0) {
|
||||||
|
if (!amduatd_strbuf_append_char(&resp, ',')) {
|
||||||
|
free(out_hex);
|
||||||
|
amduatd_strbuf_free(&resp);
|
||||||
|
ok = amduatd_send_json_error(fd, 500, "Internal Server Error", "oom");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!amduatd_strbuf_append_cstr(&resp, "\"") ||
|
||||||
|
!amduatd_strbuf_append_cstr(&resp, out_hex) ||
|
||||||
|
!amduatd_strbuf_append_cstr(&resp, "\"")) {
|
||||||
|
free(out_hex);
|
||||||
|
amduatd_strbuf_free(&resp);
|
||||||
|
ok = amduatd_send_json_error(fd, 500, "Internal Server Error", "oom");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
free(out_hex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduatd_strbuf_append_cstr(&resp, "],\"status\":\"") ||
|
||||||
|
!amduatd_strbuf_append_cstr(&resp, status) ||
|
||||||
|
!amduatd_strbuf_append_cstr(&resp, "\"}\n")) {
|
||||||
|
amduatd_strbuf_free(&resp);
|
||||||
|
ok = amduatd_send_json_error(fd, 500, "Internal Server Error", "oom");
|
||||||
|
goto pel_run_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = amduatd_http_send_json(fd, status_code, status_reason, resp.data, false);
|
||||||
|
amduatd_strbuf_free(&resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
pel_run_cleanup:
|
||||||
|
if (body != NULL) {
|
||||||
|
free(body);
|
||||||
|
}
|
||||||
|
if (run_result.has_result_value) {
|
||||||
|
amduat_enc_pel1_result_free(&run_result.result_value);
|
||||||
|
}
|
||||||
|
if (run_result.output_refs != NULL) {
|
||||||
|
amduat_pel_surf_free_refs(run_result.output_refs, run_result.output_refs_len);
|
||||||
|
}
|
||||||
|
amduat_pel_surf_free_ref(&run_result.result_ref);
|
||||||
|
|
||||||
|
if (input_refs != NULL) {
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < input_refs_len; ++i) {
|
||||||
|
amduat_reference_free(&input_refs[i]);
|
||||||
|
}
|
||||||
|
free(input_refs);
|
||||||
|
}
|
||||||
|
if (has_params_ref) {
|
||||||
|
amduat_reference_free(¶ms_ref);
|
||||||
|
}
|
||||||
|
if (have_program_ref) {
|
||||||
|
amduat_reference_free(&program_ref);
|
||||||
|
}
|
||||||
|
if (have_scheme_ref && !scheme_is_dag) {
|
||||||
|
amduat_reference_free(&scheme_ref);
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
static bool amduatd_handle_conn(int fd,
|
static bool amduatd_handle_conn(int fd,
|
||||||
amduat_asl_store_t *store,
|
amduat_asl_store_t *store,
|
||||||
const amduat_asl_store_fs_config_t *cfg) {
|
const amduat_asl_store_fs_config_t *cfg) {
|
||||||
|
|
@ -563,6 +1326,9 @@ static bool amduatd_handle_conn(int fd,
|
||||||
if (strcmp(req.method, "POST") == 0 && strcmp(no_query, "/v1/artifacts") == 0) {
|
if (strcmp(req.method, "POST") == 0 && strcmp(no_query, "/v1/artifacts") == 0) {
|
||||||
return amduatd_handle_post_artifacts(fd, store, &req);
|
return amduatd_handle_post_artifacts(fd, store, &req);
|
||||||
}
|
}
|
||||||
|
if (strcmp(req.method, "POST") == 0 && strcmp(no_query, "/v1/pel/run") == 0) {
|
||||||
|
return amduatd_handle_post_pel_run(fd, store, &req);
|
||||||
|
}
|
||||||
if (strcmp(req.method, "GET") == 0 &&
|
if (strcmp(req.method, "GET") == 0 &&
|
||||||
strncmp(no_query, "/v1/artifacts/", 14) == 0) {
|
strncmp(no_query, "/v1/artifacts/", 14) == 0) {
|
||||||
return amduatd_handle_get_artifact(fd, store, req.path, false);
|
return amduatd_handle_get_artifact(fd, store, req.path, false);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue