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(); }
/// <summary> /// Loads the outgoing server connections from the App.Config file. /// </summary> private void LoadOutgoingConnections() { ConnectionConfigSection section = null; try { section = (ConnectionConfigSection)ConfigurationManager.GetSection("OutgoingConnections"); } catch (Exception e) { Log1.Logger("Server").Fatal("Error loading config file section 'OutgoingConnections'. " + e.Message); return; } if (ConfigHelper.GetStringConfig("DatabaseConnectivity", "TRUE").ToLower() != "false") { DB.Instance.AddServerGroupSessionConnection("Default", ConfigurationManager.ConnectionStrings["SessionDataConnectionString"].ConnectionString); } OutboundServerUpdateInterval = section == null? int.MaxValue : section.UpdateIntervalSecs; GameServerInfoGroup group = null; if(section != null) { foreach (GroupElement g in section.Groups) { group = new GameServerInfoGroup(); group.SharedHiveKey = g.SharedHiveKey; group.ID = g.ID; // DB session, if exists if (g.SessionDataConnectionString.Length > 0) { DB.Instance.AddServerGroupSessionConnection(group.ID, g.SessionDataConnectionString); } else { DB.Instance.AddServerGroupSessionConnection(group.ID, ConfigurationManager.ConnectionStrings["SessionDataConnectionString"].ConnectionString); } string cm = g.ConnectMode.ToLower(); switch (cm) { case "roundrobin": group.ConnectMode = OutgoingServerConnectMethod.RoundRobin; break; case "random": group.ConnectMode = OutgoingServerConnectMethod.Random; break; default: group.ConnectMode = OutgoingServerConnectMethod.All; break; } foreach (ConnectionElement con in g.ConnectionItems) { try { GameServerInfo<OutboundServerConnection> gsi = new GameServerInfo<OutboundServerConnection>(); gsi.HostName = con.Address; gsi.Name = con.ConnectionName; gsi.ServiceID = con.ServiceID; if (con.SharedHiveKey.Length < 1) { gsi.SharedHiveKey = g.SharedHiveKey; } else { gsi.SharedHiveKey = con.SharedHiveKey; } string ip = con.Address; try { IPHostEntry iphe = Dns.GetHostEntry(ip); // 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 = con.Port; gsi.IsOnline = false; gsi.LastUpdate = DateTime.UtcNow; if (group.OutboundServers.Exists(xcon => xcon.UniqueID == gsi.UniqueID)) { Log1.Logger("Server").Error("Not adding outbound server [" + gsi.Name + "] as it's destination endpoing [" + gsi.UniqueID + "] matches an existing connection."); continue; } gsi.ServerGroup = group.ID; group.OutboundServers.Add(gsi); } finally { } } } if (group != null) { if (group.ConnectMode == OutgoingServerConnectMethod.Random || group.ConnectMode == OutgoingServerConnectMethod.RoundRobin) { // these two connect methods always start with a random index in the list. this helps a little in balancing the load across many instances of servers, in lieu of a proper load balancer. group.CurConnectionIndex = m_Random.Next(0, group.OutboundServers.Count); } OutboundServerGroups.Groups.Remove(group.ID); OutboundServerGroups.Groups.Add(group.ID, group); } } }