func main() { flag.StringVar(&config.server, "s", "127.0.0.1", "server:port") flag.IntVar(&config.port, "p", 0, "server:port") flag.IntVar(&config.core, "core", 1, "number of CPU cores to use") flag.StringVar(&config.passwd, "k", "", "password") flag.StringVar(&config.method, "m", "", "encryption method, use empty string or rc4") flag.IntVar(&config.nconn, "nc", 1, "number of connection to server") flag.IntVar(&config.nreq, "nr", 1, "number of request for each connection") // flag.IntVar(&config.nsec, "ns", 0, "run how many seconds for each connection") flag.BoolVar((*bool)(&debug), "d", false, "print http response body for debugging") flag.Parse() if config.server == "" || config.port == 0 || config.passwd == "" || len(flag.Args()) != 1 { fmt.Printf("Usage: %s -s <server> -p <port> -k <password> <url>\n", os.Args[0]) os.Exit(1) } runtime.GOMAXPROCS(config.core) uri := flag.Arg(0) if strings.HasPrefix(uri, "https://") { fmt.Println("https not supported") os.Exit(1) } if !strings.HasPrefix(uri, "http://") { uri = "http://" + uri } cipher, err := ss.NewCipher(config.method, config.passwd) if err != nil { fmt.Println("Error creating cipher:", err) os.Exit(1) } serverAddr := net.JoinHostPort(config.server, strconv.Itoa(config.port)) parsedURL, err := url.Parse(uri) if err != nil { fmt.Println("Error parsing url:", err) os.Exit(1) } host, _, err := net.SplitHostPort(parsedURL.Host) if err != nil { host = net.JoinHostPort(parsedURL.Host, "80") } else { host = parsedURL.Host } // fmt.Println(host) rawAddr, err := ss.RawAddr(host) if err != nil { panic("Error getting raw address.") } done := make(chan []time.Duration) for i := 1; i <= config.nconn; i++ { go get(i, uri, serverAddr, rawAddr, cipher, done) } // collect request finish time reqTime := make([]int64, config.nconn*config.nreq) reqDone := 0 for i := 1; i <= config.nconn; i++ { rt := <-done for _, t := range rt { reqTime[reqDone] = int64(t) reqDone++ } } fmt.Println("number of total requests:", config.nconn*config.nreq) fmt.Println("number of finished requests:", reqDone) if reqDone == 0 { return } // calculate average an standard deviation reqTime = reqTime[:reqDone] var sum int64 for _, d := range reqTime { sum += d } avg := float64(sum) / float64(reqDone) varSum := float64(0) for _, d := range reqTime { di := math.Abs(float64(d) - avg) di *= di varSum += di } stddev := math.Sqrt(varSum / float64(reqDone)) fmt.Println("\naverage time per request:", time.Duration(avg)) fmt.Println("standard deviation:", time.Duration(stddev)) }
func parseServerConfig(config *ss.Config) { hasPort := func(s string) bool { _, port, err := net.SplitHostPort(s) if err != nil { return false } return port != "" } if len(config.ServerPassword) == 0 { method := config.Method if config.Auth { method += "-ota" } // only one encryption table cipher, err := ss.NewCipher(method, config.Password) if err != nil { log.Fatal("Failed generating ciphers:", err) } srvPort := strconv.Itoa(config.ServerPort) srvArr := config.GetServerArray() n := len(srvArr) servers.srvCipher = make([]*ServerCipher, n) for i, s := range srvArr { if hasPort(s) { log.Println("ignore server_port option for server", s) servers.srvCipher[i] = &ServerCipher{s, cipher} } else { servers.srvCipher[i] = &ServerCipher{net.JoinHostPort(s, srvPort), cipher} } } } else { // multiple servers n := len(config.ServerPassword) servers.srvCipher = make([]*ServerCipher, n) cipherCache := make(map[string]*ss.Cipher) i := 0 for _, serverInfo := range config.ServerPassword { if len(serverInfo) < 2 || len(serverInfo) > 3 { log.Fatalf("server %v syntax error\n", serverInfo) } server := serverInfo[0] passwd := serverInfo[1] encmethod := "" if len(serverInfo) == 3 { encmethod = serverInfo[2] } if !hasPort(server) { log.Fatalf("no port for server %s\n", server) } // Using "|" as delimiter is safe here, since no encryption // method contains it in the name. cacheKey := encmethod + "|" + passwd cipher, ok := cipherCache[cacheKey] if !ok { var err error cipher, err = ss.NewCipher(encmethod, passwd) if err != nil { log.Fatal("Failed generating ciphers:", err) } cipherCache[cacheKey] = cipher } servers.srvCipher[i] = &ServerCipher{server, cipher} i++ } } servers.failCnt = make([]int, len(servers.srvCipher)) for _, se := range servers.srvCipher { log.Println("available remote server", se.server) } return }