예제 #1
0
파일: server.go 프로젝트: vzex/dog-tunnel
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())
}
예제 #2
0
파일: server.go 프로젝트: vzex/dog-tunnel
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
		}
	}
}
예제 #3
0
파일: admin.go 프로젝트: vzex/dog-tunnel
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
}
예제 #4
0
파일: server.go 프로젝트: vzex/dog-tunnel
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() {
		})
	}
}