• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# Copyright (C) 2023 Huawei Device Co., Ltd.
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import http
17import json
18from datetime import datetime
19from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
20import ssl
21import os
22from urllib.parse import urlparse
23import urllib.request
24import subprocess
25import re
26import platform
27import webbrowser
28
29PORT = 9000
30CERT_FILE = './cert/certFile.pem'
31KEY_FILE = './cert/keyFile.key'
32version = 'v1.0.0'
33serveInfo = ''
34
35
36def is_windows():
37    return platform.system() == 'Windows'
38
39
40def is_darwin():
41    return platform.system() == 'Darwin'
42
43
44def is_linux():
45    return platform.system() == 'Linux'
46
47
48def openWeb(url):
49    webbrowser.open(url)
50
51
52def get_pid_by_port(port_number):
53    res_pid = -1
54    cmd_res = subprocess.run(f"netstat -ano -p tcp | findstr {port_number}", capture_output=True, text=True,
55                             shell=True)
56    cmd_res_str = cmd_res.stdout
57    find_str = re.findall(r'\s(\d+)\s', cmd_res_str)
58    if len(find_str) > 0:
59        try:
60            res_pid = int(find_str[0])
61        except ValueError:
62            res_pid = -1
63    return res_pid
64
65
66def check_port(port):
67    if is_windows():
68        pid = get_pid_by_port(port)
69        if pid != -1:
70            subprocess.run(f"taskkill /F /PID {pid} /T", shell=True)
71
72
73class SpRequestHandler(http.server.BaseHTTPRequestHandler):
74    global version
75    global serveInfo
76
77    def log_message(self, format, *args):
78        return
79
80    def do_GET(self):
81        parse_result = urlparse(self.path)
82        if parse_result.path == '/application/serverInfo':
83            self.serverInfo_handler()
84        elif parse_result.path.startswith('/application'):
85            self.application_handler(parse_result)
86        else:
87            self.send_error(404, 'Not found')
88
89    def do_POST(self):
90        parse_result = urlparse(self.path)
91        if parse_result.path.startswith('/logger'):
92            self.console_handler()
93        elif parse_result.path.startswith('/upload'):
94            print(f'upload')
95
96        elif parse_result.path.startswith('/download-file'):
97            print(f'download-file')
98            self.download_handler()
99
100    def download_handler(self):
101        self.clear_overdue_file()
102        content_type = self.headers.get("Content-Type")
103        if content_type and content_type.startswith("application/x-www-form-urlencoded"):
104            url = self.post_form_value("url")
105            try:
106                req = urllib.request.Request(url)
107                response = urllib.request.urlopen(req)
108                content = response.read().decode("utf-8")
109            except Exception as e:
110                self.send_response(200)
111                response = {"success": False, "code": -1, "message": str(e), "data": None}
112                self.wfile.write(bytes(json.dumps(response), "utf-8"))
113                return
114            suffixStr = os.path.splitext(url.split("/")[-1])[1]
115            file_name = f"upload/{datetime.now().strftime('%Y%m%d%H%M%S%f')}{suffixStr}"
116            os.makedirs(os.path.dirname(file_name), exist_ok=True)
117            try:
118                with open(file_name, "wb") as f:
119                    f.write(content)
120                    written = f.tell()
121            except Exception as e:
122                self.send_response(200)
123                response = {"success": False, "code": -1, "message": str(e), "data": None}
124                self.wfile.write(bytes(json.dumps(response), "utf-8"))
125                return
126            self.send_response(200)
127            response = {"success": True, "code": 0, "message": "success", "data": {"url": file_name, "size": written}}
128            self.wfile.write(bytes(json.dumps(response), "utf-8"))
129            return
130
131    def post_form_value(self, key):
132        content_length = int(self.headers.get("Content-Length", 0))
133        post_data = self.rfile.read(content_length).decode("utf-8")
134        for param in post_data.split("&"):
135            param_key, param_value = param.split("=")
136            if param_key == key:
137                return param_value
138        return ""
139
140    def clear_overdue_file(self):
141        path = "./upload/"
142        upload_dir = os.path.dirname(os.path.normpath(path))
143        if not os.path.exists(upload_dir):
144            os.makedirs(upload_dir)
145        now = datetime.now()
146        for root, dirs, files in os.walk(path):
147            for file_name in files:
148                file_path = os.path.join(root, file_name)
149                if self.check_due(file_name):
150                    print(f"{now} delete -> {file_path}")
151                    os.remove(file_path)
152
153    def check_due(self, file_name):
154        now = datetime.now()
155        datetime_str = os.path.splitext(os.path.basename(file_name))[0]
156        fileDate = datetime.strptime(datetime_str, "%Y%m%d%H%M%S%f")
157        return (now - fileDate).total_seconds() > 3600
158
159    def console_handler(self):
160        self.check_dir('./logger')
161        nowDate = datetime.now()
162        now = nowDate.strftime("%Y-%m-%d")
163        fileName = f"{now}.txt"
164        dst = open("./logger/" + fileName, "a")
165        content_type = self.headers.get("Content-Type")
166        if content_type and content_type.startswith("application/json"):
167            content_length = int(self.headers.get("Content-Length", 0))
168            req_data = self.rfile.read(content_length)
169            req = json.loads(req_data)
170            now = datetime.now()
171            formatted_date = now.strftime("%Y-%m-%d %H:%M:%S")
172            dst.write(f"{formatted_date} {req['fileName']} ({req['fileSize']} M)\n")
173            self.send_response(200)
174            self.send_header("Content-type", "text/html")
175            self.end_headers()
176            self.wfile.write(bytes(f"日志写入成功", "utf-8"))
177
178    def check_dir(self, dir_path):
179        if not os.path.exists(dir_path):
180            os.makedirs(dir_path)
181
182    def application_handler(self, parse_result):
183        file_path = parse_result.path[12:]
184        file_extension = os.path.splitext(file_path)[1]
185        if file_path == '/' or file_path == '':
186            file_path = './index.html'
187            file_extension = '.html'
188        else:
189            file_path = '.' + file_path
190        try:
191            with open(file_path, 'rb') as file:
192                content = file.read()
193            self.send_response(200)
194            self.send_header('Content-type', get_content_type(file_extension))
195            self.send_header("Cross-Origin-Opener-Policy", "same-origin")
196            self.send_header("Cross-Origin-Embedder-Policy", "require-corp")
197            self.send_header("Access-Control-Allow-Origin", "*")
198            self.send_header("Access-Control-Allow-Credentials", "true")
199            self.send_header("Access-Control-Allow-Headers", "x-requested-with, authorization, blade-auth")
200            self.send_header("Access-Control-Allow-Methods", "*")
201            self.send_header("Access-Control-Max-Age", "3600")
202            self.send_header("data-version", version)
203            self.end_headers()
204            self.wfile.write(content)
205        except FileNotFoundError:
206            self.send_error(404, 'File not found')
207
208    def serverInfo_handler(self):
209        self.send_response(200)
210        self.send_header("Access-Control-Allow-Origin", "*")
211        self.send_header("request_info", serveInfo)
212        self.end_headers()
213
214
215def read_text(read_file_path):
216    try:
217        with open(read_file_path, 'r') as file:
218            content = file.read()
219        return content
220    except IOError:
221        return None
222
223
224def get_content_type(file_extension):
225    if file_extension == '.js':
226        return 'application/javascript'
227    if file_extension == '.wasm':
228        return 'application/wasm'
229    if file_extension == '.json':
230        return 'application/json'
231    if file_extension == '.html':
232        return 'text/html'
233    if file_extension == '.svg':
234        return 'image/svg+xml'
235    return 'text/plain'
236
237def gen_ssl(cert_file, key_file):
238    serial_number = 123456789
239    organization = "www.smartperf.com"
240    organizational_unit = "ITs"
241    common_name = "www.smartperf.com"
242    validity_days = 3650
243    subprocess.run(["openssl", "genpkey", "-algorithm", "RSA", "-out", key_file])
244    csr_file = "cert/cert.csr"
245    subprocess.run(["openssl", "req", "-new", "-key", key_file, "-out", csr_file, "-subj",
246                    "/O={}/OU={}/CN={}".format(organization, organizational_unit, common_name)])
247    subprocess.run(["openssl", "x509", "-req", "-days", str(validity_days), "-in", csr_file, "-signkey",
248                    key_file, "-out", cert_file, "-set_serial", str(serial_number)])
249
250class SpServer:
251    def __init__(self, server_address, cert_file_path, keyfile_path):
252        global version
253        global serveInfo
254        version = read_text('version.txt')
255        serveInfo = read_text('server-config.txt')
256        self.server_address = server_address
257        self.context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
258        self.context.load_cert_chain(cert_file_path, keyfile_path)
259        self.httpd = ThreadingHTTPServer(server_address, SpRequestHandler)
260        self.httpd.socket = self.context.wrap_socket(self.httpd.socket, True)
261
262    def start(self):
263        print(f'HTTPS[{PORT}] SmartPerf Server Start')
264        if is_windows():
265            openWeb("https://127.0.0.1:9000/application/")
266        self.httpd.serve_forever()
267
268
269def main():
270    check_port(PORT)
271    if not os.path.exists(CERT_FILE) or not os.path.exists(KEY_FILE):
272        if is_linux():
273            if not os.path.exists('./cert'):
274                os.makedirs('./cert')
275            gen_ssl(CERT_FILE, KEY_FILE)
276    server_address = ('', PORT)
277    server = SpServer(server_address, CERT_FILE, KEY_FILE)
278    server.start()
279
280
281if __name__ == '__main__':
282    main()
283