X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=submit%2Fcommands.c;h=6abd935f0f30cd9f3bbf4ed2d491b74df1e4ae16;hb=92811b1aa5a791bc776b58afb241a7d93e737604;hp=49440993d73b8975accfa299899b3c8b65a8b1f6;hpb=bdd61c84b621a5b53a78c7401094720ac1529126;p=eval.git diff --git a/submit/commands.c b/submit/commands.c index 4944099..6abd935 100644 --- a/submit/commands.c +++ b/submit/commands.c @@ -6,14 +6,13 @@ #include "lib/lib.h" #include "lib/mempool.h" -#include "lib/stkstring.h" #include "sherlock/object.h" #include "sherlock/objread.h" -#include - #include "submitd.h" +/*** REQUESTS AND REPLIES ***/ + static void NONRET read_error_cb(struct obj_read_state *st UNUSED, byte *msg) { @@ -61,6 +60,8 @@ read_request(struct conn *c) static void write_reply(struct conn *c) { + if (!obj_find_attr(c->reply, '-') && !obj_find_attr(c->reply, '+')) + obj_set_attr(c->reply, '+', "OK"); if (trace_commands) { byte *msg; @@ -71,24 +72,98 @@ write_reply(struct conn *c) else log(L_DEBUG, ">> ???"); } - put_attr_set_type(BUCKET_TYPE_PLAIN); - bput_object(&c->tx_fb, c->reply); + obj_write(&c->tx_fb, c->reply, BUCKET_TYPE_PLAIN); bputc(&c->tx_fb, '\n'); bflush(&c->tx_fb); } +static void +err(struct conn *c, byte *msg) +{ + obj_set_attr(c->reply, '-', msg); +} + +/*** SUBMIT ***/ + +static struct fastbuf * +read_attachment(struct conn *c) +{ + uns size = obj_find_anum(c->request, 'S', 0); + if (size > max_attachment_size) + { + err(c, "Submission too large"); + return NULL; + } + obj_set_attr(c->reply, '+', "Go on"); + write_reply(c); + obj_set_attr(c->reply, '+', NULL); + + // This is less efficient than bbcopy(), but we want our own error handling. + struct fastbuf *fb = bopen_tmp(4096); + byte buf[4096]; + uns remains = size; + while (remains) + { + uns cnt = bread(&c->rx_fb, buf, MIN(remains, (uns)sizeof(buf))); + if (!cnt) + { + bclose(fb); + client_error("Truncated attachment"); + } + bwrite(fb, buf, cnt); + remains -= cnt; + } + brewind(fb); + return fb; +} + +static void +cmd_submit(struct conn *c) +{ + byte *tname = obj_find_aval(c->request, 'T'); + if (!tname) + { + err(c, "No task specified"); + return; + } + struct task *task = task_find(tname); + if (!task) + { + err(c, "No such task"); + return; + } + struct fastbuf *fb = read_attachment(c); + if (!fb) + return; + + // FIXME: Check contest time + // FIXME: Keep history of submitted tasks + // FIXME: File names + + task_lock_status(c); + struct odes *o = task_status_find_task(c, task); + task_submit(c, task, fb, task->name); + log(L_INFO, "User %s submitted task %s", c->user, task->name); + task_unlock_status(c, 1); +} + +/*** COMMAND MUX ***/ + static void execute_command(struct conn *c) { byte *cmd = obj_find_aval(c->request, '!'); if (!cmd) { - obj_set_attr(c->reply, '-', "Missing command"); + err(c, "Missing command"); return; } if (trace_commands) log(L_DEBUG, "<< %s", cmd); - obj_set_attr(c->reply, '-', "Unknown command"); + if (!strcasecmp(cmd, "SUBMIT")) + cmd_submit(c); + else + err(c, "Unknown command"); } int @@ -101,13 +176,7 @@ process_command(struct conn *c) return 1; } -static int -user_exists_p(byte *user) -{ - byte *fn = stk_printf("solutions/%s/status", user); - struct stat st; - return !stat(fn, &st) && S_ISREG(st.st_mode); -} +/*** INITIAL HANDSHAKE ***/ static void execute_init(struct conn *c) @@ -115,7 +184,7 @@ execute_init(struct conn *c) byte *user = obj_find_aval(c->request, 'U'); if (!user) { - obj_set_attr(c->reply, '-', "Missing user"); + err(c, "Missing user"); return; } if (!c->cert_name || @@ -124,18 +193,17 @@ execute_init(struct conn *c) { if (!user_exists_p(user)) { - obj_set_attr(c->reply, '-', "Unknown user"); + err(c, "Unknown user"); return; } log(L_INFO, "Logged in %s", user); } else { - obj_set_attr(c->reply, '-', "Permission denied"); + err(c, "Permission denied"); log(L_ERROR, "Unauthorized attempt to log in as %s", user); return; } - obj_set_attr(c->reply, '+', "OK"); c->user = xstrdup(user); } @@ -146,5 +214,5 @@ process_init(struct conn *c) return 0; execute_init(c); write_reply(c); - return !!obj_find_attr(c->reply, '+'); + return !obj_find_attr(c->reply, '-'); }