func connect() { if *pipeNum <= 0 { *pipeNum = 1 } clientInfo := common.ClientSetting{Version: common.Version, Delay: *delayTime, Mode: *clientMode, PipeNum: *pipeNum, AccessKey: *accessKey, ClientKey: *clientKey, AesKey: ""} if *bEncrypt { clientInfo.AesKey = string([]byte(fmt.Sprintf("asd4%d%d", int32(time.Now().Unix()), (rand.Intn(100000) + 100)))[:16]) log.Println("debug aeskey", clientInfo.AesKey) key, _ := aes.NewCipher([]byte(clientInfo.AesKey)) aesKey = &key } if *bLoadSettingFromFile { var setting fileSetting err := loadSettings(&setting) if err == nil { clientInfo.AccessKey = setting.Key } else { log.Println("load setting fail", err.Error()) } } else { if clientInfo.AccessKey != "" { var setting = fileSetting{Key: clientInfo.AccessKey} err := saveSettings(setting) if err != nil { log.Println("save setting error", err.Error()) } else { println("save setting ok, nexttime please use -f to replace -key") } } } if clientType == 0 { markName = *serveName clientInfo.ClientType = "reg" } else if clientType == 1 { markName = *linkName clientInfo.ClientType = "link" } else { println("no clienttype!") } clientInfo.Name = markName clientInfoStr, err := json.Marshal(clientInfo) if err != nil { println("encode args error") } log.Println("init client", string(clientInfoStr)) common.Write(remoteConn, "0", "init", string(clientInfoStr)) }
func handleResponse(conn net.Conn, id string, action string, content string) { //log.Println("got", id, action, content) common.GetClientInfoByConn(conn, func(client *common.ClientInfo) { client.ResponseTime = time.Now().Unix() }, func() { }) switch action { case "init": clientInfoStr := content var clientInfo common.ClientSetting err := json.Unmarshal([]byte(clientInfoStr), &clientInfo) if err != nil { log.Println("error decode clientinfo, kick out", conn.RemoteAddr().String()) common.Write(conn, "0", "showandquit", "server decode clientInfo error") return } if common.Version != clientInfo.Version { s_version := fmt.Sprintf("%.2f", common.Version) c_version := fmt.Sprintf("%.2f", clientInfo.Version) log.Println("version not eq", conn.RemoteAddr().String(), s_version, c_version) common.Write(conn, "0", "showandquit", "client version:"+c_version+" not eq with server:"+s_version) return } ServerName := clientInfo.Name if clientInfo.ClientType == "reg" { var user *auth.User if bUseDB { if clientInfo.AccessKey == "" { user, _ = auth.GetUser("test") } else { user, _ = auth.GetUserByKey(clientInfo.AccessKey) } } else { user = &auth.User{UserType: auth.UserType_Admin} } //fmt.Printf("%+v\n", user) if user == nil { common.Write(conn, "0", "showandquit", "invalid user accessKey:"+clientInfo.AccessKey+"!!!") return } if !user.CheckOnlineServiceNum() { common.Write(conn, "0", "showandquit", "online service num cannot overstep "+strconv.Itoa(user.MaxOnlineServerNum)) return } if !user.CheckIpLimit(conn.RemoteAddr().(*net.TCPAddr).IP.String()) { common.Write(conn, "0", "showandquit", "ip limit service num cannot overstep "+strconv.Itoa(user.MaxSameIPServers)) return } f := func() { common.ServerName2Conn[ServerName] = conn common.GetClientInfoByConn(conn, func(info *common.ClientInfo) { info.ServerName = ServerName info.IsServer = true info.Id2MakeSession = make(map[string]*common.UDPMakeSession) info.UserName = user.UserName info.ClientKey = clientInfo.ClientKey }, func() {}) log.Println("client reg service success", conn.RemoteAddr().String(), user.UserName, ServerName) common.Write(conn, "0", "show", "register service ok, user:"******"force unregister service Name", server.ServerName) if bUseDB { user, _ := auth.GetUser(server.UserName) if user != nil { user.OnLogout() } } delete(common.Conn2ClientInfo, _conn) common.Write(_conn, "0", "showandquit", "some one kick you out") _conn.Close() f() } else { common.Write(conn, "0", "showandretry", "already have the ServerName!") } }, f) } else if clientInfo.ClientType == "link" { if clientInfo.Mode < 0 || clientInfo.Mode > 2 { clientInfo.Mode = 0 } ServerName := clientInfo.Name bAuth := true common.GetClientInfoByName(ServerName, func(info *common.ClientInfo) { var user *auth.User if bUseDB { user, _ = auth.GetUser(info.UserName) } else { user = &auth.User{UserType: auth.UserType_Admin} } //fmt.Printf("%+v\n", user) if user == nil { common.Write(conn, "0", "showandquit", "invalid user:"******"!!!") bAuth = false return } if info.ClientKey != clientInfo.ClientKey { common.Write(conn, "0", "showandquit", "clientkey invalid!!!") bAuth = false return } if !user.CheckSessionNum(len(info.ClientMap)) { common.Write(conn, "0", "showandquit", "session numcannot overstep "+strconv.Itoa(len(info.ClientMap))) bAuth = false return } if !user.CheckPipeNum(clientInfo.PipeNum) { common.Write(conn, "0", "showandquit", "pipenum cannot overstep "+strconv.Itoa(user.MaxPipeNum)) bAuth = false return } }, func() { common.Write(conn, "0", "showandquit", "serverName invalid!!!") bAuth = false }) if !bAuth { return } common.GetClientInfoByConn(conn, func(client *common.ClientInfo) { client.ServerName = ServerName }, func() { }) common.GetClientInfoByName(ServerName, func(server *common.ClientInfo) { log.Println("client link service success", conn.RemoteAddr().String(), ServerName) server.AddClient(conn, clientInfo) }, func() { common.Write(conn, "0", "showandquit", "donnt have this service name") }) } case "tunnel_error": common.GetServerInfoByConn(conn, func(server *common.ClientInfo) { log.Println("<<=====tunnel_error", server.ServerName, conn.RemoteAddr().String()) session, bHave := server.Id2Session[id] if bHave { session.Status = "fail" common.Write(session.ClientA, "0", "showandquit", content) server.DelClient(session.ClientA) } }, func() { }) case "makeholefail": common.GetServerInfoByConn(conn, func(server *common.ClientInfo) { udpsession, bHave := server.Id2MakeSession[id] if bHave { log.Println("<<=====make hole fail", conn.RemoteAddr().String(), udpsession.ServerName, udpsession.SessionId, id) sessionId := udpsession.SessionId session, _bHave := server.Id2Session[sessionId] if _bHave { session.Status = "fail" session.MakeHoleResponseN++ session.MakeHoleHasFail = true if session.MakeHoleResponseN == session.Setting.PipeNum { if session.Method == "udp" { session.RestartSession(server.ServerName) } else if session.Method == "restart" { if session.Setting.Mode == 0 { tmp := session.ClientA session.ClientA = session.ClientB session.ClientB = tmp session.StartCSMode() } else { server.DelClient(session.ClientB) } } else { server.DelClient(session.ClientA) } } } udpsession.Remove(false) } }, func() { }) case "makeholeok": common.GetServerInfoByConn(conn, func(server *common.ClientInfo) { if content == "csmode" { session, _bHave := server.Id2Session[id] if _bHave { log.Println("<<=====make hole ok", conn.RemoteAddr().String(), server.ServerName, session.Id) session.Status = "ok" session.MakeHoleResponseN++ } } udpsession, bHave := server.Id2MakeSession[id] if bHave { log.Println("<<=====make hole ok", conn.RemoteAddr().String(), udpsession.ServerName, udpsession.SessionId, id) sessionId := udpsession.SessionId session, _bHave := server.Id2Session[sessionId] if _bHave { session.MakeHoleResponseN++ if session.MakeHoleResponseN == session.Setting.PipeNum { if !session.MakeHoleHasFail { session.Status = "ok" } } } udpsession.Remove(false) } }, func() { }) case "report_addrlist": common.GetServerInfoByConn(conn, func(server *common.ClientInfo) { udpsession, bHave := server.Id2MakeSession[id] //log.Println("test", udpsession, id, server.ServerName) if bHave { log.Println("<<===report addr list ok", conn.RemoteAddr().String(), udpsession.ServerName, udpsession.Id) udpsession.BeginMakeHole(1, content) } }, func() { }) case "success_bust_a": common.GetServerInfoByConn(conn, func(server *common.ClientInfo) { udpsession, bHave := server.Id2MakeSession[id] if bHave { log.Println("<<=====success_bust_a", conn.RemoteAddr().String(), udpsession.ServerName, udpsession.SessionId, id) udpsession.BeginMakeHole(2, content) } }, func() { }) // for c/s mode case "tunnel_close": common.GetServerInfoByConn(conn, func(server *common.ClientInfo) { session := server.GetSession(conn) if session != nil { common.Write(session.ClientB, session.Id+"-"+id, "csmode_s_tunnel_close", content) } else { println("no session") } }, func() { }) case "tunnel_open": common.GetServerInfoByConn(conn, func(server *common.ClientInfo) { session := server.GetSession(conn) if session != nil { common.Write(session.ClientB, session.Id+"-"+id, "csmode_s_tunnel_open", content) } else { println("no session") } }, func() { }) case "tunnel_msg_c": common.GetServerInfoByConn(conn, func(server *common.ClientInfo) { var user *auth.User if bUseDB { user, _ = auth.GetUser(server.UserName) } else { user = &auth.User{UserType: auth.UserType_Admin} } if user == nil { common.Write(conn, "0", "showandquit", "cannot get userinfo of this service "+server.UserName) return } if !user.UpdateCSMode(len(content)) { common.Write(conn, "0", "showandquit", "reach today's csmode data limit") return } session := server.GetSession(conn) if session != nil { common.Write(session.ClientB, session.Id+"-"+id, "csmode_msg_c", content) } else { println("no session") } }, func() { }) case "tunnel_msg_s": common.GetServerInfoByConn(conn, func(server *common.ClientInfo) { var user *auth.User if bUseDB { user, _ = auth.GetUser(server.UserName) } else { user = &auth.User{UserType: auth.UserType_Admin} } if user == nil { common.Write(conn, "0", "showandquit", "cannot get userinfo of this service"+server.UserName) return } if !user.UpdateCSMode(len(content)) { common.Write(conn, "0", "show", "reach today's csmode data limit") return } arr := strings.Split(id, "-") clientId := arr[0] session, bHave := server.Id2Session[clientId] if bHave { common.Write(session.ClientA, id, "csmode_msg_s", content) } else { println("no session") } }, func() { }) case "tunnel_close_s": common.GetServerInfoByConn(conn, func(server *common.ClientInfo) { arr := strings.Split(id, "-") clientId := arr[0] session, bHave := server.Id2Session[clientId] if bHave { common.Write(session.ClientA, id, "csmode_c_tunnel_close", content) } else { println("no session") } }, func() { }) } }