]> mj.ucw.cz Git - eval.git/blobdiff - submit/commands.c
Further bits of submit command.
[eval.git] / submit / commands.c
index 49440993d73b8975accfa299899b3c8b65a8b1f6..6abd935f0f30cd9f3bbf4ed2d491b74df1e4ae16 100644 (file)
@@ -6,14 +6,13 @@
 
 #include "lib/lib.h"
 #include "lib/mempool.h"
 
 #include "lib/lib.h"
 #include "lib/mempool.h"
-#include "lib/stkstring.h"
 #include "sherlock/object.h"
 #include "sherlock/objread.h"
 
 #include "sherlock/object.h"
 #include "sherlock/objread.h"
 
-#include <sys/stat.h>
-
 #include "submitd.h"
 
 #include "submitd.h"
 
+/*** REQUESTS AND REPLIES ***/
+
 static void NONRET
 read_error_cb(struct obj_read_state *st UNUSED, byte *msg)
 {
 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)
 {
 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;
   if (trace_commands)
     {
       byte *msg;
@@ -71,24 +72,98 @@ write_reply(struct conn *c)
       else
        log(L_DEBUG, ">> ???");
     }
       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);
 }
 
   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)
     {
 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);
       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
 }
 
 int
@@ -101,13 +176,7 @@ process_command(struct conn *c)
   return 1;
 }
 
   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)
 
 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)
     {
   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 ||
       return;
     }
   if (!c->cert_name ||
@@ -124,18 +193,17 @@ execute_init(struct conn *c)
     {
       if (!user_exists_p(user))
        {
     {
       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
     {
          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;
     }
       log(L_ERROR, "Unauthorized attempt to log in as %s", user);
       return;
     }
-  obj_set_attr(c->reply, '+', "OK");
   c->user = xstrdup(user);
 }
 
   c->user = xstrdup(user);
 }
 
@@ -146,5 +214,5 @@ process_init(struct conn *c)
     return 0;
   execute_init(c);
   write_reply(c);
     return 0;
   execute_init(c);
   write_reply(c);
-  return !!obj_find_attr(c->reply, '+');
+  return !obj_find_attr(c->reply, '-');
 }
 }