• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2022 Huawei Device Co., Ltd.
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6//     http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14package main
15
16//遇到报错请在当前目录下执行这个命令: go mod download golang.org/x/text
17import (
18    "bufio"
19    "bytes"
20    "crypto/rand"
21    "crypto/rsa"
22    "crypto/x509"
23    "crypto/x509/pkix"
24    "encoding/json"
25    "encoding/pem"
26    "fmt"
27    "io"
28    "io/ioutil"
29    "log"
30    "math/big"
31    "mime"
32    "net"
33    "net/http"
34    "os"
35    "os/exec"
36    "path"
37    "path/filepath"
38    "regexp"
39    "runtime"
40    "strconv"
41    "strings"
42    "time"
43)
44
45const HttpPort = 9000
46
47var exPath string
48
49// CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go
50// CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go
51func cors(fs http.Handler, version string) http.HandlerFunc {
52    return func(w http.ResponseWriter, r *http.Request) {
53		// return if you do not want the FileServer handle a specific request
54        r.Header.Add("Cross-Origin-Opener-Policy", "same-origin")
55        r.Header.Add("Cross-Origin-Embedder-Policy", "require-corp")
56        w.Header().Add("Cross-Origin-Opener-Policy", "same-origin")
57        w.Header().Add("Cross-Origin-Embedder-Policy", "require-corp")
58        w.Header().Set("Access-Control-Allow-Origin", "*")
59        w.Header().Set("Access-Control-Allow-Credentials", "true")
60        w.Header().Set("Access-Control-Allow-Headers", "x-requested-with, authorization, blade-auth") //*
61        w.Header().Set("Access-Control-Allow-Methods", "*")                                           //*
62        w.Header().Set("Access-Control-Max-Age", "3600")
63        w.Header().Set("data-version", version)
64        fs.ServeHTTP(w, r)
65    }
66}
67
68func exist(path string) bool {
69    _, err := os.Stat(path)
70    if err != nil {
71        if os.IsExist(err) {
72            return true
73        }
74        return false
75    }
76    return true
77}
78func genSSL() {
79    if exist("cert/keyFile.key") || exist("cert/certFile.pem") {
80        fmt.Println("keyFile.key exists")
81        return
82    }
83    max := new(big.Int).Lsh(big.NewInt(1), 128)
84    serialNumber, _ := rand.Int(rand.Reader, max)
85    subject := pkix.Name{
86        Organization:       []string{"www.smartperf.com"},
87        OrganizationalUnit: []string{"ITs"},
88        CommonName:         "www.smartperf.com",
89	}
90    certificate509 := x509.Certificate{
91        SerialNumber: serialNumber,
92        Subject:      subject,
93        NotBefore:    time.Now(),
94        NotAfter:     time.Now().AddDate(10, 0, 0),
95        KeyUsage:     x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
96        ExtKeyUsage:  []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
97        IPAddresses:  []net.IP{net.ParseIP("127.0.0.1")},
98    }
99    chekDir("cert")
100    pk, _ := rsa.GenerateKey(rand.Reader, 1024)
101    derBytes, _ := x509.CreateCertificate(rand.Reader, &certificate509, &certificate509, &pk.PublicKey, pk)
102    certOut, _ := os.Create("cert/certFile.pem")
103    pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
104    certOut.Close()
105    keyOut, _ := os.Create("cert/keyFile.key")
106    pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(pk)})
107    keyOut.Close()
108}
109func main() {
110    checkPort(HttpPort)
111    genSSL()
112    exPath = getCurrentAbPath()
113    fmt.Println(exPath)
114    go func() {
115        version := ""
116        readVersion, versionErr := ioutil.ReadFile(exPath + "/version.txt")
117        if versionErr != nil {
118            version = ""
119        } else {
120            version = string(readVersion)
121        }
122        mux := http.NewServeMux()
123        mime.TypeByExtension(".js")
124        mime.AddExtensionType(".js", "application/javascript")
125        log.Println(mime.TypeByExtension(".js"))
126        mux.HandleFunc("/upload", uploadHandler)
127        mux.HandleFunc("/logger", consoleHandler)
128        mux.Handle("/upload/", http.StripPrefix("/upload/", http.FileServer(http.Dir(exPath+"/upload"))))
129        fs := http.FileServer(http.Dir(exPath + "/"))
130        mux.Handle("/application/", http.StripPrefix("/application/", cors(fs, version)))
131        ser := &http.Server{
132            Addr:    fmt.Sprintf(":%d", HttpPort),
133            Handler: mux,
134        }
135        log.Println(fmt.Sprintf("HTTP[%d]服务启动", HttpPort))
136        open(fmt.Sprintf("https://localhost:%d/application", HttpPort))
137        err := ser.ListenAndServeTLS("cert/certFile.pem", "cert/keyFile.key")
138        CheckErr(err)
139    }()
140    select {}
141}
142
143func getPidByPort(portNumber int) int {
144    resPid := -1
145    var out bytes.Buffer
146    cmdRes := exec.Command("cmd", "/c", fmt.Sprintf("netstat -ano -p tcp | findstr %d", portNumber))
147    cmdRes.Stdout = &out
148    cmdRes.Run()
149    cmdResStr := out.String()
150    findStr := regexp.MustCompile(`\s\d+\s`).FindAllString(cmdResStr, -1)
151    if len(findStr) > 0 {
152        pid, err := strconv.Atoi(strings.TrimSpace(findStr[0]))
153        if err != nil {
154            resPid = -1
155        } else {
156            resPid = pid
157        }
158    }
159    return resPid
160}
161
162type LoggerReq struct {
163	FileName string `json:"fileName"`
164	FileSize string `json:"fileSize"`
165}
166
167func consoleHandler(w http.ResponseWriter, r *http.Request) {
168	chekDir(exPath + "/logger")
169	var now = time.Now()
170	var fileName = fmt.Sprintf("%d-%d-%d", now.Year(), now.Month(), now.Day())
171	dst, err := os.OpenFile(exPath+"/logger/"+fileName, os.O_WRONLY|os.O_CREATE|os.O_APPEND|os.O_SYNC, 0666)
172	CheckErr(err)
173	contentType := r.Header["Content-Type"]
174	if len(contentType) > 0 {
175		contentTypeName := contentType[0]
176		if strings.HasPrefix(contentTypeName, "application/json") {
177			decoder := json.NewDecoder(r.Body)
178			var req LoggerReq
179			decoder.Decode(&req)
180			dst.WriteString(fmt.Sprintf("%s %s (%s M)\n", now.Format("2006-01-02 15:04:05"), req.FileName, req.FileSize))
181			fmt.Fprintf(w, fmt.Sprintf("日志写入成功%s", exPath))
182		}
183	}
184}
185func uploadHandler(w http.ResponseWriter, r *http.Request) {
186    defer func() {
187        var err = recover()
188        fmt.Println(err)
189    }()
190    chekDir(exPath + "/upload")
191    contentType := r.Header["Content-Type"]
192    if len(contentType) > 0 {
193        contentTypeName := contentType[0]
194        if strings.HasPrefix(contentTypeName, "multipart/form-data") {
195            err := r.ParseMultipartForm(32 << 20)
196            CheckErr(err)
197            file, header, err := r.FormFile("file")
198            CheckErr(err)
199            filename := header.Filename
200            index := strings.LastIndex(filename, ".")
201            distFileName := fmt.Sprintf("%d", time.Now().Unix())
202            distFileSuffix := filename[index:]
203            path := fmt.Sprintf("/upload/%s%s", distFileName, distFileSuffix)
204            dst, err := os.OpenFile(exPath+path, os.O_WRONLY|os.O_CREATE, 0666)
205            CheckErr(err)
206            defer dst.Close()
207            if _, err := io.Copy(dst, file); err != nil {
208                http.Error(w, err.Error(), http.StatusInternalServerError)
209                return
210            }
211            databaseUrl := transformDatabase(distFileName, distFileSuffix)
212            if databaseUrl != "" {
213                ohosTsPath := fmt.Sprintf("./upload/%s.ohos.ts", databaseUrl)
214                result, _ := PathExists(ohosTsPath)
215                if result {
216                    readFile, readErr := ioutil.ReadFile(ohosTsPath)
217                    if readErr == nil {
218                        fmt.Println(string(readFile))
219                        split := SplitLines(string(readFile))
220                        fmt.Println(split)
221                        if len(split) > 1 {
222                            if strings.HasSuffix(split[0], ":0") {
223                                fmt.Fprintf(w, fmt.Sprintf("/upload/%s", databaseUrl))
224                                return
225                            }
226                        }
227                    }
228                }
229            }
230            http.Error(w, "文件生成失败", http.StatusNotFound)
231            return
232        }
233    }
234}
235func SplitLines(s string) []string {
236    var lines []string
237    sc := bufio.NewScanner(strings.NewReader(s))
238    for sc.Scan() {
239        lines = append(lines, sc.Text())
240    }
241    return lines
242}
243
244func readFileFirstLine(path string) string {
245    file, err := os.Open(path)
246    if err != nil {
247        return ""
248    }
249    defer file.Close()
250
251    readFile := bufio.NewReader(file)
252    line, readErr := readFile.ReadString('\n')
253    if readErr != nil || io.EOF == err {
254        return ""
255    }
256    return line
257}
258
259func PathExists(path string) (bool, error) {
260    _, err := os.Stat(path)
261    if err == nil {
262        return true, nil
263    }
264    if os.IsNotExist(err) {
265        return false, nil
266    }
267    return false, err
268}
269
270func chekDir(path string) {
271    _, err := os.Stat(path)
272    if err != nil {
273        err := os.Mkdir(path, os.ModePerm)
274        if err != nil {
275            fmt.Printf("mkdir failed![%v]\n", err)
276        } else {
277            fmt.Printf("mkdir success!\n")
278        }
279    }
280}
281func CheckErr(err error) {
282    if err != nil {
283        log.Panicln(err)
284    }
285}
286
287func open(url string) error {
288    if isWindows() {
289        return openUrlWindows(url)
290    } else if isDarwin() {
291        return openUrlDarwin(url)
292    } else {
293        return openUrlOther(url)
294    }
295}
296
297func openUrlWindows(url string) error {
298    cmd := "cmd"
299    args := []string{"/c", "start", url}
300    return exec.Command(cmd, args...).Start()
301}
302func openUrlDarwin(url string) error {
303    var cmd = "open"
304    var args = []string{url}
305    return exec.Command(cmd, args...).Start()
306}
307func openUrlOther(url string) error {
308    var cmd = "xdg-open"
309    var args = []string{url}
310    return exec.Command(cmd, args...).Start()
311}
312
313func isWindows() bool {
314    return runtime.GOOS == "windows"
315}
316func isDarwin() bool {
317    return runtime.GOOS == "darwin"
318}
319
320func transformDatabase(name string, suffix string) string {
321    if isWindows() {
322        cmd := exec.Command(
323            "cmd",
324            "/c",
325            `.\bin\trace_streamer_windows.exe`,
326            fmt.Sprintf(`.\upload\%s%s`, name, suffix),
327            "-e",
328            fmt.Sprintf(`.\upload\%s.db`, name),
329        )
330        var stdout, stderr bytes.Buffer
331        cmd.Stdout = &stdout // 标准输出
332        cmd.Stderr = &stderr // 标准错误
333        err := cmd.Run()
334        if err != nil {
335            return ""
336        }
337        return fmt.Sprintf("%s.db", name)
338    } else if isDarwin() {
339        cmd := exec.Command(
340            "/bin/bash",
341            "-c",
342            fmt.Sprintf("%s/bin/trace_streamer_mac %s/upload/%s%s -e %s/upload/%s.db", exPath, exPath, name, suffix, exPath, name),
343        )
344        var stdout, stderr bytes.Buffer
345        cmd.Stdout = &stdout // 标准输出
346        cmd.Stderr = &stderr // 标准错误
347        err := cmd.Run()
348        outStr, errStr := string(stdout.Bytes()), string(stderr.Bytes())
349        fmt.Printf("out:\n%s\n :\n%s\n", outStr, errStr)
350        if err != nil {
351            return ""
352        }
353        return fmt.Sprintf("%s.db", name)
354    } else {
355        cmd := exec.Command(
356            "/bin/bash",
357            "-c",
358            fmt.Sprintf("%s/bin/trace_streamer_linux %s/upload/%s%s -e %s/upload/%s.db", exPath, exPath, name, suffix, exPath, name),
359        )
360        var stdout, stderr bytes.Buffer
361        cmd.Stdout = &stdout // 标准输出
362        cmd.Stderr = &stderr // 标准错误
363        err := cmd.Run()
364        outStr, errStr := string(stdout.Bytes()), string(stderr.Bytes())
365        fmt.Printf("out:\n%s\n :\n%s\n", outStr, errStr)
366        if err != nil {
367            return ""
368        }
369        return fmt.Sprintf("%s.db", name)
370    }
371    return ""
372}
373func getCurrentAbPath() string {
374    dir := getCurrentAbPathByExecutable()
375    tmpDir, _ := filepath.EvalSymlinks(os.TempDir())
376    if strings.Contains(dir, tmpDir) {
377        return getCurrentAbPathByCaller()
378    }
379    return dir
380}
381
382func getCurrentAbPathByCaller() string {
383    var abPath string
384    _, filename, _, ok := runtime.Caller(0)
385    if ok {
386        abPath = path.Dir(filename)
387    }
388    return abPath
389}
390func getCurrentAbPathByExecutable() string {
391    exePath, err := os.Executable()
392    if err != nil {
393        log.Fatal(err)
394    }
395    res, _ := filepath.EvalSymlinks(filepath.Dir(exePath))
396    return res
397}
398
399func checkPort(port int){
400    if isWindows() {
401        pid := getPidByPort(port)
402        if pid != -1 {
403            res := exec.Command("cmd", "/c", fmt.Sprintf("taskkill /F /PID %d /T",pid))
404            res.Run()
405        }
406    }
407}