Esempio n. 1
0
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))
}
Esempio n. 2
0
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() {
		})
	}
}