diff --git a/client.py b/client.py index 49c0b3e..ffe16d9 100644 --- a/client.py +++ b/client.py @@ -7,80 +7,15 @@ import time import requests from utils import make_signature +from languages import c_lang_config, c_lang_spj_config, cpp_lang_config, java_lang_config -c_lang_config = { - "name": "c", - "compile": { - "src_name": "main.c", - "exe_name": "main", - "max_cpu_time": 3000, - "max_real_time": 5000, - "max_memory": 128 * 1024 * 1024, - "compile_command": "/usr/bin/gcc -DONLINE_JUDGE -O2 -w -fmax-errors=3 -std=c99 -static {src_path} -lm -o {exe_path}", - }, - "run": { - "command": "{exe_path}", - "seccomp_rule": "c_cpp", - "max_process_number": 5 - }, - "spj_compile": { - "src_name": "spj-{spj_version}.c", - "exe_name": "spj-{spj_version}", - "max_cpu_time": 10000, - "max_real_time": 20000, - "max_memory": 1024 * 1024 * 1024, - "compile_command": "/usr/bin/gcc -DONLINE_JUDGE -O2 -w -fmax-errors=3 -std=c99 {src_path} -lm -o {exe_path}", - # server should replace to real info - "version": "1", - "src": "" - } -} - - -cpp_lang_config = { - "name": "cpp", - "compile": { - "src_name": "main.cpp", - "exe_name": "main", - "max_cpu_time": 3000, - "max_real_time": 5000, - "max_memory": 128 * 1024 * 1024, - "compile_command": "/usr/bin/g++ -DONLINE_JUDGE -O2 -w -fmax-errors=3 -std=c++11 {src_path} -lm -o {exe_path}", - }, - "run": { - "command": "{exe_path}", - "seccomp_rule": "c_cpp", - "max_process_number": 5 - } -} - - -java_lang_config = { - "name": "java", - "compile": { - "src_name": "Main.java", - "exe_name": "Main", - "max_cpu_time": 3000, - "max_real_time": 5000, - "max_memory": -1, - "compile_command": "/usr/bin/javac {src_path} -d {exe_dir} -encoding UTF8" - }, - "run": { - "command": "/usr/bin/java -cp {exe_dir} -Xss1M -XX:MaxPermSize=16M -XX:PermSize=8M -Xms16M -Xmx{max_memory}k -Djava.security.manager -Djava.security.policy==/server/java_policy -Djava.awt.headless=true Main", - "seccomp_rule": None, - "max_process_number": -1 - } -} submission_id = str(int(time.time())) c_config = c_lang_config -c_config["spj_compile"]["version"] = "1027" -c_config["spj_compile"]["src"] = "#include\nint main(){//哈哈哈哈\nwhile(1);return 0;}" token = hashlib.sha256("token").hexdigest() - c_src = r""" #include int main(){ @@ -113,7 +48,7 @@ public class Main{ Scanner in=new Scanner(System.in); int a=in.nextInt(); int b=in.nextInt(); - System.out.println((a / (b - 2))); + System.out.println(a + b); } } """ @@ -126,12 +61,12 @@ def judge(): src=java_src, max_cpu_time=1000, max_memory=1024 * 1024 * 1024, test_case_id="d28280c6f3c5ddeadfecc3956a52da3a") - r = requests.post("http://192.168.99.100:8080/judge", data=json.dumps(data)) + r = requests.post("http://123.57.151.42:11235/judge", data=json.dumps(data)) print r.json() def ping(): - r = requests.post("http://192.168.99.100:8080/ping", data=json.dumps({})) + r = requests.post("http://123.57.151.42:11235/ping", data=json.dumps({})) print r.json() ping() diff --git a/docker-compose.example.yml b/docker-compose.example.yml index 7fb7c1e..e1b24e0 100644 --- a/docker-compose.example.yml +++ b/docker-compose.example.yml @@ -4,7 +4,7 @@ judge_server: - /data/test_case:/test_case - /data/log:/log - /data/JudgeServer:/code - environments: + environment: - judger_token=PLEASE_REPLACE_TO_SECRET_TOKEN ports: - "0.0.0.0:11235:8080" diff --git a/languages.py b/languages.py new file mode 100644 index 0000000..c408ef0 --- /dev/null +++ b/languages.py @@ -0,0 +1,68 @@ +# coding=utf-8 +from __future__ import unicode_literals + +c_lang_config = { + "name": "c", + "compile": { + "src_name": "main.c", + "exe_name": "main", + "max_cpu_time": 3000, + "max_real_time": 5000, + "max_memory": 128 * 1024 * 1024, + "compile_command": "/usr/bin/gcc -DONLINE_JUDGE -O2 -w -fmax-errors=3 -std=c99 -static {src_path} -lm -o {exe_path}", + }, + "run": { + "command": "{exe_path}", + "seccomp_rule": "c_cpp", + "max_process_number": 5 + } +} + + +c_lang_spj_config = { + "src_name": "spj-{spj_version}.c", + "exe_name": "spj-{spj_version}", + "max_cpu_time": 10000, + "max_real_time": 20000, + "max_memory": 1024 * 1024 * 1024, + "compile_command": "/usr/bin/gcc -DONLINE_JUDGE -O2 -w -fmax-errors=3 -std=c99 {src_path} -lm -o {exe_path}", + # server should replace to real info + "version": "1", + "src": "" +} + + +cpp_lang_config = { + "name": "cpp", + "compile": { + "src_name": "main.cpp", + "exe_name": "main", + "max_cpu_time": 3000, + "max_real_time": 5000, + "max_memory": 128 * 1024 * 1024, + "compile_command": "/usr/bin/g++ -DONLINE_JUDGE -O2 -w -fmax-errors=3 -std=c++11 {src_path} -lm -o {exe_path}", + }, + "run": { + "command": "{exe_path}", + "seccomp_rule": "c_cpp", + "max_process_number": 5 + } +} + + +java_lang_config = { + "name": "java", + "compile": { + "src_name": "Main.java", + "exe_name": "Main", + "max_cpu_time": 3000, + "max_real_time": 5000, + "max_memory": -1, + "compile_command": "/usr/bin/javac {src_path} -d {exe_dir} -encoding UTF8" + }, + "run": { + "command": "/usr/bin/java -cp {exe_dir} -Xss1M -XX:MaxPermSize=16M -XX:PermSize=8M -Xms16M -Xmx{max_memory}k -Djava.security.manager -Djava.security.policy==/etc/java_policy -Djava.awt.headless=true Main", + "seccomp_rule": None, + "max_process_number": -1 + } +} \ No newline at end of file diff --git a/server.py b/server.py index e4f42cd..d684dc0 100644 --- a/server.py +++ b/server.py @@ -4,19 +4,21 @@ from __future__ import unicode_literals import hashlib import json import os -import socket import shutil +import socket -import web import _judger import psutil +import web -from judge_client import JudgeClient from compiler import Compiler from config import JUDGER_WORKSPACE_BASE, TEST_CASE_DIR from exception import SignatureVerificationFailed, CompileError, SPJCompileError +from judge_client import JudgeClient from utils import make_signature, check_signature +DEBUG = os.environ.get("judger_debug") == "1" + class InitSubmissionEnv(object): def __init__(self, judger_workspace, submission_id): @@ -28,7 +30,8 @@ class InitSubmissionEnv(object): return self.path def __exit__(self, exc_type, exc_val, exc_tb): - shutil.rmtree(self.path, ignore_errors=True) + if not DEBUG: + shutil.rmtree(self.path, ignore_errors=True) class JudgeServer(object): @@ -50,11 +53,12 @@ class JudgeServer(object): raise SignatureVerificationFailed("token not set") return hashlib.sha256(t).hexdigest() - def judge(self, data, signature, timestamp): - # check_signature(token=self._token, data=data, signature=signature, timestamp=timestamp) + def entry(self, data, signature, timestamp, callback): + if not DEBUG: + check_signature(token=self._token, data=data, signature=signature, timestamp=timestamp) ret = {"err": None, "data": None} try: - ret["data"] = self._judge(**json.loads(data)) + ret["data"] = callback(**json.loads(data)) except (CompileError, SPJCompileError, SignatureVerificationFailed) as e: ret["err"] = e.__class__.__name__ ret["data"] = e.message @@ -63,7 +67,7 @@ class JudgeServer(object): ret["data"] = ": ".join([e.__class__.__name__, e.message]) return make_signature(token=self._token, **ret) - def _judge(self, language_config, submission_id, src, max_cpu_time, max_memory, test_case_id): + def judge(self, language_config, submission_id, src, max_cpu_time, max_memory, test_case_id): # init compile_config = language_config["compile"] spj_compile_config = language_config.get("spj_compile") @@ -87,39 +91,39 @@ class JudgeServer(object): test_case_id=test_case_id, submission_dir=submission_dir) run_result = judge_client.run() - - if spj_compile_config: - spj_compile_config["src_name"] = spj_compile_config["src_name"].format(spj_version=spj_compile_config["version"]) - spj_compile_config["exe_name"] = spj_compile_config["exe_name"].format(spj_version=spj_compile_config["version"]) - - spj_src_path = os.path.join(TEST_CASE_DIR, test_case_id, spj_compile_config["src_name"]) - spj_exe_path = os.path.join(TEST_CASE_DIR, test_case_id, spj_compile_config["exe_name"]) - - # if spj source code not found, then write it into file - if not os.path.exists(spj_src_path): - with open(spj_src_path, "w") as f: - f.write(spj_compile_config["src"].encode("utf-8")) - - # if spj exe file not found, then compile it - if not os.path.exists(spj_exe_path): - try: - spj_exe_path = Compiler().compile(compile_config=spj_compile_config, - src_path=spj_src_path, - output_dir=os.path.join(TEST_CASE_DIR, test_case_id)) - # turn common CompileError into SPJCompileError - except CompileError as e: - raise SPJCompileError(e.message) return run_result + def compile_spj(self, spj_compile_config, test_case_id): + spj_compile_config["src_name"] = spj_compile_config["src_name"].format(spj_version=spj_compile_config["version"]) + spj_compile_config["exe_name"] = spj_compile_config["exe_name"].format(spj_version=spj_compile_config["version"]) + + spj_src_path = os.path.join(TEST_CASE_DIR, test_case_id, spj_compile_config["src_name"]) + + # if spj source code not found, then write it into file + if not os.path.exists(spj_src_path): + with open(spj_src_path, "w") as f: + f.write(spj_compile_config["src"].encode("utf-8")) + try: + Compiler().compile(compile_config=spj_compile_config, + src_path=spj_src_path, + output_dir=os.path.join(TEST_CASE_DIR, test_case_id)) + # turn common CompileError into SPJCompileError + except CompileError as e: + raise SPJCompileError(e.message) + return "success" + def POST(self): try: data = json.loads(web.data()) - print web.ctx["path"] if web.ctx["path"] == "/judge": - return json.dumps(self.judge(**data)) - if web.ctx["path"] == "/ping": - return json.dumps(self.pong()) - return {"err": "invalid-method", "data": None} + callback = self.judge + elif web.ctx["path"] == "/ping": + callback = self.pong + elif web.ctx["path"] == "/compile_spj": + callback = self.compile_spj + else: + return {"err": "invalid-method", "data": None} + return json.dumps(self.entry(data=data["data"], signature=data["signature"], timestamp=data["timestamp"], callback=callback)) except Exception as e: ret = dict() ret["err"] = "ServerError" @@ -129,7 +133,8 @@ class JudgeServer(object): urls = ( "/judge", "JudgeServer", - "/ping", "JudgeServer" + "/ping", "JudgeServer", + "/compile_spj", "JudgerServer" ) if not os.environ.get("judger_token"): diff --git a/utils.py b/utils.py index fd99035..0b25fe1 100644 --- a/utils.py +++ b/utils.py @@ -17,7 +17,7 @@ def make_signature(**kwargs): def check_signature(token, data, signature, timestamp): ts = int(time.time()) - if abs(timestamp - ts) > 5: + if abs(timestamp - ts) > 10: raise SignatureVerificationFailed("Timestamp interval is too long") if hashlib.sha256(data + str(timestamp) + token).hexdigest() != signature: