diff --git a/Admin/Heartbeat.cs b/Admin/Heartbeat.cs index c4356087..3835d813 100644 --- a/Admin/Heartbeat.cs +++ b/Admin/Heartbeat.cs @@ -14,7 +14,7 @@ namespace IW4MAdmin public void Send() { - String URI = String.Format("http://raidmax.org/IW4M/Admin/heartbeat.php?address={0}&name={1}&map={2}&players={3}&version={4}", Instance.getPort().ToString(), Instance.getName(), Instance.getMap(), Instance.statusPlayers.Count.ToString() + '/' + Instance.getMaxClients().ToString(), IW4MAdmin.Program.Version.ToString()); + String URI = String.Format("http://raidmax.org/IW4M/Admin/heartbeat.php?address={0}&name={1}&map={2}&players={3}&version={4}", Instance.getPort().ToString(), Instance.getName(), Instance.getMap(), Instance.getClientNum() + '/' + Instance.getMaxClients().ToString(), IW4MAdmin.Program.Version.ToString()); Handle.Request(URI); } diff --git a/Admin/IW4M ADMIN.csproj b/Admin/IW4M ADMIN.csproj index 07aee0cf..5ec7f622 100644 --- a/Admin/IW4M ADMIN.csproj +++ b/Admin/IW4M ADMIN.csproj @@ -102,6 +102,7 @@ + diff --git a/Admin/IW4_GameStructs.cs b/Admin/IW4_GameStructs.cs index b1e1c3ed..13046338 100644 --- a/Admin/IW4_GameStructs.cs +++ b/Admin/IW4_GameStructs.cs @@ -104,8 +104,6 @@ namespace IW4MAdmin public int max; } - - class Helpers { public static String NET_AdrToString(netadr_t a) @@ -122,5 +120,4 @@ namespace IW4MAdmin return (T)Marshal.PtrToStructure(new IntPtr(b), typeof(T)); } } - } diff --git a/Admin/Main.cs b/Admin/Main.cs index 042f8d7c..83035295 100644 --- a/Admin/Main.cs +++ b/Admin/Main.cs @@ -3,20 +3,13 @@ using System; using System.Collections.Generic; using System.Text; using System.Threading; -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Net; namespace IW4MAdmin { class Program { - static String IP; - static int Port; - static String RCON; - static public double Version = 0.9; + static public double Version = 0.91; static public double latestVersion; - static public List Servers; static public bool usingMemory = true; static void Main(string[] args) @@ -30,12 +23,9 @@ namespace IW4MAdmin else Console.WriteLine(" Version " + Version + " (unable to retrieve latest)"); Console.WriteLine("====================================================="); - - List viableServers = getServers(); - +#if DEBUG if (viableServers.Count < 1) viableServers = checkConfig(); // fall back to config - Servers = viableServers; foreach (Server IW4M in viableServers) @@ -45,17 +35,16 @@ namespace IW4MAdmin Thread monitorThread = new Thread(new ThreadStart(SV.Monitor)); monitorThread.Start(); } +#endif + IW4MAdmin.Manager IW4MAdmin = new IW4MAdmin.Manager(); + IW4MAdmin.Init(); - IW4MAdmin_Web.WebFront WebStuff = new IW4MAdmin_Web.WebFront(); - - Thread webFrontThread = new Thread( new ThreadStart(WebStuff.Init)); - webFrontThread.Start(); - - Utilities.Wait(3); Console.WriteLine("IW4M Now Initialized! Visit http://127.0.0.1:1624 for server overview."); - - } + IW4MAdmin_Web.WebFront frontEnd = new IW4MAdmin_Web.WebFront(); + frontEnd.Init(); + } +#if DEBUG static void setupConfig() { bool validPort = false; @@ -77,6 +66,7 @@ namespace IW4MAdmin file Config = new file("config\\servers.cfg", true); Console.WriteLine("Great! Let's go ahead and start 'er up."); } +#endif static String checkUpdate() { @@ -84,6 +74,7 @@ namespace IW4MAdmin return Ver.Read(); } +#if DEBUG static List checkConfig() { @@ -92,7 +83,6 @@ namespace IW4MAdmin List Servers = new List(); Config.Close(); - if (SV_CONF == null || SV_CONF.Length < 1 || SV_CONF[0] == String.Empty) { setupConfig(); // get our first time server @@ -116,40 +106,8 @@ namespace IW4MAdmin Servers.Add(new Server(server_line[0], newPort, server_line[2],0)); } } - return Servers; } - - [DllImport("kernel32.dll")] - public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); - - [DllImport("kernel32.dll")] - public static extern bool ReadProcessMemory(int hProcess, - int lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead); - - static List getServers() - { - List Servers = new List(); - foreach ( Process P in Process.GetProcessesByName("iw4m")) - { - IntPtr Handle = OpenProcess(0x0010, false, P.Id); - int numberRead = 0; - Byte[] dediStuff = new Byte[1]; - ReadProcessMemory((int)Handle, 0x5DEC04, dediStuff, 1, ref numberRead); - - if (dediStuff[0] == 0) - { - Console.WriteLine("Viable IW4M Instance found with PID #" + P.Id); - - dvar net_ip = Utilities.getDvar(0x64A1DF8, (int)Handle); - dvar net_port = Utilities.getDvar(0x64A3004, (int)Handle); - dvar rcon_password = Utilities.getDvar(0x111FF634, (int)Handle); - - Servers.Add(new Server(Dns.GetHostAddresses(net_ip.current)[1].ToString(), Convert.ToInt32(net_port.current), rcon_password.current, (int)Handle)); - } - } - return Servers; - - } +#endif } } diff --git a/Admin/Manager.cs b/Admin/Manager.cs new file mode 100644 index 00000000..b1d28081 --- /dev/null +++ b/Admin/Manager.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Net; +using System.Threading; + +namespace IW4MAdmin +{ + class Manager + { + private List Servers; + private SortedDictionary ThreadList; + private List activePIDs; + + public Manager() + { + ThreadList = new SortedDictionary(); + } + + public void Init() + { + activePIDs = getCurrentIW4MProcesses(); + Servers = loadServers(); + + foreach (Server S in Servers) + { + Server IW4MServer = S; + Thread IW4MServerThread = new Thread(IW4MServer.Monitor); + ThreadList.Add(IW4MServer.pID(), IW4MServerThread); + IW4MServerThread.Start(); + } + + while (true) + { + lock (Servers) + { + foreach (Server S in Servers) + { + if (S == null) + continue; + + if (!isIW4MStillRunning(S.pID())) + { + Thread Defunct = ThreadList[S.pID()]; + if (Defunct != null) + { + Defunct.Abort(); + ThreadList[S.pID()] = null; + } + activePIDs.Remove(S.pID()); + } + } + } + scanForNewServers(); + Utilities.Wait(5); + } + } + + private void scanForNewServers() + { + List newProcesses = getCurrentIW4MProcesses(); + foreach (int pID in activePIDs) + { + bool newProcess = true; + foreach (int I in newProcesses) + { + if (I == pID) + newProcess = false; + } + + if (newProcess) + { + Server S = loadIndividualServer(pID); + Servers.Add(S); + Thread IW4MServerThread = new Thread(S.Monitor); + ThreadList.Add(pID, IW4MServerThread); + + IW4MServerThread.Start(); + } + } + + } + + private bool isIW4MStillRunning(int pID) + { + if (pID > 0) + { + Process P = Process.GetProcessById(pID); + if (P.ProcessName.Length == 0) + { + return false; + Console.WriteLine("Server with PID #" + pID + " doesn't seem to be running anymore"); + } + return true; + } + return false; + } + + [DllImport("kernel32.dll")] + public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); + + [DllImport("kernel32.dll")] + public static extern bool ReadProcessMemory(int hProcess, int lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead); + + private List getCurrentIW4MProcesses() + { + List PIDs = new List(); + foreach (Process P in Process.GetProcessesByName("iw4m")) + { + IntPtr Handle = OpenProcess(0x10, false, P.Id); + Byte[] isClient = new Byte[1]; + int numberRead = 0; + ReadProcessMemory((int)Handle, 0x5DEC04, isClient, 1, ref numberRead); + + if (isClient[0] == 0) + PIDs.Add(P.Id); + } + + return PIDs; + } + + private List loadServers() + { + List activeServers = new List(); + foreach (int pID in activePIDs) + { + Server S = loadIndividualServer(pID); + if (S != null) + activeServers.Add(S); + } + return activeServers; + } + + private Server loadIndividualServer(int pID) + { + if (pID > 0) + { + IntPtr Handle = OpenProcess(0x10, false, pID); + if (Handle != null) + { + dvar net_ip = Utilities.getDvar(0x64A1DF8, (int)Handle); + dvar net_port = Utilities.getDvar(0x64A3004, (int)Handle); + // unfortunately this needs to be updated for every iw4m build :/ + dvar rcon_password = Utilities.getDvar(0x1120CC3C, (int)Handle); + + return new Server(Dns.GetHostAddresses(net_ip.current)[1].ToString(), Convert.ToInt32(net_port.current), rcon_password.current, (int)Handle, pID); + } + + return null; + } + return null; + } + } +} diff --git a/Admin/Server.cs b/Admin/Server.cs index 047f953e..d14cf329 100644 --- a/Admin/Server.cs +++ b/Admin/Server.cs @@ -1,11 +1,9 @@ -//#define USINGMEMORY -using System; +using System; using System.Collections.Generic; using System.Collections; using System.Text; -using System.Threading; //SLEEP +using System.Threading; using System.IO; -using System.Diagnostics; using System.Runtime.InteropServices; @@ -15,8 +13,9 @@ namespace IW4MAdmin { const int FLOOD_TIMEOUT = 300; - public Server(string address, int port, string password, int H) + public Server(string address, int port, string password, int H, int PID) { + this.PID = PID; Handle = H; IP = address; Port = port; @@ -114,6 +113,11 @@ namespace IW4MAdmin return Bans; } + public int pID() + { + return this.PID; + } + public void getAliases(List returnPlayers, Player Origin) { if (Origin == null) @@ -558,7 +562,7 @@ namespace IW4MAdmin Utilities.Wait(10); return; } -#if DEBUG == false +#if DEBUG //Thread to handle polling server for IP's Thread statusUpdate = new Thread(new ThreadStart(pollServer)); statusUpdate.Start(); @@ -583,8 +587,6 @@ namespace IW4MAdmin while (isRunning) { - - #if DEBUG == false try #endif @@ -622,7 +624,7 @@ namespace IW4MAdmin } } -#if DEBUG +#if DEBUG == false if ((DateTime.Now - lastPoll).Milliseconds > 750) { int numberRead = 0; @@ -634,6 +636,8 @@ namespace IW4MAdmin ReadProcessMemory((int)Handle, 0x31D9390 + (buff.Length)*(i), buff, buff.Length, ref numberRead); // svs_clients start + current client client_s eachClient = (client_s)Helpers.ReadStruct(buff); + if (eachClient.isBot == 1) + continue; if (eachClient.state == 0) removePlayer(i); @@ -707,7 +711,7 @@ namespace IW4MAdmin RCONQueue.Abort(); eventQueue.Abort(); } - +#if DEBUG private void pollServer() { int timesFailed = 0; @@ -779,6 +783,7 @@ namespace IW4MAdmin Utilities.Wait(15); } } +#endif //Vital RCON commands to establish log file and server name. May need to cleanup in the future #if USINGMEMORY @@ -941,9 +946,7 @@ namespace IW4MAdmin logPath = Basepath + '\\' + "m2demo" + '\\' + log; else logPath = Basepath + '\\' + Mod + '\\' + log; -#if DEBUG - // logPath = "C:\\Users\\Michael\\Desktop\\test.txt"; -#endif + if (!File.Exists(logPath)) { Log.Write("Gamelog does not exist!", Log.Level.All); @@ -964,7 +967,7 @@ namespace IW4MAdmin lastPoll = DateTime.Now; #if DEBUG - /* System.Net.FtpWebRequest tmp = (System.Net.FtpWebRequest)System.Net.FtpWebRequest.Create("ftp://raidmax.org/logs/games_old.log"); + /* System.Net.FtpWebRequest tmp = (System.Net.FtpWebRequest)System.Net.FtpWebRequest.Create(""); tmp.Credentials = new System.Net.NetworkCredential("*", "*"); System.IO.Stream ftpStream = tmp.GetResponse().GetResponseStream(); String ftpLog = new StreamReader(ftpStream).ReadToEnd();*/ @@ -983,6 +986,8 @@ namespace IW4MAdmin //Process any server event public bool processEvent(Event E) { + +#if DEBUG /*if (E.Type == Event.GType.Connect) // this is anow handled by memory :) { if (E.Origin == null) @@ -990,6 +995,7 @@ namespace IW4MAdmin addPlayer(E.Origin); return true; }*/ +#endif if (E.Type == Event.GType.Connect) { @@ -1353,7 +1359,6 @@ namespace IW4MAdmin //END - //THIS IS BAD BECAUSE WE DON"T WANT EVERYONE TO HAVE ACCESS :/ public String getPassword() { return rcon_pass; @@ -1365,8 +1370,7 @@ namespace IW4MAdmin Macros.Add("WISDOM", Wisdom()); Macros.Add("TOTALPLAYERS", clientDB.totalPlayers()); Macros.Add("TOTALKILLS", totalKills); - Macros.Add("VERSION", IW4MAdmin.Program.Version); - + Macros.Add("VERSION", IW4MAdmin.Program.Version); } private void initMaps() @@ -1507,7 +1511,6 @@ namespace IW4MAdmin public List chatHistory; public Queue playerHistory; - //Info private String IP; private int Port; @@ -1527,13 +1530,12 @@ namespace IW4MAdmin private Moserware.TrueSkill Skills; private DateTime lastWebChat; private int Handle; - + private int PID; //Will probably move this later public Dictionary statusPlayers; public bool isRunning; private DateTime lastPoll; - //Log stuff private String Basepath; diff --git a/Admin/WebFront.cs b/Admin/WebFront.cs index 70bc4fee..990856f4 100644 --- a/Admin/WebFront.cs +++ b/Admin/WebFront.cs @@ -350,7 +350,12 @@ namespace IW4MAdmin_Web forumID = forumID - 76561197960265728; } - buffer.AppendFormat("{0}{1}{2}{3}{4}{5}{6} ago{8}", Player.getName(), str, IPs, Rating, IW4MAdmin.Utilities.nameHTMLFormatted(Player.getLevel()), Player.getConnections(), Player.getLastConnection(), forumID, Player.getName(), "/0/" + Player.getDBID() + "/userip/?player"); + String Screenshot = String.Empty; + + if (logged) + Screenshot = String.Format("
", forumID, Player.getName()); + + buffer.AppendFormat("{0}{10}{1}{2}{3}{4}{5}{6} ago{8}", Player.getName(), str, IPs, Rating, IW4MAdmin.Utilities.nameHTMLFormatted(Player.getLevel()), Player.getConnections(), Player.getLastConnection(), forumID, Player.getName(), "/0/" + Player.getDBID() + "/userip/?player", Screenshot); buffer.Append(""); } diff --git a/Admin/webfront/header.html b/Admin/webfront/header.html index f69df801..182f5853 100644 --- a/Admin/webfront/header.html +++ b/Admin/webfront/header.html @@ -11,7 +11,7 @@ - +