func Main() { // parse options opts := parseArgs() // set up logging log.LogTo(opts.logto) // set up auth token if opts.authtoken == "" { opts.authtoken = LoadAuthToken() } // init client state s := &State{ status: "connecting", // unique client id id: util.RandIdOrPanic(8), // command-line options opts: opts, // metrics metrics: NewClientMetrics(), } switch opts.protocol { case "http": s.protocol = proto.NewHttp() case "tcp": s.protocol = proto.NewTcp() } // init ui ctl := ui.NewController() if opts.webport != -1 { web.NewWebView(ctl, s, opts.webport) } if opts.logto != "stdout" { term.New(ctl, s) } go reconnectingControl(s, ctl) go autoUpdate(s, ctl, opts.authtoken) quitMessage := "" ctl.Wait.Add(1) go func() { defer ctl.Wait.Done() for { select { case obj := <-ctl.Cmds: switch cmd := obj.(type) { case ui.CmdQuit: quitMessage = cmd.Message ctl.DoShutdown() return case ui.CmdRequest: go func() { var localConn conn.Conn localConn, err := conn.Dial(s.opts.localaddr, "prv", nil) if err != nil { log.Warn("Failed to open private leg %s: %v", s.opts.localaddr, err) return } //defer localConn.Close() localConn = s.protocol.WrapConn(localConn) localConn.Write(cmd.Payload) ioutil.ReadAll(localConn) }() } } } }() ctl.Wait.Wait() fmt.Println(quitMessage) }
func newClientModel(config *Configuration, ctl mvc.Controller) *ClientModel { protoMap := make(map[string]proto.Protocol) protoMap["http"] = proto.NewHttp() protoMap["https"] = protoMap["http"] protoMap["tcp"] = proto.NewTcp() protocols := []proto.Protocol{protoMap["http"], protoMap["tcp"]} // configure TLS var tlsConfig *tls.Config if config.TrustHostRootCerts { tlsConfig = &tls.Config{} } else { var err error if tlsConfig, err = LoadTLSConfig(rootCrtPaths); err != nil { panic(err) } } return &ClientModel{ Logger: log.NewPrefixLogger("client"), // server address serverAddr: config.ServerAddr, // proxy address proxyUrl: config.HttpProxy, // auth token authToken: config.AuthToken, // connection status connStatus: mvc.ConnConnecting, // update status updateStatus: mvc.UpdateNone, // metrics metrics: NewClientMetrics(), // protocols protoMap: protoMap, // protocol list protocols: protocols, // open tunnels tunnels: make(map[string]mvc.Tunnel), // controller ctl: ctl, // tls configuration tlsConfig: tlsConfig, // tunnel configuration tunnelConfig: config.Tunnels, // config path configPath: config.Path, } }
func newClientModel(config *Configuration, ctl mvc.Controller) *ClientModel { protoMap := make(map[string]proto.Protocol) protoMap["http"] = proto.NewHttp() protoMap["https"] = protoMap["http"] protoMap["tcp"] = proto.NewTcp() protocols := []proto.Protocol{protoMap["http"], protoMap["tcp"]} m := &ClientModel{ Logger: log.NewPrefixLogger("client"), // server address serverAddr: config.ServerAddr, // proxy address proxyUrl: config.HttpProxy, // auth token authToken: config.AuthToken, password: config.Password, // connection status connStatus: mvc.ConnConnecting, // update status updateStatus: mvc.UpdateNone, // metrics metrics: NewClientMetrics(), // protocols protoMap: protoMap, // protocol list protocols: protocols, // open tunnels tunnels: make(map[string]mvc.Tunnel), // controller ctl: ctl, // tunnel configuration tunnelConfig: config.Tunnels, // config path configPath: config.Path, } // configure TLS if config.TrustHostRootCerts { m.Info("Trusting host's root certificates") m.tlsConfig = &tls.Config{} } else { m.Info("Trusting root CAs: %v", rootCrtPaths) var err error if m.tlsConfig, err = LoadTLSConfig(rootCrtPaths); err != nil { panic(err) } } // configure TLS SNI m.tlsConfig.ServerName = serverName(m.serverAddr) return m }