func (sc *Client) Run(index int, specPipe string) { var pipe net.Conn if index >= 0 { pipe = sc.pipes[index] } else { pipe = sc.specPipes[specPipe] } if pipe == nil { return } go func() { callback := func(conn net.Conn, sessionId, action, content string) { if sc != nil { sc.OnTunnelRecv(conn, sessionId, action, content) } } common.Read(pipe, callback) log.Println("client end read", index) if index >= 0 { delete(sc.pipes, index) if clientType == 1 { if len(sc.pipes) == 0 { if remoteConn != nil { remoteConn.Close() } } } } else { delete(sc.specPipes, specPipe) } }() }
func handleClient(conn net.Conn) { common.Conn2ClientInfo[conn] = &common.ClientInfo{Conn: conn, ClientMap: make(map[net.Conn]*common.Session), Id2Session: make(map[string]*common.Session), IsServer: false, Quit: make(chan bool), ResponseTime: time.Now().Unix()} log.Println("client linked success", conn.RemoteAddr().String()) common.Conn2ClientInfo[conn].Loop() common.Read(conn, handleResponse) client, bHave := common.Conn2ClientInfo[conn] if bHave { close(client.Quit) if client.IsServer { for conn, session := range client.ClientMap { conn.Close() common.RmId(client.ServerName, session.Id) } delete(common.ServerName2Conn, client.ServerName) log.Println("unregister service Name", client.ServerName) if bUseDB { user, _ := auth.GetUser(client.UserName) if user != nil { user.OnLogout() } } } else { common.GetServerInfoByConn(conn, func(server *common.ClientInfo) { id := server.DelClient(conn) log.Println("send quit") common.Write(server.Conn, id, "clientquit", "") }, func() {}) } delete(common.Conn2ClientInfo, conn) } conn.Close() log.Println("client disconnected", conn.RemoteAddr().String()) }
func main() { flag.Parse() checkDns = make(chan *dnsQueryReq) checkDnsRes = make(chan *dnsQueryBack) go dnsLoop() if *bShowVersion { fmt.Printf("%.2f\n", common.Version) return } if !*bVerbose { log.SetOutput(ioutil.Discard) } if *dataShards < 0 || *dataShards >= 128 { println("-ds should in [0-127]") return } if *parityShards < 0 || *parityShards >= 128 { println("-ds should in [0-127]") return } if *serveName == "" && *linkName == "" { println("you must assign reg or link") return } if *serveName != "" && *linkName != "" { println("you must assign reg or link, not both of them") return } if *localAddr == "" { println("you must assign the local addr") return } if *serveName != "" { clientType = 0 } else { clientType = 1 } if *bEncrypt { if clientType != 1 { println("only link size need encrypt") return } } go func() { c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt, syscall.SIGTERM) n := 0 for { <-c log.Println("received signal,shutdown") bForceQuit = true if remoteConn != nil { remoteConn.Close() } n++ if n > 5 { log.Println("force shutdown") os.Exit(-1) } } }() loop := func() bool { if bForceQuit { return true } g_ClientMap = make(map[string]*Client) g_ClientMapKey = make(map[string]*cipher.Block) g_Id2UDPSession = make(map[string]*UDPMakeSession) //var err error if *bUseSSL { _remoteConn, err := tls.Dial("tcp", *serverAddr, &tls.Config{InsecureSkipVerify: true}) if err != nil { println("connect remote err:" + err.Error()) return false } remoteConn = net.Conn(_remoteConn) } else { _remoteConn, err := net.DialTimeout("tcp", *serverAddr, 10*time.Second) if err != nil { println("connect remote err:" + err.Error()) return false } remoteConn = _remoteConn } println("connect to server succeed") go connect() q := make(chan bool) go func() { c := time.NewTicker(time.Second * 10) out: for { select { case <-c.C: if remoteConn != nil { common.Write(remoteConn, "-1", "ping", "") } case <-q: break out } } c.Stop() }() common.Read(remoteConn, handleResponse) q <- true for clientId, client := range g_ClientMap { log.Println("client shutdown", clientId) client.Quit() } for _, session := range g_Id2UDPSession { if session.engine != nil { session.engine.Fail() } } if remoteConn != nil { remoteConn.Close() } if bForceQuit { return true } return false } if clientType == 0 { for { if loop() { break } time.Sleep(10 * time.Second) } } else { loop() } log.Println("service shutdown") }