2 * The Submit Daemon: High-Level Part of the Protocol
4 * (c) 2007 Martin Mares <mj@ucw.cz>
8 #include "lib/mempool.h"
9 #include "sherlock/object.h"
10 #include "sherlock/objread.h"
14 /*** REQUESTS AND REPLIES ***/
17 read_error_cb(struct obj_read_state *st UNUSED, byte *msg)
19 client_error("Request parse error: %s", msg);
23 read_request(struct conn *c)
28 c->pool = mp_new(1024);
29 c->request = obj_new(c->pool);
30 c->reply = obj_new(c->pool);
32 struct obj_read_state st;
33 obj_read_start(&st, c->request);
34 st.error_callback = read_error_cb;
39 int l = bgets_nodie(&c->rx_fb, line, sizeof(line));
41 client_error("Request line too long");
47 client_error("Truncated request");
52 if (size >= max_request_size)
53 client_error("Request too long");
54 obj_read_attr(&st, line[0], line+1);
61 write_reply(struct conn *c)
63 if (!obj_find_attr(c->reply, '-') && !obj_find_attr(c->reply, '+'))
64 obj_set_attr(c->reply, '+', "OK");
68 if (msg = obj_find_aval(c->reply, '-'))
69 log(L_DEBUG, ">> -%s", msg);
70 else if (msg = obj_find_aval(c->reply, '+'))
71 log(L_DEBUG, ">> +%s", msg);
73 log(L_DEBUG, ">> ???");
75 obj_write(&c->tx_fb, c->reply, BUCKET_TYPE_PLAIN);
76 bputc(&c->tx_fb, '\n');
81 err(struct conn *c, byte *msg)
83 obj_set_attr(c->reply, '-', msg);
88 static struct fastbuf *
89 read_attachment(struct conn *c)
91 uns size = obj_find_anum(c->request, 'S', 0);
92 if (size > max_attachment_size)
94 err(c, "Submission too large");
97 obj_set_attr(c->reply, '+', "Go on");
99 obj_set_attr(c->reply, '+', NULL);
101 // This is less efficient than bbcopy(), but we want our own error handling.
102 struct fastbuf *fb = bopen_tmp(4096);
107 uns cnt = bread(&c->rx_fb, buf, MIN(remains, (uns)sizeof(buf)));
111 client_error("Truncated attachment");
113 bwrite(fb, buf, cnt);
121 cmd_submit(struct conn *c)
123 byte *tname = obj_find_aval(c->request, 'T');
126 err(c, "No task specified");
129 struct task *task = task_find(tname);
132 err(c, "No such task");
135 struct fastbuf *fb = read_attachment(c);
139 // FIXME: Check contest time
140 // FIXME: Keep history of submitted tasks
144 struct odes *o = task_status_find_task(c, task);
145 task_submit(c, task, fb, task->name);
146 log(L_INFO, "User %s submitted task %s", c->user, task->name);
147 task_unlock_status(c, 1);
150 /*** COMMAND MUX ***/
153 execute_command(struct conn *c)
155 byte *cmd = obj_find_aval(c->request, '!');
158 err(c, "Missing command");
162 log(L_DEBUG, "<< %s", cmd);
163 if (!strcasecmp(cmd, "SUBMIT"))
166 err(c, "Unknown command");
170 process_command(struct conn *c)
172 if (!read_request(c))
179 /*** INITIAL HANDSHAKE ***/
182 execute_init(struct conn *c)
184 byte *user = obj_find_aval(c->request, 'U');
187 err(c, "Missing user");
191 !strcmp(user, c->cert_name) ||
192 c->rule->allow_admin && !strcmp(c->cert_name, "admin"))
194 if (!user_exists_p(user))
196 err(c, "Unknown user");
199 log(L_INFO, "Logged in %s", user);
203 err(c, "Permission denied");
204 log(L_ERROR, "Unauthorized attempt to log in as %s", user);
207 c->user = xstrdup(user);
211 process_init(struct conn *c)
213 if (!read_request(c))
217 return !obj_find_attr(c->reply, '-');