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 shutdown() { for conn, client := range common.Conn2ClientInfo { if !client.IsServer { log.Println("shutdown client", client.ServerName) common.Write(conn, "0", "showandquit", "server shutdown") } else { log.Println("unregister service Name", client.ServerName) if bUseDB { user, _ := auth.GetUser(client.UserName) if user != nil { user.OnLogout() } } //donnot showandquit,because client_server need to reconnect } } }
func _adminUserSetting(w http.ResponseWriter, r *http.Request) (result string, bSuccess bool) { action := r.FormValue("action") key := r.FormValue("user") if key == "" && action != "list" { result = "please spec user" bSuccess = false return } switch action { case "limit": n := r.FormValue("size") size, _ := strconv.Atoi(n) user, err := auth.GetUser(key) if err != nil { result = err.Error() bSuccess = false return } else { user.LimitDataSize = size err := auth.UpdateUser(key, user) if err == nil { bSuccess = true } else { result = err.Error() bSuccess = false } return } case "add": passwd := r.FormValue("passwd") if passwd == "" { result = "please spec passwd" bSuccess = false return } _usertype := auth.UserType_Normal usertype := r.FormValue("type") maxOnlineServerNum := auth.DefaultMaxOnlineServerNum maxSessionNum := auth.DefaultMaxSessionNum maxPipeNum := auth.DefaultMaxPipeNum maxSameIPServers := auth.DefaultMaxSameIPServers switch usertype { case "black": _usertype = auth.UserType_BlackList case "super": _usertype = auth.UserType_Super maxOnlineServerNum = 10 maxSessionNum = 10 maxPipeNum = 10 maxSameIPServers = 10 case "admin": _usertype = auth.UserType_Admin } user := &auth.User{UserName: key, Passwd: common.HashPasswd(common.Md5(passwd)), UserType: _usertype, LastLoginTime: 0, LastLogoutTime: 0, MaxOnlineServerNum: maxOnlineServerNum, MaxSessionNum: maxSessionNum, MaxPipeNum: maxPipeNum, MaxSameIPServers: maxSameIPServers, TodayCSModeData: 0, LimitDataSize: 0} key, err := auth.AddUser(key, user) if err != nil { result = err.Error() bSuccess = false return } else { result = key bSuccess = true return } case "list": limita := r.FormValue("limita") limitb := r.FormValue("limitb") if limita == "" || limitb == "" { result = "please limita and limitb" bSuccess = false return } arr := auth.GetUserNameList(limita, limitb) res, _ := json.Marshal(arr) result = string(res) bSuccess = true return case "get": user, err := auth.GetUser(key) if err != nil { result = err.Error() bSuccess = false return } else { if user == nil { result = "donnot have this user" bSuccess = false return } res, _ := json.Marshal(user) result = string(res) bSuccess = true return } case "del": bHave, err := auth.DelUser(key) if err != nil { result = err.Error() bSuccess = false return } else { if !bHave { result = "donnot have this user" } bSuccess = true return } case "key": _key := auth.GenUserKey(key) if _key == "" { result = "gen user key fail" bSuccess = false return } err := auth.UpdateUserKey(key, _key) if err == nil { result = _key bSuccess = true } else { result = err.Error() bSuccess = false } return case "set": _usertype := -1 maxOnlineServerNum := -1 maxSessionNum := -1 maxPipeNum := -1 maxSameIPServers := -1 pass := "" passwd := r.FormValue("passwd") if passwd != "" { pass = common.HashPasswd(common.Md5(passwd)) } usertype := r.FormValue("type") if usertype != "" { switch usertype { case "black": _usertype = auth.UserType_BlackList case "super": _usertype = auth.UserType_Super maxOnlineServerNum = 10 maxSessionNum = 10 maxPipeNum = 10 case "normal": _usertype = auth.UserType_Normal maxOnlineServerNum = auth.DefaultMaxOnlineServerNum maxSessionNum = auth.DefaultMaxSessionNum maxPipeNum = auth.DefaultMaxPipeNum maxSameIPServers = auth.DefaultMaxSameIPServers case "admin": _usertype = auth.UserType_Admin } } servern := r.FormValue("serven") if servern != "" { maxOnlineServerNum, _ = strconv.Atoi(servern) } sessionn := r.FormValue("sessionn") if sessionn != "" { maxSessionNum, _ = strconv.Atoi(sessionn) } pipen := r.FormValue("pipen") if pipen != "" { maxPipeNum, _ = strconv.Atoi(pipen) } ipn := r.FormValue("sameip") if ipn != "" { maxSameIPServers, _ = strconv.Atoi(ipn) } user, err := auth.GetUser(key) if err != nil { result = err.Error() bSuccess = false return } else { if _usertype != -1 { user.UserType = _usertype } if maxOnlineServerNum != -1 { user.MaxOnlineServerNum = maxOnlineServerNum } if maxSessionNum != -1 { user.MaxSessionNum = maxSessionNum } if maxPipeNum != -1 { user.MaxPipeNum = maxPipeNum } if maxSameIPServers != -1 { user.MaxSameIPServers = maxSameIPServers } if pass != "" { user.Passwd = pass } err := auth.UpdateUser(key, user) if err == nil { bSuccess = true } else { result = err.Error() bSuccess = false } return } default: result = "invalid action" bSuccess = false return } result = "" bSuccess = true return }
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() { }) } }