// PipeThenClose copies data from src to dst, closes dst when done. func PipeThenClose(src, dst net.Conn, timeoutOpt int, flowData *flow.Info, port string) { defer dst.Close() buf := pipeBuf.Get() defer pipeBuf.Put(buf) for { if timeoutOpt == SET_TIMEOUT { SetReadTimeout(src) } n, err := src.Read(buf) // read may return EOF with n > 0 // should always process n > 0 bytes before handling error if n > 0 { if _, err = dst.Write(buf[0:n]); err != nil { Debug.Println("write:", err) break } } if err != nil { // Always "use of closed network connection", but no easy way to // identify this specific error. So just leave the error along for now. // More info here: https://code.google.com/p/go/issues/detail?id=4373 /* if bool(Debug) && err != io.EOF { Debug.Println("read:", err) } */ break } now := time.Now().Format("2006-01-02 15:04:05") if len(flowData.Usage[port]) == 0 { flowData.Usage[port] = []string{"0", now} } used, _ := strconv.ParseUint(flowData.Usage[port][0], 10, 64) used += uint64(n) flowData.Usage[port][0] = strconv.FormatUint(used, 10) flowData.Usage[port][1] = now if used%47 == 0 { flow.SaveConfig("flowInfo.json", flowData) } } }
func main() { log.SetOutput(os.Stdout) var cmdConfig ss.Config var printVer bool var core int flag.BoolVar(&printVer, "version", false, "print version") flag.StringVar(&configFile, "c", "config.json", "specify config file") flag.StringVar(&cmdConfig.Password, "k", "", "password") flag.IntVar(&cmdConfig.ServerPort, "p", 0, "server port") flag.IntVar(&cmdConfig.Timeout, "t", 60, "connection timeout (in seconds)") flag.StringVar(&cmdConfig.Method, "m", "", "encryption method, default: aes-256-cfb") flag.IntVar(&core, "core", 0, "maximum number of CPU cores to use, default is determinied by Go runtime") flag.BoolVar((*bool)(&debug), "d", false, "print debug message") flag.BoolVar(&udp, "u", false, "UDP Relay") flag.Parse() if printVer { ss.PrintVersion() os.Exit(0) } ss.SetDebug(debug) var err error config, err = ss.ParseConfig(configFile) if err != nil { if !os.IsNotExist(err) { fmt.Fprintf(os.Stderr, "error reading %s: %v\n", configFile, err) os.Exit(1) } config = &cmdConfig } else { ss.UpdateConfig(config, &cmdConfig) } if config.Method == "" { config.Method = "aes-128-cfb" } if err = ss.CheckCipherMethod(config.Method); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } if err = unifyPortPassword(config); err != nil { os.Exit(1) } if core > 0 { runtime.GOMAXPROCS(core) } if udp { ss.InitNAT() } //read from file flowData, err = flow.ParseConfig("flowInfo.json") if err != nil { now := time.Now().Format("2006-01-02 15:04:05") flowData = &flow.Info{now, map[string][]string{}} flow.SaveConfig("flowInfo.json", flowData) } for port, pass_limit := range config.PortPasswordLimit { go run(port, pass_limit[0], pass_limit[1]) if udp { go runUDP(port, pass_limit[0], pass_limit[1]) } } //url http.HandleFunc("/", status) //设置访问的路由 http.Handle("/css/", http.FileServer(http.Dir("static"))) http.Handle("/js/", http.FileServer(http.Dir("static"))) err = http.ListenAndServe(":9000", nil) //设置监听的端口 if err != nil { log.Fatal("ListenAndServe: ", err) } waitSignal() }