/// <summary> /// Looks at all the attached content servers and determines which one has the lowest population, i.e. the one the player should play on. /// Returns null if no suitable servers are found (i.e. all available servers are at capacity). /// </summary> /// <returns></returns> public GameServerInfo <OutboundServerConnection> GetLowPopGameServer() { GameServerInfo <OutboundServerConnection> gsi = null; // Grab the game server with the least number of players GameServerInfoGroup g = OutboundServerGroups.Groups["Default"]; if (g == null) { return(null); } List <string> addresses; List <string> ids; List <int> ports; List <int> curConnections; List <int> maxConnections; if (!DB.Instance.Server_GetRegistrations("content", out addresses, out ids, out ports, out curConnections, out maxConnections)) { gsi = g.NextConnection(); } else { int low = 0; float lowRatio = 1f; for (int i = 0; i < ids.Count; i++) { float ratio = (float)curConnections[i] / (float)maxConnections[i]; if (ratio < lowRatio) { lowRatio = ratio; low = i; } } if (lowRatio >= 1) { // All servers are at capacity return(null); } // See if we're connected to that server //gsi = GetOutboundServerByServerUserID(ids[low]); //if (gsi == null || !gsi.IsOnline) { // Create a temp object with latest info from DB gsi = new GameServerInfo <OutboundServerConnection>(); gsi.Name = ids[low]; gsi.UserID = ids[low]; gsi.IP = addresses[low]; gsi.Port = ports[low]; gsi.CurUsers = curConnections[low]; gsi.MaxUsers = maxConnections[low]; } } return(gsi); }
/// <summary> /// Gets called when a player requests to be handed off to a particular Hive. This Base implementation simply returns the "Next" server /// in the indicated server group's connection list, using the group's ConnectMethod to determine the algorithm by which the "Next" /// connection is chosen (I.e. random or roundrobin). This implementation only considers currently connected servers as candidates. /// </summary> /// <param name="serverGroup"></param> /// <returns></returns> protected virtual GameServerInfo <OutboundServerConnection> GetTargetServerForClusterHandoff(string serverGroup) { GameServerInfoGroup g = MyServer.OutboundServerGroups[serverGroup]; if (g == null) { return(null); } return(g.NextConnection());; }
public override void StartServer() { base.StartServer(); // FORMAT: serverNAME|state|desc string[] services = WispServices.GetInstalledServices(); GameServerInfoGroup gr = new GameServerInfoGroup(); OutboundServerUpdateInterval = 10; gr.ID = "Default"; OutboundServerGroups.Groups.Clear(); OutboundServerGroups.Groups.Add(gr.ID, gr); for (int i = 0; i < services.Length; i++) { string[] parts = services[i].Split(char.Parse("|")); if (parts.Length < 3) { continue; } string name = parts[0]; if (name.ToLower() == "zeus") { continue; // don't connect to self } string state = parts[1]; string desc = parts[2]; object val = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\" + name, "ImagePath", ""); if (val == null) { Log1.Logger("Server").Error("Wisp registry claims that service [" + name + "] is installed, but the Windows registry does not agree."); continue; } string exePath = val.ToString(); string directory = Path.GetDirectoryName(exePath); if (!Directory.Exists(directory)) { Log1.Logger("Server").Error("Windows registry claims that Wisp service [" + name + "] is installed at [" + directory + "] but that directory was not found."); continue; } string targetConfig = exePath + ".config"; if (!File.Exists(targetConfig)) { Log1.Logger("Server").Error("Unable to locate config file [" + targetConfig + "] for service [" + name + "] and so the connection port can't be determnined."); continue; } int port = 0; try { string configContents = File.ReadAllText(targetConfig); int loc = configContents.IndexOf("ListenOnPort"); if (loc < 0) { Log1.Logger("Server").Error("Failed to find 'ListenOnPort' directive in config file [" + targetConfig + "] for service [" + name + "]. Unable to determine port for that service."); continue; } int valLoc = configContents.IndexOf("\"", loc + 13); int valEndLoc = configContents.IndexOf("\"", valLoc + 1); string sport = configContents.Substring(valLoc + 1, valEndLoc - valLoc - 1); if (!int.TryParse(sport, out port) || port <= 0) { Log1.Logger("Server").Error("'ListenOnPort' directive in config file [" + targetConfig + "] for service [" + name + "] was in the wrong format - [" + sport + "]. Unable to determine port for that service."); continue; } } catch (Exception e) { Log1.Logger("Server").Error("Failed to read config file [" + targetConfig + "] for service [" + name + "]. Unable to determine port for that service.", e); continue; } GameServerInfo <OutboundServerConnection> gsi = new GameServerInfo <OutboundServerConnection>(); gsi.HostName = "localhost"; gsi.Name = name; string ip = "localhost"; try { gsi.ServiceID = 7; IPHostEntry iphe = Dns.GetHostEntry("localhost"); // this call will delay the server from starting if it doesn't resolve fast enough. bool gotOne = false; foreach (IPAddress addy in iphe.AddressList) { if (addy.AddressFamily == AddressFamily.InterNetwork) { gotOne = true; ip = addy.ToString(); break; } } if (!gotOne) { Log1.Logger("Server.Network").Error("Could not resolve IP address for server " + gsi.Name + " (" + ip + ")"); continue; } } catch (Exception e) { Log1.Logger("Server.Network").Error("Error setting up outbound server connection. " + gsi.Name + " / " + gsi.HostName + " : " + e.Message, e); // try the next address in the config continue; } if (ip.Trim().Length < 1) { // try the next address in the config continue; } gsi.IP = ip; gsi.Port = port; gsi.IsOnline = false; gsi.LastUpdate = DateTime.UtcNow; if (gr.OutboundServers.Exists(con => con.UniqueID == gsi.UniqueID)) { continue; } gr.OutboundServers.Add(gsi); } StartOutboundServerUpdate(); }