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}