From e90dbf14e93ba7ec7ed8c7522a4e134f607f9fc1 Mon Sep 17 00:00:00 2001 From: milk <53408947@qq.com> Date: Tue, 18 Nov 2025 22:09:19 +0800 Subject: [PATCH] =?UTF-8?q?=E8=88=8D=E5=BC=83flask=E3=80=82=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E5=A2=9E=E5=8A=A0H2=E5=8D=8F=E8=AE=AE=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Module/DeviceInfo.py | 2 +- Module/FlaskService.py | 148 ++++++++++++++++++------------- Module/FlaskSubprocessManager.py | 24 ++++- Module/Main.py | 24 ++--- Utils/LogManager.py | 2 +- build.bat | 2 +- resources/cert.pem | 21 ----- resources/key.pem | 28 ------ resources/server.crt | 21 +++++ resources/server.key | 28 ++++++ 10 files changed, 170 insertions(+), 130 deletions(-) delete mode 100644 resources/cert.pem delete mode 100644 resources/key.pem create mode 100644 resources/server.crt create mode 100644 resources/server.key diff --git a/Module/DeviceInfo.py b/Module/DeviceInfo.py index 04854d3..f9a1b4a 100644 --- a/Module/DeviceInfo.py +++ b/Module/DeviceInfo.py @@ -169,7 +169,7 @@ class DeviceInfo: if getattr(self, "_add_executor", None) is None: from concurrent.futures import ThreadPoolExecutor import os - max_workers = max(2, min(6, (os.cpu_count() or 4) // 2)) + max_workers = int(os.getenv("DEVICE_ADD_WORKERS", "6")) self._add_executor = ThreadPoolExecutor( max_workers=max_workers, thread_name_prefix="dev-add" diff --git a/Module/FlaskService.py b/Module/FlaskService.py index 53b9d2b..40ff274 100644 --- a/Module/FlaskService.py +++ b/Module/FlaskService.py @@ -7,13 +7,16 @@ import time from pathlib import Path from queue import Queue from typing import Any, Dict, List +import anyio +from quart import Quart +from quart_cors import cors + from Entity import Variables from Utils.AiUtils import AiUtils from Utils.IOSAIStorage import IOSAIStorage from Utils.LogManager import LogManager import wda -from flask import Flask, request -from flask_cors import CORS +from quart import Quart, request, g from Entity.ResultData import ResultData from Utils.ControlUtils import ControlUtils from Utils.ThreadManager import ThreadManager @@ -29,8 +32,9 @@ for name in ('werkzeug', 'werkzeug.serving'): log.propagate = False log.handlers.clear() -app = Flask(__name__) -CORS(app) +app = Quart(__name__) # ⭐ 这里用 Quart,而不是 Flask +app = cors(app, allow_origin="*") # 允许所有来源跨域 + app.config['JSON_AS_ASCII'] = False # Flask jsonify 不转义中文/emoji app.config['JSONIFY_MIMETYPE'] = "application/json; charset=utf-8" @@ -277,9 +281,27 @@ def bootstrap_server_side_effects(): def get_app(): return app +@app.before_request +def _log_request_start(): + g._start_ts = time.time() + LogManager.info( + text=f"[HTTP] START {request.method} {request.path}", + udid="flask" + ) + +@app.after_request +def _log_request_end(response): + cost = time.time() - getattr(g, "_start_ts", time.time()) + LogManager.info( + text=f"[HTTP] END {request.method} {request.path} {response.status_code} in {cost:.3f}s", + udid="flask" + ) + return response + + # ============ API 路由 ============ @app.route('/deviceList', methods=['GET']) -def deviceList(): +async def deviceList(): global _last_device_count, change_version global _last_nonempty_snapshot, _last_snapshot_ts, _STICKY_TTL_SEC global _empty_logged, _recovered_logged @@ -315,23 +337,23 @@ def deviceList(): return ResultData(data=[]).toJson() @app.route('/passToken', methods=['POST']) -def passToken(): - data = request.get_json() +async def passToken(): + data = await request.get_json() print(json.dumps(data)) return ResultData(data="").toJson() # 获取设备应用列表 @app.route('/deviceAppList', methods=['POST']) -def deviceAppList(): - param = request.get_json() +async def deviceAppList(): + param = await request.get_json() udid = param["udid"] apps = ControlUtils.getDeviceAppList(udid) return ResultData(data=apps).toJson() # 打开指定app @app.route('/launchApp', methods=['POST']) -def launchApp(): - body = request.get_json() +async def launchApp(): + body = await request.get_json() udid = body.get("udid") bundleId = body.get("bundleId") t = wda.USBClient(udid, wdaFunctionPort) @@ -340,8 +362,8 @@ def launchApp(): # 回到首页 @app.route('/toHome', methods=['POST']) -def toHome(): - body = request.get_json() +async def toHome(): + body = await request.get_json() udid = body.get("udid") client = wda.USBClient(udid, wdaFunctionPort) client.home() @@ -349,8 +371,8 @@ def toHome(): # 点击事件 @app.route('/tapAction', methods=['POST']) -def tapAction(): - body = request.get_json() +async def tapAction(): + body = await request.get_json() udid = body.get("udid") client = wda.USBClient(udid, wdaFunctionPort) print("-----------------------") @@ -365,8 +387,8 @@ def tapAction(): # 拖拽事件 @app.route('/swipeAction', methods=['POST']) -def swipeAction(): - body = request.get_json() +async def swipeAction(): + body = await request.get_json() udid = body.get("udid") duration = body.get("duration") # 时长 sx = body.get("sx") # 起始X点 @@ -383,8 +405,8 @@ def swipeAction(): # 长按事件 @app.route('/longPressAction', methods=['POST']) -def longPressAction(): - body = request.get_json() +async def longPressAction(): + body = await request.get_json() udid = body.get("udid") x = body.get("x") y = body.get("y") @@ -396,8 +418,8 @@ def longPressAction(): # 养号 @app.route('/growAccount', methods=['POST']) -def growAccount(): - body = request.get_json() +async def growAccount(): + body = await request.get_json() udid = body.get("udid") Variables.commentList = body.get("comment") isComment = body.get("isComment") @@ -412,8 +434,8 @@ def growAccount(): # 观看直播 @app.route("/watchLiveForGrowth", methods=['POST']) -def watchLiveForGrowth(): - body = request.get_json() +async def watchLiveForGrowth(): + body = await request.get_json() udid = body.get("udid") manager = ScriptManager() event = threading.Event() @@ -424,8 +446,8 @@ def watchLiveForGrowth(): # 停止脚本 @app.route("/stopScript", methods=['POST']) -def stopScript(): - body = request.get_json() +async def stopScript(): + body = await request.get_json() udid = body.get("udid") LogManager.method_info(f"接口收到 /stopScript udid={udid}", method="task") code, msg = ThreadManager.stop(udid) @@ -433,10 +455,10 @@ def stopScript(): # 关注打招呼 @app.route('/passAnchorData', methods=['POST']) -def passAnchorData(): +async def passAnchorData(): try: LogManager.method_info("关注打招呼", "关注打招呼") - data: Dict[str, Any] = request.get_json() + data: Dict[str, Any] = await request.get_json() # 设备列表 idList = data.get("deviceList", []) # 主播列表 @@ -469,10 +491,10 @@ def passAnchorData(): return ResultData(data="", code=1001).toJson() @app.route('/followAndGreetUnion', methods=['POST']) -def followAndGreetUnion(): +async def followAndGreetUnion(): try: LogManager.method_info("关注打招呼", "关注打招呼(联盟号)") - data: Dict[str, Any] = request.get_json() + data: Dict[str, Any] = await request.get_json() # 设备列表 idList = data.get("deviceList", []) # 主播列表 @@ -510,20 +532,20 @@ def followAndGreetUnion(): # 获取私信数据 @app.route("/getPrologueList", methods=['GET']) -def getPrologueList(): +async def getPrologueList(): import Entity.Variables as Variables return ResultData(data=Variables.prologueList).toJson() # 添加临时数据 # 批量追加主播到 JSON 文件 @app.route("/addTempAnchorData", methods=['POST']) -def addTempAnchorData(): +async def addTempAnchorData(): """ 请求体支持: - 单个对象:{"anchorId": "xxx", "country": "CN"} - 对象数组:[{"anchorId": "xxx", "country": "CN"}, {"anchorId": "yyy", "country": "US"}] """ - data = request.get_json() + data = await request.get_json() if not data: return ResultData(code=400, message="请求数据为空").toJson() # 追加到 JSON 文件 @@ -532,8 +554,8 @@ def addTempAnchorData(): # 获取当前屏幕上的聊天信息 @app.route("/getChatTextInfo", methods=['POST']) -def getChatTextInfo(): - data = request.get_json() +async def getChatTextInfo(): + data = await request.get_json() udid = data.get("udid") client = wda.USBClient(udid,wdaFunctionPort) session = client.session() @@ -578,9 +600,9 @@ def getChatTextInfo(): # 监控消息 @app.route("/replyMessages", methods=['POST']) -def monitorMessages(): +async def monitorMessages(): LogManager.method_info("开始监控消息,监控消息脚本启动", "监控消息") - body = request.get_json() + body = await request.get_json() udid = body.get("udid") # Variables.commentList = body.get("comment") @@ -594,8 +616,8 @@ def monitorMessages(): # 上传日志 @app.route("/setLoginInfo", methods=['POST']) -def upLoadLogLogs(): - data = request.get_json() # 解析 JSON +async def upLoadLogLogs(): + data = await request.get_json() # 解析 JSON token = data.get("token") userId = data.get("userId") tenantId = data.get("tenantId") @@ -607,7 +629,7 @@ def upLoadLogLogs(): # 获取当前的主播列表数据 @app.route("/anchorList", methods=['POST']) -def queryAnchorList(): +async def queryAnchorList(): # 项目根目录(当前文件在 infos 下,回退两层到根目录) root_dir = Path(__file__).resolve().parent.parent file_path = root_dir / "data" / "acList.json" @@ -624,12 +646,12 @@ def queryAnchorList(): # 修改当前的主播列表数据 @app.route("/updateAnchorList", methods=['POST']) -def updateAnchorList(): +async def updateAnchorList(): """ invitationType: 1 普票 2 金票 state: 1 通行(True) / 0 不通行(False) """ - data = request.get_json(force=True, silent=True) or {} + data = await request.get_json(force=True, silent=True) or {} invitationType = data.get("invitationType") state = bool(data.get("state")) # 转成布尔 @@ -679,16 +701,16 @@ def updateAnchorList(): # 删除主播 @app.route("/deleteAnchorWithIds", methods=['POST']) -def deleteAnchorWithIds(): - ls: list[dict] = request.get_json() # [{"anchorId": "xxx"}, ...] +async def deleteAnchorWithIds(): + ls: list[dict] = await request.get_json() # [{"anchorId": "xxx"}, ...] ids = [d.get("anchorId") for d in ls if d.get("anchorId")] deleted = AiUtils.delete_anchors_by_ids(ids) return ResultData(data={"deleted": deleted}).toJson() # 配置ai人设 @app.route("/aiConfig", methods=['POST']) -def aiConfig(): - data = request.get_json() +async def aiConfig(): + data = await request.get_json() agentName = data.get("agentName") guildName = data.get("guildName") contactTool = data.get("contactTool") @@ -725,14 +747,14 @@ def aiConfig(): # 查询主播聊天发送的最后一条信息 @app.route("/select_last_message", methods=['GET']) -def select_last_message(): +async def select_last_message(): data = JsonUtils.query_all_json_items() return ResultData(data=data).toJson() # 修改消息(已读改成未读) @app.route("/update_last_message", methods=['POST']) -def update_last_message(): - data = request.get_json() # 解析 JSON +async def update_last_message(): + data = await request.get_json() # 解析 JSON sender = data.get("sender") udid = data.get("device") text = data.get("text") @@ -749,8 +771,8 @@ def update_last_message(): # 删除已读消息 @app.route("/delete_last_message", methods=['POST']) -def delete_last_message(): - data = request.get_json() # 解析 JSON +async def delete_last_message(): + data = await request.get_json() # 解析 JSON sender = data.get("sender") udid = data.get("device") text = data.get("text") @@ -767,15 +789,15 @@ def delete_last_message(): # 停止所有任务 @app.route("/stopAllTask", methods=['POST']) -def stopAllTask(): - idList = request.get_json() +async def stopAllTask(): + idList = await request.get_json() code, msg, data = ThreadManager.batch_stop(idList) return ResultData(code, data, msg).toJson() # 切换账号 @app.route('/changeAccount', methods=['POST']) -def changeAccount(): - body = request.get_json() +async def changeAccount(): + body = await request.get_json() udid = body.get("udid") if not udid: return ResultData(data="", code=400, message="缺少 udid").toJson() @@ -792,12 +814,16 @@ def changeAccount(): # 查看设备网络状态 @app.route('/getDeviceNetStatus', methods=['POST']) -def getDeviceNetStatus(): - body = request.get_json() +async def getDeviceNetStatus(): + body = await request.get_json() udid = body.get("udid") - client = wda.USBClient(udid, wdaFunctionPort) - r = client.getNetWorkStatus() - value = r.get("value") + # 同步且超级慢的逻辑 → 丢到线程池,不阻塞事件循环 + def _work(): + client = wda.USBClient(udid, wdaFunctionPort) + r = client.getNetWorkStatus() + return r.get("value") + value = await anyio.to_thread.run_sync(_work) + return ResultData(data=value, code=200).toJson() @app.route('/test', methods=['POST']) @@ -866,8 +892,8 @@ def getAiConfig(): # 重新开启tiktok @app.route("/restartTikTok", methods=['POST']) -def restartTikTok(): - json = request.get_json() +async def restartTikTok(): + json = await request.get_json() udid = json.get("udid") client = wda.USBClient(udid, wdaFunctionPort) session = client.session() diff --git a/Module/FlaskSubprocessManager.py b/Module/FlaskSubprocessManager.py index 2156804..09fd0aa 100644 --- a/Module/FlaskSubprocessManager.py +++ b/Module/FlaskSubprocessManager.py @@ -59,7 +59,7 @@ class FlaskSubprocessManager: self._log("info", "FlaskSubprocessManager 初始化完成") # ========= 日志工具 ========= - def _log(self, level: str, msg: str, udid="system"): + def _log(self, level: str, msg: str, udid="flask"): """同时写 LogManager + 控制台""" try: if level == "info": @@ -146,6 +146,12 @@ class FlaskSubprocessManager: threading.Thread(target=self._flush_stdout, daemon=True).start() self._log("info", f"[FlaskMgr] Flask 子进程已启动,PID={self.process.pid}") + # 启动看门狗线程 + self._watchdog_thread = threading.Thread(target=self.watchdog_loop, daemon=True) + self._watchdog_thread.start() + + LogManager.info("[FlaskWD] 看门狗线程已启动", udid="flask") + if not self._wait_port_open(timeout=10): self._log("error", "[FlaskMgr] 启动失败,端口未监听") self.stop() @@ -292,4 +298,18 @@ class FlaskSubprocessManager: @classmethod def get_instance(cls) -> 'FlaskSubprocessManager': - return cls() \ No newline at end of file + return cls() + + def watchdog_loop(self): + while True: + if self.process is not None: + code = self.process.poll() + if code is not None: + LogManager.error( + text=f"[FlaskWD] Flask 子进程退出,exit code={code}", + udid="flask", + ) + # 可以顺便触发一下 _stop_event,看你愿不愿意 + # self._stop_event.set() + break + time.sleep(1) \ No newline at end of file diff --git a/Module/Main.py b/Module/Main.py index e214067..8472715 100644 --- a/Module/Main.py +++ b/Module/Main.py @@ -5,6 +5,7 @@ import sys from pathlib import Path from asgiref.wsgi import WsgiToAsgi +from sympy import false from Utils.AiUtils import AiUtils from Utils.LogManager import LogManager @@ -40,9 +41,6 @@ def _run_flask_role(): AiUtils.flask_port_free(flaskPort) bootstrap_server_side_effects() - # 把 WSGI Flask app 包成 ASGI app - asgi_app = WsgiToAsgi(app) - # ==== 关键:统一获取 resources 目录 ==== if "__compiled__" in globals(): # 被 Nuitka 编译后的 exe 运行时 @@ -54,20 +52,16 @@ def _run_flask_role(): resource_dir = os.path.join(base_dir, "resources") - + # Hypercorn 配置 config = Config() config.bind = [f"0.0.0.0:{flaskPort}"] - config.alpn_protocols = ["h2"] # 开 HTTP/2 - config.certfile = os.path.join(resource_dir, "cert.pem") - config.keyfile = os.path.join(resource_dir, "key.pem") + config.certfile = os.path.join(resource_dir, "server.crt") + config.keyfile = os.path.join(resource_dir, "server.key") + config.alpn_protocols = ["h2"] # 👈 这一行 + config.workers = 6 # 你机器 4GB → 推荐 3~4 个 worker - print(f"Starting Hypercorn on port {flaskPort} (HTTP/2 enabled)") - - # 开启 HTTP/2 - config.alpn_protocols = ["h2"] - - print(f"Starting Hypercorn on https://localhost:{flaskPort} (HTTP/2 enabled)") - asyncio.run(serve(asgi_app, config)) + # 直接跑 Quart(ASGI 原生,不再用 WsgiToAsgi) + asyncio.run(serve(app, config)) if "--role=flask" in sys.argv: _run_flask_role() @@ -84,7 +78,7 @@ if __name__ == "__main__": # 清空日志 LogManager.clearLogs() - main(sys.argv) + # main(sys.argv) # 添加iOS开发包到电脑上 deployer = DevDiskImageDeployer(verbose=True) diff --git a/Utils/LogManager.py b/Utils/LogManager.py index 9a81fe5..c1432e0 100644 --- a/Utils/LogManager.py +++ b/Utils/LogManager.py @@ -26,7 +26,7 @@ def _force_utf8_everywhere(): except Exception: pass -_force_utf8_everywhere() +# _force_utf8_everywhere() class LogManager: """ diff --git a/build.bat b/build.bat index 01fb3f0..58cfb00 100644 --- a/build.bat +++ b/build.bat @@ -9,7 +9,7 @@ python -m nuitka Module\Main.py ^ --windows-console-mode=disable ^ --output-filename=IOSAI ^ --include-package=Module,Utils,Entity,script ^ - --include-module=flask,wda,psutil,portalocker,flask_cors,cv2,lxml.etree,requests,urllib3,certifi,idna,setuptools,asgiref,hypercorn,h2,hpack,wsproto,priority,anyio,sniffio ^ + --include-module=quart,quart_cors,wda,psutil,portalocker,cv2,lxml.etree,requests,urllib3,certifi,idna,setuptools,asgiref,hypercorn,h2,hpack,wsproto,priority,anyio,sniffio ^ --include-data-dir=resources=resources ^ --include-data-dir=SupportFiles=SupportFiles ^ --include-data-files="resources/iproxy/*=resources/iproxy/" ^ diff --git a/resources/cert.pem b/resources/cert.pem deleted file mode 100644 index baa7f31..0000000 --- a/resources/cert.pem +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDizCCAnOgAwIBAgIUXpRsBS0IBEvAw22Ii/wtu/gdooUwDQYJKoZIhvcNAQEL -BQAwXTELMAkGA1UEBhMCQ04xDjAMBgNVBAgMBUxvY2FsMQ4wDAYDVQQHDAVMb2Nh -bDEMMAoGA1UECgwDRGV2MQwwCgYDVQQLDANEZXYxEjAQBgNVBAMMCWxvY2FsaG9z -dDAeFw0yNTExMTcwODI2MzdaFw0yNjExMTcwODI2MzdaMF0xCzAJBgNVBAYTAkNO -MQ4wDAYDVQQIDAVMb2NhbDEOMAwGA1UEBwwFTG9jYWwxDDAKBgNVBAoMA0RldjEM -MAoGA1UECwwDRGV2MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQCixGQJ0gdzcQoqdOv4lLvfH5Kz4C/t4/WCZfheF3Z7 -cYiog0Ql8URyn6bF8ux97X4TtpJ621jM/lfxc2hKrqXpbsyO2EKgT3OEpuv/lyqC -YQqbHUUIAiXI9OF/iAANY5rBIeEDEUhcH4Ngt6EJ1FZdU+tfgV8V9zNUSeSJ+VtF -C+0LsTyWy7eqnXkXnPZvitVeZU85Zy5lWdC1mp9cOoyElmYuGxIQkW6ZtEzMjVp4 -Eim3RsZgk6ZYRAdMGfdaa6YrmDDqhEZVEEL55dstOqfIWKUppazC9HSs7FnGsaUn -xkdqOArACdhU9y3f+yyeLC93Xllx9kgFfvLueysUqSgdAgMBAAGjQzBBMCAGA1Ud -EQQZMBeCCWxvY2FsaG9zdIcEfwAAAYcEwKgB2jAdBgNVHQ4EFgQURY1BDcpSTUNO -D0olM9H84Gu/QQ0wDQYJKoZIhvcNAQELBQADggEBAFrCAqIlpzncH6owBImN8Ub5 -8ZwtTm+C3nQZF5FkCdsXHfqtPTEk4bX7IFHaj7saqroCYXfgopzvk2QX16wlPwk2 -SKA/pF6I2bNNozlcVN9QAf9ue6xa8g8AxwPT46gbKTKFyG5lg1umYXhCGKVIJ/1l -B4Bh8KmPfzNWxiKOzflGNx5j1BHPZ9S7jt9wtiEwENceGZXVE8ANMiNR44+suuM7 -6/syQUetPN+VWW+/14OrDeYQDLZTbUVigY75KIuLF41PxNWG745Qlcu/5nmvBnHv -5NNm2Zs8GYKLqLIlUQNU8x0R03FBLCYjDKRJsNpsZPqjI5cDSPj5vHZrzD3Jh0s= ------END CERTIFICATE----- diff --git a/resources/key.pem b/resources/key.pem deleted file mode 100644 index f019759..0000000 --- a/resources/key.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCixGQJ0gdzcQoq -dOv4lLvfH5Kz4C/t4/WCZfheF3Z7cYiog0Ql8URyn6bF8ux97X4TtpJ621jM/lfx -c2hKrqXpbsyO2EKgT3OEpuv/lyqCYQqbHUUIAiXI9OF/iAANY5rBIeEDEUhcH4Ng -t6EJ1FZdU+tfgV8V9zNUSeSJ+VtFC+0LsTyWy7eqnXkXnPZvitVeZU85Zy5lWdC1 -mp9cOoyElmYuGxIQkW6ZtEzMjVp4Eim3RsZgk6ZYRAdMGfdaa6YrmDDqhEZVEEL5 -5dstOqfIWKUppazC9HSs7FnGsaUnxkdqOArACdhU9y3f+yyeLC93Xllx9kgFfvLu -eysUqSgdAgMBAAECggEAGY29qvEHbG9Vyj6bAWbQbAI39PeAbte4JqW9rX//gPfd -HZ+mJlLPjTNVaoRt7oNHpO6n5pPjSCOySNz2hasPrytPACoho6t1lmDicjkYWmnD -0YBx4wT7S6ZudKg0YeW+WQ3plqKy+ouUA64woStt968CJ/dWp0stCtGjCKpWUuuB -TXvAUM91qrQlpIuqQI0QYRcKaoKPV6IckWPGeLvKi8EhVOFCNdya8jTP/ayxT06r -/cNucO+Tqe0PUe6jet6Ecx7Av4h8QXg9FMoF40RKxD6Q+sK/bM1c51KvUZVt9v4F -epAHjQyrzPjUozjtKzQvibexBvSwz/XaFCDgr7OwPQKBgQDOJtILcxjJDZfk8LUG -GNF8XVtgDu2FFVw79MSuQgERC+w2b+P2feffwdI4vu2+8jkWCHnttXNgdrS3r41C -gak3Xb2Jzx8M06eNC9QCtjicrWNTmJtcp5YZm1vS+fAPQG4DPLK+J4EmLNNyQ9nC -0vMfYRwKr3TX5FU6MyJbAsVnkwKBgQDKH/zUhMPdN6+0upEVoUJrI3BOhVdN8eEp -eqNWYU2Hhmg5mHsnoxz8Rjxw5ZKx108BT1JNea/rrNgOhe8TTpiAIVl5ZMN0OcO2 -INlfteCtXY5nzU8HilfFBPwroR8Msx662GpM8TRA9RfTGJ7nKmiXhC1jnmkPecwX -+f+LaLCfjwKBgQC11H3dxXYuF8RLFZjFuOxFIl7vOht8D9wbsggsn2ErdPWzCjvq -9SCpNt7CWH2At0tsyKsq5KnQgsNhZQFWkOD9SbxdKgf8G0+k07L7dVg3saNzX55h -OhvlmCeEzhlUioK+bjJGELgUQON73Kbc9Y2lttSyBBIuPmKCBAogdjBB6wKBgGnM -VIro85zXiSEQhuDLh/iMlDyFjy09bp5HkzejtvE5aVS8e7pDpuhl2z087YwpJzGI -U4w6Jds2neD8Oifg+/IVgsAH/kbX9ZlfmGiAyxnz3pZ24OcRgt+dvGEZ9Sawm2Ux -4nJjzvYxVEcqnAJkMFse1KNQR63SEwJ52Ukfg1QBAoGBAKByisJiMTi/gmSlPFf6 -3ZfxCd5ReMS/Ak4JIBN4S+GoAZp6yMZy1jYFHqV2k3slhmcswy+V9DGxtldHlDu9 -+90zV1btfaB3nq5ydkmj32SU9MRqpzP4axHYTi8cvmOBlOEpL5e7KWTg072rGHAC -+ih8VPn9LTKk2GCtCCp4r2jI ------END PRIVATE KEY----- diff --git a/resources/server.crt b/resources/server.crt new file mode 100644 index 0000000..f2f2494 --- /dev/null +++ b/resources/server.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDaTCCAlGgAwIBAgIUAQMZUx/qRQIv49P6EIWt+mjYlKYwDQYJKoZIhvcNAQEL +BQAwXTELMAkGA1UEBhMCQ04xDjAMBgNVBAgMBUxvY2FsMQ4wDAYDVQQHDAVMb2Nh +bDEMMAoGA1UECgwDRGV2MQwwCgYDVQQLDANEZXYxEjAQBgNVBAMMCWxvY2FsaG9z +dDAeFw0yNTExMTgwNjMyMjlaFw0zNTExMTYwNjMyMjlaMF0xCzAJBgNVBAYTAkNO +MQ4wDAYDVQQIDAVMb2NhbDEOMAwGA1UEBwwFTG9jYWwxDDAKBgNVBAoMA0RldjEM +MAoGA1UECwwDRGV2MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDxY0znIdwlVW+EVcQww7Xg/16iN3JpX0svpEOIbo1u +40S3bRn057cS//1AG+c+55iisfOaoUX59ZUQhihcAje7IfTKO1/dCzDy4d/PT2hl +UOO9Zo8GQzflFM0U6fIi2Ifly09JTGJEyxr+SrJHcJPENualiR6zwNLlqupE9bDP +40ydznYWZRvw3N0QmrkOg+eY6FwaYtWspvf/KiJWucscc31zGyA0MhF552k6sIVg +9Vskr9Bd3g52Umv/1yPZmESkuM905ImCwSCK0VPAY+rooUeTYw3ktE7q/iy5+l71 +s6hN9YHVo3m4pIJz4G0YT039TnjtZxxHt8IIVSv6Ymr3AgMBAAGjITAfMB0GA1Ud +DgQWBBQ6Q3V0wyXXyNm3jvmSKc2KoAMvAzANBgkqhkiG9w0BAQsFAAOCAQEAacsO +ja4qpX/vWUTelhdvzg5alD5WDrP8iSIXmGF+HSHgJbbjxbDm4vlMZjzwh8iqODQR +yJ9iuRiFFXGCktEqFx2NTCIUBmyoBg/LFeLtOn0Ncqs11ypoSoRxqE0IaeDjirBH +hNUIXzJ+3pOqgyHU+3WqgEzEjW63pNmjX1esVZqA0SQJejsv4hJOvBzGoFFgSRcC +Zp7NrusZ8IDkdLbUgD9pgZHPI8YNH/MVocV3wd45o9Y3nkMPhIqkp/1GOWIdN6qj +co66o0hYsJduQC9fEBceWpRNWUirEKd231SeaW9vZMPMrfmOZanDY6pXdvhsZR3L +9ZGsJk6ktoTagz2AYw== +-----END CERTIFICATE----- diff --git a/resources/server.key b/resources/server.key new file mode 100644 index 0000000..e8fe6b8 --- /dev/null +++ b/resources/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAQDxY0znIdwlVW+E +VcQww7Xg/16iN3JpX0svpEOIbo1u40S3bRn057cS//1AG+c+55iisfOaoUX59ZUQ +hihcAje7IfTKO1/dCzDy4d/PT2hlUOO9Zo8GQzflFM0U6fIi2Ifly09JTGJEyxr+ +SrJHcJPENualiR6zwNLlqupE9bDP40ydznYWZRvw3N0QmrkOg+eY6FwaYtWspvf/ +KiJWucscc31zGyA0MhF552k6sIVg9Vskr9Bd3g52Umv/1yPZmESkuM905ImCwSCK +0VPAY+rooUeTYw3ktE7q/iy5+l71s6hN9YHVo3m4pIJz4G0YT039TnjtZxxHt8II +VSv6Ymr3AgMBAAECgf9Wf6myg+iV5TRN77TAGbAP6udHacgYn+7Ad5eQC+ZlobuU +Y3Tnh325tXqvPRFSGFwiAlMQVDECt1u/PDm6vJ077t/UHQ5zjr3sYPU1oONuptJ7 +Jo0WsoFKLkH/oMeBi7h643+Oo9/GH04/nTdnMS9kqL1lYy/aUOVGW5JXIZUWhwMc +gTEXuyuaajqdRbQex6vSQANpauYMewj9jlU9RVfjB6LGUHLDJwWbi61dTOYakxkn +ssfzEDPMFuGQ8qjG5Li6ceUgNHlmY73WZBXNHKt6FcwNqldy5FB4PiIxoWx0ZHmq +z/i89BQlurp20RyFD8f+iMTIbU/z0gHM86JkziECgYEA+qO5KVSg0XQlQmsyXT7Z +nKI+DakGxn4ipJWuUDLdi0QoymNIF3diUi1o9P4Q8QzfNFCTVdUsQft24ekXAkJX +QtGL61BXBJX5vZvihbBuCEGatE+31LRQZOxWLaeWE6y8XbFfez22SRpa+IrTma+h +BxBRyKSqO03xyojKTPPMbDkCgYEA9ozsY02MUJKDXxtE2BRgwGQumoHi7HPRUISk +ij0MWw/AYdYoCsrALP4IKB65tK0M7lJsK+g5M2Kyh8XD/Z4hfT1oNnJW8SOtPBwd +heuPUzjnhIhnnxoLFeKMo6bGNqVkIYAOKbcX9s2J7U9NwUlYxMxmjNrV2/Nb2MFE +Raun8K8CgYBbX1ydaLDIKyN6N0JBJCyJIcylhj1mF43hmn/V1PVXVB3ayp75jxhV +BSECT601c4/brpRH8lMUKuyIJ0WwGSdewK3Vt5BBp7tIGJBYVJ2IfQI9QeKutJ2q +bU5tjm7z9UEmlwdMEo9lzyni+hlyKcj2nkhycTVuMVg4ke3OaALaYQKBgDD3XBt8 +01lNP/ormEiyA2UygG7/TOpZNkEflu49oa6UOkk0F0/NZM2KxmPxdkCD/gV3KTSv +Mm0aNQryJDLCrTQKdiAaJVpPE6DUlKh8WELXEmQoEyxuJ7V5ASWfgc5omrJslGOE +kaXavIH9NhwlTRQI5HUlIURF2P/7omuT5A7RAoGBAJhtThrzxExrzmf4bTIXe+EQ +M5lAPqIn46ThlujcNCLroxWz32Ekzs1ywn2NKwK6F1gMJEsFXqQDXtumJYTJ94tY +L1fv0knHgRnURsq6xZ4IQgq3YzV0OXQwN4PBzqcRR6sMgFAXfCzXMy/eE7iz8eZT +FsrkWh/9tgVvITaUrqr5 +-----END PRIVATE KEY-----